[FFmpeg-cvslog] flvdec: Export new AAC/H.264 extradata as side data on the next packet

Martin Storsjö git at videolan.org
Thu Dec 22 02:05:05 CET 2011


ffmpeg | branch: master | Martin Storsjö <martin at martin.st> | Thu Dec 15 16:29:55 2011 +0200| [251f320f7deeae22d25c013fb29d162517dd3c91] | committer: Martin Storsjö

flvdec: Export new AAC/H.264 extradata as side data on the next packet

Compared to just overwriting the old extradata, this has the
advantage of letting the decoder know exactly when the
extradata changed (otherwise it is changed immediately when the
new extradata packet is demuxed, even if there's old queued packets
awaiting to be decoded). This makes it easier for decoders to
actually react to the change, so they won't have to inspect
the extradata for each packet to see if it might have changed.

This works when sequentially playing a file with sample rate
changes, but if seeking past a new extradata packet in the
file, it obviously doesn't work properly. That case doesn't
work in flash player either, so it's probably ok not to handle
it.

Signed-off-by: Martin Storsjö <martin at martin.st>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=251f320f7deeae22d25c013fb29d162517dd3c91
---

 libavformat/flvdec.c |   39 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index 4fc5a49..2248061 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -41,6 +41,8 @@
 
 typedef struct {
     int wrong_dts; ///< wrong dts due to negative cts
+    uint8_t *new_extradata[2];
+    int      new_extradata_size[2];
 } FLVContext;
 
 static int flv_probe(AVProbeData *p)
@@ -401,6 +403,14 @@ static int flv_read_header(AVFormatContext *s,
     return 0;
 }
 
+static int flv_read_close(AVFormatContext *s)
+{
+    FLVContext *flv = s->priv_data;
+    av_freep(&flv->new_extradata[0]);
+    av_freep(&flv->new_extradata[1]);
+    return 0;
+}
+
 static int flv_get_extradata(AVFormatContext *s, AVStream *st, int size)
 {
     av_free(st->codec->extradata);
@@ -412,6 +422,18 @@ static int flv_get_extradata(AVFormatContext *s, AVStream *st, int size)
     return 0;
 }
 
+static int flv_queue_extradata(FLVContext *flv, AVIOContext *pb, int stream,
+                               int size)
+{
+    av_free(flv->new_extradata[stream]);
+    flv->new_extradata[stream] = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE);
+    if (!flv->new_extradata[stream])
+        return AVERROR(ENOMEM);
+    flv->new_extradata_size[stream] = size;
+    avio_read(pb, flv->new_extradata[stream], size);
+    return 0;
+}
+
 static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     FLVContext *flv = s->priv_data;
@@ -529,6 +551,12 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
                 dts = AV_NOPTS_VALUE;
         }
         if (type == 0) {
+            if (st->codec->extradata) {
+                if ((ret = flv_queue_extradata(flv, s->pb, is_audio, size)) < 0)
+                    return ret;
+                ret = AVERROR(EAGAIN);
+                goto leave;
+            }
             if ((ret = flv_get_extradata(s, st, size)) < 0)
                 return ret;
             if (st->codec->codec_id == CODEC_ID_AAC) {
@@ -565,6 +593,16 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
     pkt->dts = dts;
     pkt->pts = pts == AV_NOPTS_VALUE ? dts : pts;
     pkt->stream_index = st->index;
+    if (flv->new_extradata[is_audio]) {
+        uint8_t *side = av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
+                                                flv->new_extradata_size[is_audio]);
+        if (side) {
+            memcpy(side, flv->new_extradata[is_audio],
+                   flv->new_extradata_size[is_audio]);
+            av_freep(&flv->new_extradata[is_audio]);
+            flv->new_extradata_size[is_audio] = 0;
+        }
+    }
 
     if (is_audio || ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY))
         pkt->flags |= AV_PKT_FLAG_KEY;
@@ -618,6 +656,7 @@ AVInputFormat ff_flv_demuxer = {
 #if 0
     .read_seek2 = flv_read_seek2,
 #endif
+    .read_close = flv_read_close,
     .extensions = "flv",
     .value = CODEC_ID_FLV1,
 };



More information about the ffmpeg-cvslog mailing list