From 6eb2de748d0c0ac72ff2825a367fa58f1456189a Mon Sep 17 00:00:00 2001 From: Roman Shaposhnik Date: Thu, 11 Jan 2007 22:32:19 +0000 Subject: [PATCH] * Fixing seeking with DV-AVI (by Jeff Downs ) Originally committed as revision 7439 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/avidec.c | 33 ++++++++++++++++++++++++++++++--- libavformat/dv.c | 14 +++++++------- libavformat/dv.h | 2 +- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/libavformat/avidec.c b/libavformat/avidec.c index d1af79fa32..276689dd5c 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -289,6 +289,8 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) print_tag("strh", tag1, -1); #endif if(tag1 == MKTAG('i', 'a', 'v', 's') || tag1 == MKTAG('i', 'v', 'a', 's')){ + int64_t dv_dur; + /* * After some consideration -- I don't think we * have to support anything but DV in a type1 AVIs. @@ -314,8 +316,20 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) url_fskip(pb, 3 * 4); ast->scale = get_le32(pb); ast->rate = get_le32(pb); + url_fskip(pb, 4); /* start time */ + + dv_dur = get_le32(pb); + if (ast->scale > 0 && ast->rate > 0 && dv_dur > 0) { + dv_dur *= AV_TIME_BASE; + s->duration = av_rescale(dv_dur, ast->scale, ast->rate); + } + /* + * else, leave duration alone; timing estimation in utils.c + * will make a guess based on bit rate. + */ + stream_index = s->nb_streams - 1; - url_fskip(pb, size - 7*4); + url_fskip(pb, size - 9*4); break; } @@ -903,6 +917,21 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp // av_log(NULL, AV_LOG_DEBUG, "XX %"PRId64" %d %"PRId64"\n", timestamp, index, st->index_entries[index].timestamp); + if (ENABLE_DV_DEMUXER && avi->dv_demux) { + /* One and only one real stream for DV in AVI, and it has video */ + /* offsets. Calling with other stream indices should have failed */ + /* the av_index_search_timestamp call above. */ + assert(stream_index == 0); + + /* Feed the DV video stream version of the timestamp to the */ + /* DV demux so it can synth correct timestamps */ + dv_offset_reset(avi->dv_demux, timestamp); + + url_fseek(&s->pb, pos, SEEK_SET); + avi->stream_index= -1; + return 0; + } + for(i = 0; i < s->nb_streams; i++) { AVStream *st2 = s->streams[i]; AVIStream *ast2 = st2->priv_data; @@ -937,8 +966,6 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp ast2->frame_offset *=ast2->sample_size; } - if (ENABLE_DV_DEMUXER && avi->dv_demux) - dv_flush_audio_packets(avi->dv_demux); /* do the seek */ url_fseek(&s->pb, pos, SEEK_SET); avi->stream_index= -1; diff --git a/libavformat/dv.c b/libavformat/dv.c index 3ff8a3fe2f..10a3062601 100644 --- a/libavformat/dv.c +++ b/libavformat/dv.c @@ -358,8 +358,13 @@ static int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c, return offset; } -void dv_flush_audio_packets(DVDemuxContext *c) +void dv_offset_reset(DVDemuxContext *c, int64_t frame_offset) { + c->frames= frame_offset; + if (c->ach) + c->abytes= av_rescale(c->frames, + c->ast[0]->codec->bit_rate * (int64_t)c->sys->frame_rate_base, + 8*c->sys->frame_rate); c->audio_pkt[0].size = c->audio_pkt[1].size = 0; } @@ -419,13 +424,8 @@ static int dv_read_seek(AVFormatContext *s, int stream_index, DVDemuxContext *c = r->dv_demux; int64_t offset= dv_frame_offset(s, c, timestamp, flags); - c->frames= offset / c->sys->frame_size; - if (c->ach) - c->abytes= av_rescale(c->frames, - c->ast[0]->codec->bit_rate * (int64_t)c->sys->frame_rate_base, - 8*c->sys->frame_rate); + dv_offset_reset(c, offset / c->sys->frame_size); - dv_flush_audio_packets(c); return url_fseek(&s->pb, offset, SEEK_SET); } diff --git a/libavformat/dv.h b/libavformat/dv.h index f39d22c9fa..2fa30036cc 100644 --- a/libavformat/dv.h +++ b/libavformat/dv.h @@ -29,7 +29,7 @@ typedef struct DVDemuxContext DVDemuxContext; DVDemuxContext* dv_init_demux(AVFormatContext* s); int dv_get_packet(DVDemuxContext*, AVPacket *); int dv_produce_packet(DVDemuxContext*, AVPacket*, uint8_t*, int); -void dv_flush_audio_packets(DVDemuxContext*); +void dv_offset_reset(DVDemuxContext *c, int64_t frame_offset); typedef struct DVMuxContext DVMuxContext; DVMuxContext* dv_init_mux(AVFormatContext* s);