[MPlayer-dev-eng] [PATCH] mpegts

Dan Oscarsson Dan.Oscarsson at tieto.com
Sat Jan 9 17:16:13 CET 2010


Hi

A friend of mine is recording from DVB-T and gets a mpeg-ts file with
AAC for audio and h264 for video. It did not play very well in mplayer.
Looking at it I found that pts values for audio and video were not very
good and pts for video were out of order.

Playing with -correct-pts fixes the pts order when using -demuxer lavf
but only partially when using the normal demux_ts.c.
Audio pts were best using demux_ts.c compared to lavf demuxer.

Analysing quality of pts values for demux_ts.c I found that they were
bad due to using float instead of double for pts values. The attached
patch fixes that. Now pts values from demux_ts.c are very good.

The audio pts values in the demux stream packets from demux_ts.c are
very good. They are not when using lavf demuxer where the pts values on
demux stream packets do not match the data in the stream very well. I
have looked at the code but the pts handling in demux_ts.c and lavf
demuxer are very different and I have not found why they are so much
better when using demux_ts.c.

When using -correct-pts the pts order was corrected in lavf demuxer but
only partially with demux_ts.c, after a seek. From what I have found out
it looks like lavf demuxer after a seek have the first video pcket be
aligned on stream buffer start so that its pts value is defined, but
with demux_ts.c a seek often results in first packet not being on buffer
start so first packets gets pts value MP_NOPTS_VALUE. This results in
dec_video.c that the first packet is not added to reorder table.
This movie needed 4 values (h264 says 4 b-frames) to do correction but
when the first frame was of undefined pts, the correct pts code skipped
first frame and then only managed 3 values which results in some pts
values not being corrected.
The attached patch fixes this by allowing the MP_NOPTS_VALUE in pts
correction as it is less then other pts values and should do no harm,
from what I can see. At lest it works for the movies I have tested it
on. If you have a better idea of how to fix this, please do that
instead.

Regards,

   Dan

-------------- next part --------------
--- libmpdemux/demux_ts.c.org	2010-01-09 10:16:52.000000000 +0100
+++ libmpdemux/demux_ts.c	2010-01-09 10:19:35.000000000 +0100
@@ -97,7 +97,7 @@
 	unsigned char *start;
 	uint16_t payload_size;
 	es_stream_type_t type, subtype;
-	float pts, last_pts;
+	double pts, last_pts;
 	int pid;
 	char lang[4];
 	int last_cc;				// last cc code (-1 if first packet)
@@ -219,8 +219,8 @@
 typedef struct {
 	uint64_t size;
 	float duration;
-	float first_pts;
-	float last_pts;
+	double first_pts;
+	double last_pts;
 } TS_stream_info;
 
 typedef struct {
@@ -1255,7 +1255,7 @@
 					return -1;
 			}
 
-			pes_es->pts = (float) v / (float) sl->ts_resolution;
+			pes_es->pts = (double) v / (double) sl->ts_resolution;
 			mp_msg(MSGT_DEMUXER,MSGL_DBG2, "CTS: %d bits, value: %"PRIu64"/%d = %.3f\n", sl->ts_len, v, sl->ts_resolution, pes_es->pts);
 		}
 
@@ -1398,7 +1398,7 @@
 		pts |=  p[12]         <<  7 ;
 		pts |= (p[13] & 0xFE) >>  1 ;
 
-		es->pts = pts / 90000.0f;
+		es->pts = pts / (double)90000.0f;
 	}
 	else
 		es->pts = 0.0f;
@@ -3277,8 +3277,8 @@
 	{
 		if(sh_audio && !d_audio->eof && d_video->pts && d_audio->pts)
 		{
-			float a_pts=d_audio->pts;
-			a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
+			double a_pts=d_audio->pts;
+			a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(double)sh_audio->i_bps;
 			if(d_video->pts > a_pts)
 			{
 				skip_audio_frame(sh_audio);  // sync audio
-------------- next part --------------
--- libmpcodecs/dec_video.c.org	2010-01-09 10:10:37.000000000 +0100
+++ libmpcodecs/dec_video.c	2010-01-09 11:02:26.000000000 +0100
@@ -332,7 +332,16 @@
     unsigned int t2;
     double tt;
 
-    if (correct_pts && pts != MP_NOPTS_VALUE) {
+    //if (correct_pts && pts != MP_NOPTS_VALUE) {
+    // above test can result in one delay frame missed
+    // example: with demux_ts a seek in a h264 stream
+    // results in first frame after seek having MP_NOPTS_VALUE
+    // this results in only 3 frames gets reordered below
+    // instead of the 4 that is needed
+    // ny including MP_NOPTS_VALUE we may get one frame
+    // incorrectely sorted but we then get all following
+    // frames sorted ok (MP_NOPTS_VALUE is large negatve value)
+    if (correct_pts) {
 	int delay = get_current_video_decoder_lag(sh_video);
 	if (delay >= 0) {
 	    if (delay > sh_video->num_buffered_pts)


More information about the MPlayer-dev-eng mailing list