changeset 1629:aedce96c28ff libavformat

* Fixing seeking with DV-AVI (by Jeff Downs <heydowns at borg dot com>)
author romansh
date Thu, 11 Jan 2007 22:32:19 +0000
parents 421c130983da
children e7c247a67e20
files avidec.c dv.c dv.h
diffstat 3 files changed, 38 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/avidec.c	Wed Jan 10 10:30:03 2007 +0000
+++ b/avidec.c	Thu Jan 11 22:32:19 2007 +0000
@@ -289,6 +289,8 @@
             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 @@
                 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 @@
 
 //    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 @@
             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;
--- a/dv.c	Wed Jan 10 10:30:03 2007 +0000
+++ b/dv.c	Thu Jan 11 22:32:19 2007 +0000
@@ -358,8 +358,13 @@
     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 @@
     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);
 }
 
--- a/dv.h	Wed Jan 10 10:30:03 2007 +0000
+++ b/dv.h	Thu Jan 11 22:32:19 2007 +0000
@@ -29,7 +29,7 @@
 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);