Imported Debian version 2.5.0~trusty1.1
[deb_ffmpeg.git] / ffmpeg / libavformat / ffmdec.c
index 448762b02628c982d708fa89b035558dcf520ec7..987f419c96ba8bd593d9c6b5e57a4fbeb3b5852b 100644 (file)
@@ -23,6 +23,9 @@
 
 #include "libavutil/intreadwrite.h"
 #include "libavutil/intfloat.h"
+#include "libavutil/opt.h"
+#include "libavutil/avassert.h"
+#include "libavutil/avstring.h"
 #include "avformat.h"
 #include "internal.h"
 #include "ffm.h"
@@ -230,6 +233,27 @@ static int ffm_close(AVFormatContext *s)
     return 0;
 }
 
+static int ffm_append_recommended_configuration(AVStream *st, char **conf)
+{
+    int ret;
+    size_t newsize;
+    av_assert0(conf && st);
+    if (!*conf)
+        return 0;
+    if (!st->recommended_encoder_configuration) {
+        st->recommended_encoder_configuration = *conf;
+        *conf = 0;
+        return 0;
+    }
+    newsize = strlen(*conf) + strlen(st->recommended_encoder_configuration) + 2;
+    if ((ret = av_reallocp(&st->recommended_encoder_configuration, newsize)) < 0)
+        return ret;
+    av_strlcat(st->recommended_encoder_configuration, ",", newsize);
+    av_strlcat(st->recommended_encoder_configuration, *conf, newsize);
+    av_freep(conf);
+    return 0;
+}
+
 static int ffm2_read_header(AVFormatContext *s)
 {
     FFMContext *ffm = s->priv_data;
@@ -237,6 +261,9 @@ static int ffm2_read_header(AVFormatContext *s)
     AVIOContext *pb = s->pb;
     AVCodecContext *codec;
     int ret;
+    int f_main = 0, f_cprv, f_stvi, f_stau;
+    AVCodec *enc;
+    char *buffer;
 
     ffm->packet_size = avio_rb32(pb);
     if (ffm->packet_size != FFM_PACKET_SIZE) {
@@ -267,10 +294,15 @@ static int ffm2_read_header(AVFormatContext *s)
 
         switch(id) {
         case MKBETAG('M', 'A', 'I', 'N'):
+            if (f_main++) {
+                ret = AVERROR(EINVAL);
+                goto fail;
+            }
             avio_rb32(pb); /* nb_streams */
             avio_rb32(pb); /* total bitrate */
             break;
         case MKBETAG('C', 'O', 'M', 'M'):
+            f_cprv = f_stvi = f_stau = 0;
             st = avformat_new_stream(s, NULL);
             if (!st) {
                 ret = AVERROR(ENOMEM);
@@ -291,63 +323,111 @@ static int ffm2_read_header(AVFormatContext *s)
                 if (ff_get_extradata(codec, pb, avio_rb32(pb)) < 0)
                     return AVERROR(ENOMEM);
             }
-            avio_seek(pb, next, SEEK_SET);
-            id = avio_rb32(pb);
-            size = avio_rb32(pb);
-            next = avio_tell(pb) + size;
-            switch(id) {
-            case MKBETAG('S', 'T', 'V', 'I'):
-                codec->time_base.num = avio_rb32(pb);
-                codec->time_base.den = avio_rb32(pb);
-                codec->width = avio_rb16(pb);
-                codec->height = avio_rb16(pb);
-                codec->gop_size = avio_rb16(pb);
-                codec->pix_fmt = avio_rb32(pb);
-                codec->qmin = avio_r8(pb);
-                codec->qmax = avio_r8(pb);
-                codec->max_qdiff = avio_r8(pb);
-                codec->qcompress = avio_rb16(pb) / 10000.0;
-                codec->qblur = avio_rb16(pb) / 10000.0;
-                codec->bit_rate_tolerance = avio_rb32(pb);
-                avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf));
-                codec->rc_eq = av_strdup(rc_eq_buf);
-                codec->rc_max_rate = avio_rb32(pb);
-                codec->rc_min_rate = avio_rb32(pb);
-                codec->rc_buffer_size = avio_rb32(pb);
-                codec->i_quant_factor = av_int2double(avio_rb64(pb));
-                codec->b_quant_factor = av_int2double(avio_rb64(pb));
-                codec->i_quant_offset = av_int2double(avio_rb64(pb));
-                codec->b_quant_offset = av_int2double(avio_rb64(pb));
-                codec->dct_algo = avio_rb32(pb);
-                codec->strict_std_compliance = avio_rb32(pb);
-                codec->max_b_frames = avio_rb32(pb);
-                codec->mpeg_quant = avio_rb32(pb);
-                codec->intra_dc_precision = avio_rb32(pb);
-                codec->me_method = avio_rb32(pb);
-                codec->mb_decision = avio_rb32(pb);
-                codec->nsse_weight = avio_rb32(pb);
-                codec->frame_skip_cmp = avio_rb32(pb);
-                codec->rc_buffer_aggressivity = av_int2double(avio_rb64(pb));
-                codec->codec_tag = avio_rb32(pb);
-                codec->thread_count = avio_r8(pb);
-                codec->coder_type = avio_rb32(pb);
-                codec->me_cmp = avio_rb32(pb);
-                codec->me_subpel_quality = avio_rb32(pb);
-                codec->me_range = avio_rb32(pb);
-                codec->keyint_min = avio_rb32(pb);
-                codec->scenechange_threshold = avio_rb32(pb);
-                codec->b_frame_strategy = avio_rb32(pb);
-                codec->qcompress = av_int2double(avio_rb64(pb));
-                codec->qblur = av_int2double(avio_rb64(pb));
-                codec->max_qdiff = avio_rb32(pb);
-                codec->refs = avio_rb32(pb);
-                break;
-            case MKBETAG('S', 'T', 'A', 'U'):
-                codec->sample_rate = avio_rb32(pb);
-                codec->channels = avio_rl16(pb);
-                codec->frame_size = avio_rl16(pb);
-                break;
+            break;
+        case MKBETAG('S', 'T', 'V', 'I'):
+            if (f_stvi++) {
+                ret = AVERROR(EINVAL);
+                goto fail;
+            }
+            codec->time_base.num = avio_rb32(pb);
+            codec->time_base.den = avio_rb32(pb);
+            codec->width = avio_rb16(pb);
+            codec->height = avio_rb16(pb);
+            codec->gop_size = avio_rb16(pb);
+            codec->pix_fmt = avio_rb32(pb);
+            codec->qmin = avio_r8(pb);
+            codec->qmax = avio_r8(pb);
+            codec->max_qdiff = avio_r8(pb);
+            codec->qcompress = avio_rb16(pb) / 10000.0;
+            codec->qblur = avio_rb16(pb) / 10000.0;
+            codec->bit_rate_tolerance = avio_rb32(pb);
+            avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf));
+            codec->rc_eq = av_strdup(rc_eq_buf);
+            codec->rc_max_rate = avio_rb32(pb);
+            codec->rc_min_rate = avio_rb32(pb);
+            codec->rc_buffer_size = avio_rb32(pb);
+            codec->i_quant_factor = av_int2double(avio_rb64(pb));
+            codec->b_quant_factor = av_int2double(avio_rb64(pb));
+            codec->i_quant_offset = av_int2double(avio_rb64(pb));
+            codec->b_quant_offset = av_int2double(avio_rb64(pb));
+            codec->dct_algo = avio_rb32(pb);
+            codec->strict_std_compliance = avio_rb32(pb);
+            codec->max_b_frames = avio_rb32(pb);
+            codec->mpeg_quant = avio_rb32(pb);
+            codec->intra_dc_precision = avio_rb32(pb);
+            codec->me_method = avio_rb32(pb);
+            codec->mb_decision = avio_rb32(pb);
+            codec->nsse_weight = avio_rb32(pb);
+            codec->frame_skip_cmp = avio_rb32(pb);
+            codec->rc_buffer_aggressivity = av_int2double(avio_rb64(pb));
+            codec->codec_tag = avio_rb32(pb);
+            codec->thread_count = avio_r8(pb);
+            codec->coder_type = avio_rb32(pb);
+            codec->me_cmp = avio_rb32(pb);
+            codec->me_subpel_quality = avio_rb32(pb);
+            codec->me_range = avio_rb32(pb);
+            codec->keyint_min = avio_rb32(pb);
+            codec->scenechange_threshold = avio_rb32(pb);
+            codec->b_frame_strategy = avio_rb32(pb);
+            codec->qcompress = av_int2double(avio_rb64(pb));
+            codec->qblur = av_int2double(avio_rb64(pb));
+            codec->max_qdiff = avio_rb32(pb);
+            codec->refs = avio_rb32(pb);
+            break;
+        case MKBETAG('S', 'T', 'A', 'U'):
+            if (f_stau++) {
+                ret = AVERROR(EINVAL);
+                goto fail;
+            }
+            codec->sample_rate = avio_rb32(pb);
+            codec->channels = avio_rl16(pb);
+            codec->frame_size = avio_rl16(pb);
+            break;
+        case MKBETAG('C', 'P', 'R', 'V'):
+            if (f_cprv++) {
+                ret = AVERROR(EINVAL);
+                goto fail;
+            }
+            enc = avcodec_find_encoder(codec->codec_id);
+            if (enc && enc->priv_data_size && enc->priv_class) {
+                buffer = av_malloc(size + 1);
+                if (!buffer) {
+                    ret = AVERROR(ENOMEM);
+                    goto fail;
+                }
+                avio_get_str(pb, size, buffer, size + 1);
+                if ((ret = ffm_append_recommended_configuration(st, &buffer)) < 0)
+                    goto fail;
+            }
+            break;
+        case MKBETAG('S', '2', 'V', 'I'):
+            if (f_stvi++) {
+                ret = AVERROR(EINVAL);
+                goto fail;
+            }
+            buffer = av_malloc(size);
+            if (!buffer) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
+            }
+            avio_get_str(pb, INT_MAX, buffer, size);
+            av_set_options_string(codec, buffer, "=", ",");
+            if ((ret = ffm_append_recommended_configuration(st, &buffer)) < 0)
+                goto fail;
+            break;
+        case MKBETAG('S', '2', 'A', 'U'):
+            if (f_stau++) {
+                ret = AVERROR(EINVAL);
+                goto fail;
+            }
+            buffer = av_malloc(size);
+            if (!buffer) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
             }
+            avio_get_str(pb, INT_MAX, buffer, size);
+            av_set_options_string(codec, buffer, "=", ",");
+            ffm_append_recommended_configuration(st, &buffer);
             break;
         }
         avio_seek(pb, next, SEEK_SET);