lavf/ffm: store/restore private codec context
authorLukasz Marek <lukasz.m.luki2@gmail.com>
Mon, 10 Nov 2014 22:22:59 +0000 (23:22 +0100)
committerLukasz Marek <lukasz.m.luki2@gmail.com>
Sun, 16 Nov 2014 00:13:38 +0000 (01:13 +0100)
Signed-off-by: Lukasz Marek <lukasz.m.luki2@gmail.com>
doc/APIchanges
libavformat/avformat.h
libavformat/ffmdec.c
libavformat/ffmenc.c
libavformat/utils.c
libavformat/version.h

index b4a3ed8..79cccd2 100644 (file)
@@ -15,6 +15,9 @@ libavutil:     2014-08-09
 
 API changes, most recent first:
 
+2014-11-16 - xxxxxxx - lavf 56.13.0 - avformat.h
+  Add AVStream.recommended_encoder_configuration with accessors.
+
 2014-11-16 - xxxxxxx - lavu 54.13.0 - opt.h
   Add av_opt_serialize().
 
index 3733549..56ab4e1 100644 (file)
@@ -1097,11 +1097,19 @@ typedef struct AVStream {
      */
     int inject_global_side_data;
 
+    /**
+     * String containing paris of key and values describing recommended encoder configuration.
+     * Paris are separated by ','.
+     * Keys are separated from values by '='.
+     */
+    char *recommended_encoder_configuration;
 } AVStream;
 
 AVRational av_stream_get_r_frame_rate(const AVStream *s);
 void       av_stream_set_r_frame_rate(AVStream *s, AVRational r);
 struct AVCodecParserContext *av_stream_get_parser(const AVStream *s);
+char* av_stream_get_recommended_encoder_configuration(const AVStream *s);
+void  av_stream_set_recommended_encoder_configuration(AVStream *s, char *configuration);
 
 /**
  * Returns the pts of the last muxed packet + its duration
index 448762b..1c848b9 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "libavutil/intreadwrite.h"
 #include "libavutil/intfloat.h"
+#include "libavutil/opt.h"
 #include "avformat.h"
 #include "internal.h"
 #include "ffm.h"
@@ -237,6 +238,8 @@ 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;
 
     ffm->packet_size = avio_rb32(pb);
     if (ffm->packet_size != FFM_PACKET_SIZE) {
@@ -267,10 +270,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,12 +299,13 @@ 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) {
+            break;
+            //TODO: reident
             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);
@@ -343,10 +352,27 @@ static int ffm2_read_header(AVFormatContext *s)
                 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) {
+                st->recommended_encoder_configuration = av_malloc(size + 1);
+                if (!st->recommended_encoder_configuration) {
+                    ret = AVERROR(ENOMEM);
+                    goto fail;
+                }
+                avio_get_str(pb, size, st->recommended_encoder_configuration, size + 1);
             }
             break;
         }
index eb809eb..e0885e7 100644 (file)
@@ -23,6 +23,7 @@
 #include "libavutil/intfloat.h"
 #include "libavutil/avassert.h"
 #include "libavutil/parseutils.h"
+#include "libavutil/opt.h"
 #include "avformat.h"
 #include "internal.h"
 #include "ffm.h"
@@ -93,6 +94,32 @@ static void write_header_chunk(AVIOContext *pb, AVIOContext *dpb, unsigned id)
     av_free(dyn_buf);
 }
 
+static int ffm_write_header_codec_private_ctx(AVIOContext *pb, AVCodecContext *ctx, int type)
+{
+    AVIOContext *tmp;
+    char *buf = NULL;
+    int ret;
+    const AVCodec *enc = ctx->codec ? ctx->codec : avcodec_find_encoder(ctx->codec_id);
+
+    if (!enc)
+        return AVERROR(EINVAL);
+    if (ctx->priv_data && enc->priv_class && enc->priv_data_size) {
+        if ((ret = av_opt_serialize(ctx->priv_data, AV_OPT_FLAG_ENCODING_PARAM | type,
+                                    AV_OPT_SERIALIZE_SKIP_DEFAULTS, &buf, '=', ',')) < 0)
+            return ret;
+        if (buf && strlen(buf)) {
+            if (avio_open_dyn_buf(&tmp) < 0) {
+                av_free(buf);
+                return AVERROR(ENOMEM);
+            }
+            avio_put_str(tmp, buf);
+            write_header_chunk(pb, tmp, MKBETAG('C', 'P', 'R', 'V'));
+        }
+        av_free(buf);
+    }
+    return 0;
+}
+
 static int ffm_write_header(AVFormatContext *s)
 {
     FFMContext *ffm = s->priv_data;
@@ -100,10 +127,10 @@ static int ffm_write_header(AVFormatContext *s)
     AVStream *st;
     AVIOContext *pb = s->pb;
     AVCodecContext *codec;
-    int bit_rate, i;
+    int bit_rate, i, ret;
 
     if (t = av_dict_get(s->metadata, "creation_time", NULL, 0)) {
-        int ret = av_parse_time(&ffm->start_time, t->value, 0);
+        ret = av_parse_time(&ffm->start_time, t->value, 0);
         if (ret < 0)
             return ret;
     }
@@ -197,12 +224,16 @@ static int ffm_write_header(AVFormatContext *s)
             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)
+                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)
+                return ret;
             break;
         default:
             return -1;
index 8da8db4..39851fc 100644 (file)
@@ -103,6 +103,7 @@ static int64_t wrap_timestamp(AVStream *st, int64_t timestamp)
 }
 
 MAKE_ACCESSORS(AVStream, stream, AVRational, r_frame_rate)
+MAKE_ACCESSORS(AVStream, stream, char *, recommended_encoder_configuration)
 MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, video_codec)
 MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, audio_codec)
 MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, subtitle_codec)
@@ -3537,6 +3538,7 @@ void ff_free_stream(AVFormatContext *s, AVStream *st) {
     if (st->info)
         av_freep(&st->info->duration_error);
     av_freep(&st->info);
+    av_freep(&st->recommended_encoder_configuration);
     av_freep(&s->streams[ --s->nb_streams ]);
 }
 
index 4596175..27f2861 100644 (file)
@@ -30,8 +30,8 @@
 #include "libavutil/version.h"
 
 #define LIBAVFORMAT_VERSION_MAJOR 56
-#define LIBAVFORMAT_VERSION_MINOR  12
-#define LIBAVFORMAT_VERSION_MICRO 103
+#define LIBAVFORMAT_VERSION_MINOR  13
+#define LIBAVFORMAT_VERSION_MICRO 100
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
                                                LIBAVFORMAT_VERSION_MINOR, \