lavf/ffm: use AVOption API to store/restore stream properties
[ffmpeg.git] / libavformat / ffmenc.c
index e0885e7..b717813 100644 (file)
@@ -120,6 +120,48 @@ static int ffm_write_header_codec_private_ctx(AVIOContext *pb, AVCodecContext *c
     return 0;
 }
 
+static int ffm_write_header_codec_ctx(AVIOContext *pb, AVCodecContext *ctx, unsigned tag, int type)
+{
+    AVIOContext *tmp;
+    char *buf = NULL;
+    uint8_t *p = NULL;
+    int ret, need_coma = 0;
+
+#define SKIP_DEFAULTS   AV_OPT_SERIALIZE_SKIP_DEFAULTS
+#define OPT_FLAGS_EXACT AV_OPT_SERIALIZE_OPT_FLAGS_EXACT
+#define ENC             AV_OPT_FLAG_ENCODING_PARAM
+
+    if (avio_open_dyn_buf(&tmp) < 0)
+        return AVERROR(ENOMEM);
+    if ((ret = av_opt_serialize(ctx, ENC | type, SKIP_DEFAULTS, &buf, '=', ',')) < 0)
+        goto fail;
+    if (buf && strlen(buf)) {
+        avio_write(tmp, buf, strlen(buf));
+        av_free(buf);
+        need_coma = 1;
+    }
+    if ((ret = av_opt_serialize(ctx, 0, SKIP_DEFAULTS | OPT_FLAGS_EXACT, &buf, '=', ',')) < 0)
+        goto fail;
+    if (buf && strlen(buf)) {
+        if (need_coma)
+            avio_w8(tmp, ',');
+        avio_write(tmp, buf, strlen(buf));
+        av_free(buf);
+    }
+    avio_w8(tmp, 0);
+    write_header_chunk(pb, tmp, tag);
+    return 0;
+  fail:
+    av_free(buf);
+    avio_close_dyn_buf(tmp, &p);
+    av_free(p);
+    return ret;
+
+#undef SKIP_DEFAULTS
+#undef OPT_FLAGS_EXACT
+#undef ENC
+}
+
 static int ffm_write_header(AVFormatContext *s)
 {
     FFMContext *ffm = s->priv_data;
@@ -180,59 +222,13 @@ static int ffm_write_header(AVFormatContext *s)
         /* specific info */
         switch(codec->codec_type) {
         case AVMEDIA_TYPE_VIDEO:
-            avio_wb32(pb, codec->time_base.num);
-            avio_wb32(pb, codec->time_base.den);
-            avio_wb16(pb, codec->width);
-            avio_wb16(pb, codec->height);
-            avio_wb16(pb, codec->gop_size);
-            avio_wb32(pb, codec->pix_fmt);
-            avio_w8(pb, codec->qmin);
-            avio_w8(pb, codec->qmax);
-            avio_w8(pb, codec->max_qdiff);
-            avio_wb16(pb, (int) (codec->qcompress * 10000.0));
-            avio_wb16(pb, (int) (codec->qblur * 10000.0));
-            avio_wb32(pb, codec->bit_rate_tolerance);
-            avio_put_str(pb, codec->rc_eq ? codec->rc_eq : "tex^qComp");
-            avio_wb32(pb, codec->rc_max_rate);
-            avio_wb32(pb, codec->rc_min_rate);
-            avio_wb32(pb, codec->rc_buffer_size);
-            avio_wb64(pb, av_double2int(codec->i_quant_factor));
-            avio_wb64(pb, av_double2int(codec->b_quant_factor));
-            avio_wb64(pb, av_double2int(codec->i_quant_offset));
-            avio_wb64(pb, av_double2int(codec->b_quant_offset));
-            avio_wb32(pb, codec->dct_algo);
-            avio_wb32(pb, codec->strict_std_compliance);
-            avio_wb32(pb, codec->max_b_frames);
-            avio_wb32(pb, codec->mpeg_quant);
-            avio_wb32(pb, codec->intra_dc_precision);
-            avio_wb32(pb, codec->me_method);
-            avio_wb32(pb, codec->mb_decision);
-            avio_wb32(pb, codec->nsse_weight);
-            avio_wb32(pb, codec->frame_skip_cmp);
-            avio_wb64(pb, av_double2int(codec->rc_buffer_aggressivity));
-            avio_wb32(pb, codec->codec_tag);
-            avio_w8(pb, codec->thread_count);
-            avio_wb32(pb, codec->coder_type);
-            avio_wb32(pb, codec->me_cmp);
-            avio_wb32(pb, codec->me_subpel_quality);
-            avio_wb32(pb, codec->me_range);
-            avio_wb32(pb, codec->keyint_min);
-            avio_wb32(pb, codec->scenechange_threshold);
-            avio_wb32(pb, codec->b_frame_strategy);
-            avio_wb64(pb, av_double2int(codec->qcompress));
-            avio_wb64(pb, av_double2int(codec->qblur));
-            avio_wb32(pb, codec->max_qdiff);
-            avio_wb32(pb, codec->refs);
-            write_header_chunk(s->pb, pb, MKBETAG('S', 'T', 'V', 'I'));
-            if ((ret = ffm_write_header_codec_private_ctx(s->pb, codec, AV_OPT_FLAG_VIDEO_PARAM)) < 0)
+            if ((ret = ffm_write_header_codec_ctx(s->pb, codec, MKBETAG('S', '2', 'V', 'I'), AV_OPT_FLAG_VIDEO_PARAM)) < 0 ||
+                (ret = ffm_write_header_codec_private_ctx(s->pb, codec, AV_OPT_FLAG_VIDEO_PARAM)) < 0)
                 return ret;
             break;
         case AVMEDIA_TYPE_AUDIO:
-            avio_wb32(pb, codec->sample_rate);
-            avio_wl16(pb, codec->channels);
-            avio_wl16(pb, codec->frame_size);
-            write_header_chunk(s->pb, pb, MKBETAG('S', 'T', 'A', 'U'));
-            if ((ret = ffm_write_header_codec_private_ctx(s->pb, codec, AV_OPT_FLAG_AUDIO_PARAM)) < 0)
+            if ((ret = ffm_write_header_codec_ctx(s->pb, codec, MKBETAG('S', '2', 'A', 'U'), AV_OPT_FLAG_AUDIO_PARAM)) < 0 ||
+                (ret = ffm_write_header_codec_private_ctx(s->pb, codec, AV_OPT_FLAG_AUDIO_PARAM)) < 0)
                 return ret;
             break;
         default: