timestamps generation improvement when parsing avi
authorJoakim Plate <elupus@ecce.se>
Fri, 13 Apr 2007 07:50:04 +0000 (07:50 +0000)
committerBenoit Fouet <benoit.fouet@free.fr>
Fri, 13 Apr 2007 07:50:04 +0000 (07:50 +0000)
patch by Joakim \ elupus chez ecce dot se /
original thread:
date: 03/19/2007 01:47 AM
subject: [Ffmpeg-devel] [RFC] Improvement for the odd timestamp generation when parser is in use.

Originally committed as revision 8725 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavcodec/avcodec.h
libavcodec/parser.c
libavformat/avformat.h
libavformat/avidec.c
libavformat/utils.c

index 9fd2fb31ff25174b807232534433e0e58c745bdd..596f8efebc688f2dcff9d31ed168928e0edb0497 100644 (file)
@@ -37,8 +37,8 @@ extern "C" {
 #define AV_STRINGIFY(s)         AV_TOSTRING(s)
 #define AV_TOSTRING(s) #s
 
-#define LIBAVCODEC_VERSION_INT  ((51<<16)+(40<<8)+2)
-#define LIBAVCODEC_VERSION      51.40.2
+#define LIBAVCODEC_VERSION_INT  ((51<<16)+(40<<8)+3)
+#define LIBAVCODEC_VERSION      51.40.3
 #define LIBAVCODEC_BUILD        LIBAVCODEC_VERSION_INT
 
 #define LIBAVCODEC_IDENT        "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION)
@@ -2940,6 +2940,9 @@ typedef struct AVCodecParserContext {
 
     int flags;
 #define PARSER_FLAG_COMPLETE_FRAMES           0x0001
+
+    int64_t offset;      ///< byte offset from starting packet start
+    int64_t last_offset;
 } AVCodecParserContext;
 
 typedef struct AVCodecParser {
index d5b1bf168943057671c9a09ef33dc4138d73c3d0..1c21d50fe57832e5da6e954f95b7bc3032b67cfc 100644 (file)
@@ -124,6 +124,7 @@ int av_parser_parse(AVCodecParserContext *s,
             s->fetch_timestamp=0;
             s->last_pts = pts;
             s->last_dts = dts;
+            s->last_offset = 0;
             s->cur_frame_pts[k] =
             s->cur_frame_dts[k] = AV_NOPTS_VALUE;
         }
@@ -138,6 +139,7 @@ int av_parser_parse(AVCodecParserContext *s,
         s->frame_offset = s->last_frame_offset;
         s->pts = s->last_pts;
         s->dts = s->last_dts;
+        s->offset = s->last_offset;
 
         /* offset of the next frame */
         s->last_frame_offset = s->cur_offset + index;
@@ -156,6 +158,7 @@ int av_parser_parse(AVCodecParserContext *s,
 
         s->last_pts = s->cur_frame_pts[k];
         s->last_dts = s->cur_frame_dts[k];
+        s->last_offset = s->last_frame_offset - s->cur_frame_offset[k];
 
         /* some parsers tell us the packet size even before seeing the first byte of the next packet,
            so the next pts/dts is in the next chunk */
index c5d5df01979a92b2cf056ad521f0995acb5a3c4e..d6525954bbb619291e4515a4909d56a8df68dc8e 100644 (file)
@@ -25,8 +25,8 @@
 extern "C" {
 #endif
 
-#define LIBAVFORMAT_VERSION_INT ((51<<16)+(12<<8)+0)
-#define LIBAVFORMAT_VERSION     51.12.0
+#define LIBAVFORMAT_VERSION_INT ((51<<16)+(12<<8)+1)
+#define LIBAVFORMAT_VERSION     51.12.1
 #define LIBAVFORMAT_BUILD       LIBAVFORMAT_VERSION_INT
 
 #define LIBAVFORMAT_IDENT       "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION)
@@ -309,7 +309,8 @@ typedef struct AVStream {
     char language[4]; /** ISO 639 3-letter language code (empty string if undefined) */
 
     /* av_read_frame() support */
-    int need_parsing;                  ///< 1->full parsing needed, 2->only parse headers dont repack
+#define AVSTREAM_PARSE_TIMESTAMPS 3    /**< full parsing and interpolation of timestamps for frames not starting on packet boundary */
+    int need_parsing;                  ///< 1->full parsing needed, 2->only parse headers dont repack, 3->full parsing and interpolate timestamps
     struct AVCodecParserContext *parser;
 
     int64_t cur_dts;
index 02078bc77b75cb2110a9329effe7b357199acffc..d434c5718142cd23ea1cf76c36bb5f2514f43c77 100644 (file)
@@ -452,8 +452,8 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
                     if (size%2) /* 2-aligned (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */
                         url_fskip(pb, 1);
                     /* Force parsing as several audio frames can be in
-                     * one packet*/
-                    st->need_parsing = 1;
+                     * one packet and timestamps refer to packet start*/
+                    st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS;
                     /* ADTS header is in extradata, AAC without header must be stored as exact frames, parser not needed and it will fail */
                     if (st->codec->codec_id == CODEC_ID_AAC && st->codec->extradata_size)
                         st->need_parsing = 0;
index c82d7dac84d60b608e7d0a9d8ca0dc1b2de95137..b748b546cac8fcfbdefe9122b577c42a5e89f16d 100644 (file)
@@ -584,6 +584,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
                                AVCodecParserContext *pc, AVPacket *pkt)
 {
     int num, den, presentation_delayed, delay, i;
+    int64_t offset;
     /* handle wrapping */
     if(st->cur_dts != AV_NOPTS_VALUE){
         if(pkt->pts != AV_NOPTS_VALUE)
@@ -599,6 +600,16 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
         }
     }
 
+    /* correct timestamps with byte offset if demuxers only have timestamps on packet boundaries */
+    if(pc && st->need_parsing == AVSTREAM_PARSE_TIMESTAMPS && pkt->size){
+        /* this will estimate bitrate based on this frame's duration and size */
+        offset = av_rescale(pc->offset, pkt->duration, pkt->size);
+        if(pkt->pts != AV_NOPTS_VALUE)
+            pkt->pts += offset;
+        if(pkt->dts != AV_NOPTS_VALUE)
+            pkt->dts += offset;
+    }
+
     if(is_intra_only(st->codec))
         pkt->flags |= PKT_FLAG_KEY;