]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/flvdec.c
mov: Don't stick the QuickTime field ordering atom in extradata.
[ffmpeg] / libavformat / flvdec.c
index 1459850f4a0a1fc98d7d68b269588ee02a6b7c3e..4f1c805c81b76c6f88c5ecac80beb3f7a9af8811 100644 (file)
 
 #include "libavutil/avstring.h"
 #include "libavutil/dict.h"
-#include "libavutil/intfloat_readwrite.h"
+#include "libavutil/intfloat.h"
 #include "libavutil/mathematics.h"
 #include "libavcodec/bytestream.h"
 #include "libavcodec/mpeg4audio.h"
 #include "avformat.h"
+#include "internal.h"
 #include "avio_internal.h"
 #include "flv.h"
 
 
 typedef struct {
     int wrong_dts; ///< wrong dts due to negative cts
+    uint8_t *new_extradata[2];
+    int      new_extradata_size[2];
+    int      last_sample_rate;
+    int      last_channels;
 } FLVContext;
 
 static int flv_probe(AVProbeData *p)
@@ -53,8 +58,7 @@ static int flv_probe(AVProbeData *p)
     return 0;
 }
 
-static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, int flv_codecid) {
-    AVCodecContext *acodec = astream->codec;
+static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, AVCodecContext *acodec, int flv_codecid) {
     switch(flv_codecid) {
         //no distinction between S16 and S8 PCM codec flags
         case FLV_CODECID_PCM:
@@ -188,7 +192,7 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, AVStream
         for (i = 0; i < arraylen && avio_tell(ioc) < max_pos - 1; i++) {
             if (avio_r8(ioc) != AMF_DATA_TYPE_NUMBER)
                 goto finish;
-            num_val = av_int2dbl(avio_rb64(ioc));
+            num_val = av_int2double(avio_rb64(ioc));
             current_array[i] = num_val;
         }
         if (times && filepositions) {
@@ -229,7 +233,7 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst
 
     switch(amf_type) {
         case AMF_DATA_TYPE_NUMBER:
-            num_val = av_int2dbl(avio_rb64(ioc)); break;
+            num_val = av_int2double(avio_rb64(ioc)); break;
         case AMF_DATA_TYPE_BOOL:
             num_val = avio_r8(ioc); break;
         case AMF_DATA_TYPE_STRING:
@@ -360,7 +364,7 @@ static AVStream *create_stream(AVFormatContext *s, int is_audio){
         return NULL;
     st->id = is_audio;
     st->codec->codec_type = is_audio ? AVMEDIA_TYPE_AUDIO : AVMEDIA_TYPE_VIDEO;
-    av_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
+    avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
     return st;
 }
 
@@ -400,6 +404,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);
@@ -411,12 +423,25 @@ 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;
     int ret, i, type, size, flags, is_audio;
     int64_t next, pos;
     int64_t dts, pts = AV_NOPTS_VALUE;
+    int sample_rate, channels;
     AVStream *st = NULL;
 
  for(;;avio_skip(s->pb, 4)){ /* pkt size is repeated at end. skip it */
@@ -501,13 +526,24 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
     }
 
     if(is_audio){
+        int bits_per_coded_sample;
+        channels    = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1;
+        sample_rate = (44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >> FLV_AUDIO_SAMPLERATE_OFFSET) >> 3);
+        bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
         if(!st->codec->channels || !st->codec->sample_rate || !st->codec->bits_per_coded_sample) {
-            st->codec->channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1;
-            st->codec->sample_rate = (44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >> FLV_AUDIO_SAMPLERATE_OFFSET) >> 3);
-            st->codec->bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
+            st->codec->channels              = channels;
+            st->codec->sample_rate           = sample_rate;
+            st->codec->bits_per_coded_sample = bits_per_coded_sample;
         }
         if(!st->codec->codec_id){
-            flv_set_audio_codec(s, st, flags & FLV_AUDIO_CODECID_MASK);
+            flv_set_audio_codec(s, st, st->codec, flags & FLV_AUDIO_CODECID_MASK);
+            flv->last_sample_rate = st->codec->sample_rate;
+            flv->last_channels    = st->codec->channels;
+        } else {
+            AVCodecContext ctx;
+            ctx.sample_rate = sample_rate;
+            flv_set_audio_codec(s, st, &ctx, flags & FLV_AUDIO_CODECID_MASK);
+            sample_rate = ctx.sample_rate;
         }
     }else{
         size -= flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK);
@@ -528,12 +564,18 @@ 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) {
                 MPEG4AudioConfig cfg;
                 avpriv_mpeg4audio_get_config(&cfg, st->codec->extradata,
-                                         st->codec->extradata_size);
+                                             st->codec->extradata_size * 8, 1);
                 st->codec->channels = cfg.channels;
                 if (cfg.ext_sample_rate)
                     st->codec->sample_rate = cfg.ext_sample_rate;
@@ -564,6 +606,22 @@ 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 && (sample_rate != flv->last_sample_rate ||
+                     channels != flv->last_channels)) {
+        flv->last_sample_rate = sample_rate;
+        flv->last_channels    = channels;
+        ff_add_param_change(pkt, channels, 0, sample_rate, 0, 0);
+    }
 
     if (is_audio || ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY))
         pkt->flags |= AV_PKT_FLAG_KEY;
@@ -617,6 +675,7 @@ AVInputFormat ff_flv_demuxer = {
 #if 0
     .read_seek2 = flv_read_seek2,
 #endif
+    .read_close = flv_read_close,
     .extensions = "flv",
     .value = CODEC_ID_FLV1,
 };