diff options
author | reimar <reimar@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2009-10-16 08:42:00 +0000 |
---|---|---|
committer | reimar <reimar@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2009-10-16 08:42:00 +0000 |
commit | ae7068047a394183ab548919482d60939c4f69b8 (patch) | |
tree | f411b388c4c33d9bfd5f4244bac5fdfb79e5a5fa /libmpdemux/demux_ogg.c | |
parent | e3bc0549dd86c68675e05c992b864b21229a3be4 (diff) | |
download | mpv-ae7068047a394183ab548919482d60939c4f69b8.tar.bz2 mpv-ae7068047a394183ab548919482d60939c4f69b8.tar.xz |
Find and take into account stream start time for ogg files.
This also makes the demuxing function set the keyframe flag for
vorbis packets that aren't header packets and have a time stamp,
even if we do not have vorbis_info struct yet.
The reason for this is that header packets always have 0 as time stamp.
Fixes bug #1585
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@29776 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libmpdemux/demux_ogg.c')
-rw-r--r-- | libmpdemux/demux_ogg.c | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/libmpdemux/demux_ogg.c b/libmpdemux/demux_ogg.c index 2667b4ce1b..3af4866926 100644 --- a/libmpdemux/demux_ogg.c +++ b/libmpdemux/demux_ogg.c @@ -145,7 +145,9 @@ typedef struct ogg_demuxer { ogg_syncpoint_t* syncpoints; int num_syncpoint; off_t pos, last_size; + int64_t initial_granulepos; int64_t final_granulepos; + int64_t duration; /* Used for subtitle switching. */ int n_text; @@ -263,20 +265,23 @@ static unsigned char* demux_ogg_read_packet(ogg_stream_t* os,ogg_packet* pack,fl if(os->vorbis) { if(*pack->packet & PACKET_TYPE_HEADER) os->hdr_packets++; - else if (os->vi_initialized) + else { vorbis_info *vi; - int32_t blocksize; + int32_t blocksize = 0; // When we dump the audio, there is no vi, but we don't care of timestamp in this case - vi = &(os->vi); + vi = os->vi_initialized ? &os->vi : NULL; + if (vi) blocksize = vorbis_packet_blocksize(vi,pack) / samplesize; // Calculate the timestamp if the packet don't have any if(pack->granulepos == -1) { pack->granulepos = os->lastpos; if(os->lastsize > 0) pack->granulepos += os->lastsize; - } + } else + *flags = 1; + if (vi) *pts = pack->granulepos / (float)vi->rate; os->lastsize = blocksize; os->lastpos = pack->granulepos; @@ -521,12 +526,7 @@ void demux_ogg_scan_stream(demuxer_t* demuxer) { pos = last_pos = demuxer->movi_start; // Reset the stream - if(index_mode == 2) { stream_seek(s,demuxer->movi_start); - } else { - //the 270000 are just a wild guess - stream_seek(s,FFMAX(ogg_d->pos,demuxer->movi_end-270000)); - } ogg_sync_reset(sync); // Get the serial number of the stream we use @@ -574,7 +574,18 @@ void demux_ogg_scan_stream(demuxer_t* demuxer) { float pts; int flags; demux_ogg_read_packet(os,&op,&pts,&flags,samplesize); - if(op.granulepos >= 0) ogg_d->final_granulepos = op.granulepos; + if(op.granulepos >= 0) { + ogg_d->final_granulepos = op.granulepos; + if(ogg_d->initial_granulepos == MP_NOPTS_VALUE && (flags & 1)) { + ogg_d->initial_granulepos = op.granulepos; + if (index_mode != 2 && ogg_d->pos < demuxer->movi_end-2*270000) { + //the 270000 are just a wild guess + stream_seek(s,FFMAX(ogg_d->pos,demuxer->movi_end-270000)); + ogg_sync_reset(sync); + continue; + } + } + } if(index_mode == 2 && (flags || (os->vorbis && op.granulepos >= 0))) { if (ogg_d->num_syncpoint > SIZE_MAX / sizeof(ogg_syncpoint_t) - 1) break; ogg_d->syncpoints = realloc_struct(ogg_d->syncpoints,(ogg_d->num_syncpoint+1), sizeof(ogg_syncpoint_t)); @@ -1122,6 +1133,7 @@ int demux_ogg_open(demuxer_t* demuxer) { } ogg_d->final_granulepos=0; + ogg_d->initial_granulepos = MP_NOPTS_VALUE; if(!s->end_pos) demuxer->seekable = 0; else { @@ -1130,6 +1142,9 @@ int demux_ogg_open(demuxer_t* demuxer) { demuxer->seekable = 1; demux_ogg_scan_stream(demuxer); } + if (ogg_d->initial_granulepos == MP_NOPTS_VALUE) + ogg_d->initial_granulepos = 0; + ogg_d->duration = ogg_d->final_granulepos - ogg_d->initial_granulepos; mp_msg(MSGT_DEMUX,MSGL_V,"Ogg demuxer : found %d audio stream%s, %d video stream%s and %d text stream%s\n",n_audio,n_audio>1?"s":"",n_video,n_video>1?"s":"",ogg_d->n_text,ogg_d->n_text>1?"s":""); @@ -1361,10 +1376,10 @@ static void demux_ogg_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_de old_pos = ogg_d->pos; //calculate the granulepos to seek to - gp = flags & SEEK_ABSOLUTE ? 0 : os->lastpos; + gp = flags & SEEK_ABSOLUTE ? ogg_d->initial_granulepos : os->lastpos; if(flags & SEEK_FACTOR) { - if (ogg_d->final_granulepos > 0) - gp += ogg_d->final_granulepos * rel_seek_secs; + if (ogg_d->duration > 0) + gp += ogg_d->duration * rel_seek_secs; else gp += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * os->lastpos / ogg_d->pos; } else @@ -1391,8 +1406,8 @@ static void demux_ogg_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_de if(flags & SEEK_FACTOR) pos += (demuxer->movi_end - demuxer->movi_start) * rel_seek_secs; else { - if (ogg_d->final_granulepos > 0) { - pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->final_granulepos / rate); + if (ogg_d->duration > 0) { + pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->duration / rate); } else if (os->lastpos > 0) { pos += rel_seek_secs * ogg_d->pos / (os->lastpos / rate); } @@ -1547,13 +1562,13 @@ static int demux_ogg_control(demuxer_t *demuxer,int cmd, void *arg){ switch(cmd) { case DEMUXER_CTRL_GET_TIME_LENGTH: - if (ogg_d->final_granulepos<=0) return DEMUXER_CTRL_DONTKNOW; - *(double *)arg=(double)ogg_d->final_granulepos / rate; + if (ogg_d->duration<=0) return DEMUXER_CTRL_DONTKNOW; + *(double *)arg=(double)(ogg_d->duration) / rate; return DEMUXER_CTRL_GUESS; case DEMUXER_CTRL_GET_PERCENT_POS: - if (ogg_d->final_granulepos<=0) return DEMUXER_CTRL_DONTKNOW; - *(int *)arg=(os->lastpos*100) / ogg_d->final_granulepos; + if (ogg_d->duration<=0) return DEMUXER_CTRL_DONTKNOW; + *(int *)arg=((os->lastpos - ogg_d->initial_granulepos)*100) / ogg_d->duration; return DEMUXER_CTRL_OK; default: |