[MPlayer-dev-eng] Patch for correct seek in MPEG files with pts offset != 0
Yaro Pollak
slava at plris.com
Mon Jul 18 10:48:19 CEST 2005
Hello friends,
Following my post in MPlayer-users I'm posting the changes I made to demux_mpg.c in order to correct a problem, where seeking was done incorrectly (or not done at all) in MPEG-PS files that started with initial pts > 0. I'm not sure if this is the best solution (as the time stamps remain absolute, and not 0-based, it looks as if the movie started from the middle, but at least the seek works now).
Cheers!
Yaro
--- demux_mpgo.c 2005-07-10 12:36:50.000000000 +0200
+++ demux_mpg.c 2005-07-18 09:57:04.000000000 +0200
@@ -29,6 +29,7 @@
typedef struct mpg_demuxer {
float last_pts;
+ float start_pts;
float final_pts;
int has_valid_timestamps;
unsigned int es_map[0x40]; //es map of stream types (associated to the pes id) from 0xb0 to 0xef
@@ -109,10 +110,15 @@
if (!ds_fill_buffer(demuxer->video)) return 0;
mpg_d = (mpg_demuxer_t*)calloc(1,sizeof(mpg_demuxer_t));
demuxer->priv = mpg_d;
+ mpg_d->start_pts = 0.0;
mpg_d->final_pts = 0.0;
mpg_d->has_valid_timestamps = 1;
mpg_d->num_a_streams = 0;
if (demuxer->seekable && stream_tell(demuxer->stream) < end_seq_start) {
+ stream_seek(s,pos);
+ while ((!s->eof) && ds_fill_buffer(demuxer->video) && mpg_d->start_pts == 0.0) {
+ mpg_d->start_pts = mpg_d->last_pts;
+ }
stream_seek(s,(pos + end_seq_start / 2));
while ((!s->eof) && ds_fill_buffer(demuxer->video) && half_pts == 0.0) {
half_pts = mpg_d->last_pts;
@@ -122,9 +128,12 @@
if (mpg_d->final_pts < mpg_d->last_pts) mpg_d->final_pts = mpg_d->last_pts;
}
// educated guess about validity of timestamps
+ mpg_d->final_pts -= mpg_d->start_pts;
+ half_pts -= mpg_d->start_pts;
if (mpg_d->final_pts > 3 * half_pts || mpg_d->final_pts < 1.5 * half_pts) {
mpg_d->has_valid_timestamps = 0;
}
+ mpg_d->final_pts += mpg_d->start_pts;
ds_free_packs(demuxer->audio);
ds_free_packs(demuxer->video);
demuxer->stream->eof=0; // clear eof flag
@@ -528,7 +537,7 @@
//calculate the pts to seek to
if(flags & 2) {
if (mpg_d && mpg_d->final_pts > 0.0)
- newpts += mpg_d->final_pts * rel_seek_secs;
+ newpts += (mpg_d->final_pts - mpg_d->start_pts) * rel_seek_secs;
else
newpts += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * oldpts / oldpos;
} else
@@ -542,9 +551,9 @@
// time seek (secs)
if (mpg_d && mpg_d->has_valid_timestamps) {
if (mpg_d->final_pts > 0.0)
- newpos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / mpg_d->final_pts;
+ newpos += (rel_seek_secs - mpg_d->start_pts) * (demuxer->movi_end - demuxer->movi_start) / (mpg_d->final_pts - mpg_d->start_pts);
else if (oldpts > 0.0)
- newpos += rel_seek_secs * (oldpos - demuxer->movi_start) / oldpts;
+ newpos += (rel_seek_secs - mpg_d->start_pts) * (oldpos - demuxer->movi_start) / (oldpts - mpg_d->start_pts);
} else if(!sh_video || !sh_video->i_bps) // unspecified or VBR
newpos+=2324*75*rel_seek_secs; // 174.3 kbyte/sec
else
@@ -625,14 +637,14 @@
switch(cmd) {
case DEMUXER_CTRL_GET_TIME_LENGTH:
if (mpg_d && mpg_d->has_valid_timestamps) {
- *((unsigned long *)arg)=(long)mpg_d->final_pts;
+ *((unsigned long *)arg)=(long)(mpg_d->final_pts - mpg_d->start_pts);
return DEMUXER_CTRL_GUESS;
}
return DEMUXER_CTRL_DONTKNOW;
case DEMUXER_CTRL_GET_PERCENT_POS:
if (mpg_d && mpg_d->has_valid_timestamps && mpg_d->final_pts > 0.0) {
- *((int *)arg)=(int)(100 * mpg_d->last_pts / mpg_d->final_pts);
+ *((int *)arg)=(int)(100 * (mpg_d->last_pts - mpg_d->start_pts) / (mpg_d->final_pts - mpg_d->start_pts));
return DEMUXER_CTRL_OK;
}
return DEMUXER_CTRL_DONTKNOW;
More information about the MPlayer-dev-eng
mailing list