changeset 16883:1f45d7872c56

more precise seeking based on calculated average video bitrate; works quite well in case of a TS with only 1 video stream
author nicodvb
date Mon, 31 Oct 2005 23:38:32 +0000
parents dfbe8cd0e081
children 0168bf6042d6
files libmpdemux/demux_ts.c
diffstat 1 files changed, 49 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/libmpdemux/demux_ts.c	Mon Oct 31 23:37:41 2005 +0000
+++ b/libmpdemux/demux_ts.c	Mon Oct 31 23:38:32 2005 +0000
@@ -201,6 +201,13 @@
 } pmt_t;
 
 typedef struct {
+	uint64_t size;
+	float duration;
+	float first_pts;
+	float last_pts;
+} TS_stream_info;
+
+typedef struct {
 	MpegTSContext ts;
 	int last_pid;
 	av_fifo_t fifo[3];	//0 for audio, 1 for video, 2 for subs
@@ -208,8 +215,10 @@
 	pmt_t *pmt;
 	uint16_t pmt_cnt;
 	uint32_t prog;
+	uint32_t vbitrate;
 	int keep_broken;
 	char packet[TS_FEC_PACKET_SIZE];
+	TS_stream_info vstr, astr;
 } ts_priv_t;
 
 
@@ -849,7 +858,7 @@
 	if(!packet_size)
 	    return NULL;
 
-	priv = malloc(sizeof(ts_priv_t));
+	priv = calloc(1, sizeof(ts_priv_t));
 	if(priv == NULL)
 	{
 		mp_msg(MSGT_DEMUX, MSGL_FATAL, "DEMUX_OPEN_TS, couldn't allocate enough memory for ts->priv, exit\n");
@@ -2456,7 +2465,7 @@
 }
 
 
-static int fill_packet(demuxer_t *demuxer, demux_stream_t *ds, demux_packet_t **dp, int *dp_offset)
+static int fill_packet(demuxer_t *demuxer, demux_stream_t *ds, demux_packet_t **dp, int *dp_offset, TS_stream_info *si)
 {
 	int ret = 0;
 
@@ -2466,6 +2475,30 @@
 			resize_demux_packet(*dp, ret);	//shrinked to the right size
 			ds_add_packet(ds, *dp);
 			mp_msg(MSGT_DEMUX, MSGL_DBG2, "ADDED %d  bytes to %s fifo, PTS=%.3f\n", ret, (ds == demuxer->audio ? "audio" : (ds == demuxer->video ? "video" : "sub")), (*dp)->pts);
+			if(si)
+			{
+				float diff = (*dp)->pts - si->last_pts;
+				float dur;
+
+				if(abs(diff) > 1) //1 second, there's a discontinuity
+				{
+					si->duration += si->last_pts - si->first_pts;
+					si->first_pts = si->last_pts = (*dp)->pts;
+				}
+				else
+				{
+					si->last_pts = (*dp)->pts;
+				}
+				si->size += ret;
+				dur = si->duration + (si->last_pts - si->first_pts);
+
+				if(dur > 0 && ds == demuxer->video)
+				{
+					ts_priv_t * priv = (ts_priv_t*) demuxer->priv;
+					if(dur > 1)	//otherwise it may be unreliable
+						priv->vbitrate = (uint32_t) ((float) si->size / dur);
+				}
+			}
 	}
 
 	*dp = NULL;
@@ -2513,6 +2546,7 @@
 	int junk = 0, rap_flag = 0;
 	pmt_t *pmt;
 	mp4_decoder_config_t *mp4_dec;
+	TS_stream_info *si;
 
 
 	while(! done)
@@ -2524,6 +2558,7 @@
 		rap_flag = 0;
 		mp4_dec = NULL;
 		es->is_synced = 0;
+		si = NULL;
 
 		junk = priv->ts.packet_size - TS_PACKET_SIZE;
 		buf_size = priv->ts.packet_size - junk;
@@ -2707,6 +2742,7 @@
 				dp = &priv->fifo[1].pack;
 				dp_offset = &priv->fifo[1].offset;
 				buffer_size = &priv->fifo[1].buffer_size;
+				si = &priv->vstr;
 			}
 			else if(is_audio && (demuxer->audio->id == tss->pid))
 			{
@@ -2715,6 +2751,7 @@
 				dp = &priv->fifo[0].pack;
 				dp_offset = &priv->fifo[0].offset;
 				buffer_size = &priv->fifo[0].buffer_size;
+				si = &priv->astr;
 			}
 			else if(is_sub
 				|| (pid_type == SPU_DVD) || (pid_type == SPU_DVB))
@@ -2780,7 +2817,7 @@
 			//IS IT TIME TO QUEUE DATA to the dp_packet?
 			if(is_start && (dp != NULL))
 			{
-				retv = fill_packet(demuxer, ds, dp, dp_offset);
+				retv = fill_packet(demuxer, ds, dp, dp_offset, si);
 			}
 
 
@@ -2893,7 +2930,7 @@
 
 				if(is_audio)
 				{
-					retv = fill_packet(demuxer, ds, dp, dp_offset);
+					retv = fill_packet(demuxer, ds, dp, dp_offset, si);
 					return 1;
 				}
 				
@@ -2966,7 +3003,7 @@
 				if(is_audio)
 				{
 					(*dp)->pts = tss->last_pts;
-					retv = fill_packet(demuxer, ds, dp, dp_offset);
+					retv = fill_packet(demuxer, ds, dp, dp_offset, si);
 					return 1;
 				}
 
@@ -3056,7 +3093,13 @@
 
 	video_stats = (sh_video != NULL);
 	if(video_stats)
-		video_stats = sh_video->i_bps;
+	{
+		mp_msg(MSGT_DEMUX, MSGL_V, "IBPS: %d, vb: %d\r\n", sh_video->i_bps, priv->vbitrate);
+		if(priv->vbitrate)
+			video_stats = priv->vbitrate;
+		else
+			video_stats = sh_video->i_bps;
+	}
 
 	newpos = (flags & 1) ? demuxer->movi_start : demuxer->filepos;
 	if(flags & 2) // float seek 0..1