On 12.11.2014 02:12, Michael Niedermayer wrote:
On Tue, Nov 11, 2014 at 11:59:32PM +0100, Lukasz Marek wrote:
On 11.11.2014 14:46, Michael Niedermayer wrote:
the muxer might run in a seperate thread from the encoder, priv_data
could change while its being accessed, iam not sure if that would
cause some race here or not

Wouldn't it regard AVCodecContext.variables too?

potentially yes for fields which are not expected to be accessed



Also i dont think its guranteed that priv_data starts with a AVClass

Fixed patch attached


  avformat.h |    7 +++++++
  ffmdec.c   |   36 +++++++++++++++++++++++++++++++-----
  ffmenc.c   |   34 ++++++++++++++++++++++++++++++++--
  utils.c    |    1 +
  4 files changed, 71 insertions(+), 7 deletions(-)
3807f44019d60c346dee78e968e195ab783565ee  
0001-lavf-ffm-store-restore-private-codec-context.patch
 From af7c72d8d62e26c4b8fe9d8a758707532e727830 Mon Sep 17 00:00:00 2001
From: Lukasz Marek <lukasz.m.lu...@gmail.com>
Date: Mon, 10 Nov 2014 23:22:59 +0100
Subject: [PATCH 1/2] lavf/ffm: store/restore private codec context

TODO: bump minor

Signed-off-by: Lukasz Marek <lukasz.m.lu...@gmail.com>
---
  libavformat/avformat.h |  7 +++++++
  libavformat/ffmdec.c   | 36 +++++++++++++++++++++++++++++++-----
  libavformat/ffmenc.c   | 34 ++++++++++++++++++++++++++++++++--
  libavformat/utils.c    |  1 +
  4 files changed, 71 insertions(+), 7 deletions(-)

diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 3733549..474192d 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -905,6 +905,13 @@ typedef struct AVStream {
      int event_flags;
  #define AVSTREAM_EVENT_FLAG_METADATA_UPDATED 0x0001 ///< The call resulted in 
updated metadata.

+    /**
+     * 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;

this requires accessor functions for future ABI compatibility
also it should be documented what and who sets it, unless its
intended to be changed how its set then it could be documented later
when the final design is implemented

I added these accessors.
Note: I added this field in public API section. From this comment I can suspect I should be private, so please verify.

>From 56781b29559d68f39d094800a4ae6e1586b8acca Mon Sep 17 00:00:00 2001
From: Lukasz Marek <lukasz.m.lu...@gmail.com>
Date: Mon, 10 Nov 2014 23:22:59 +0100
Subject: [PATCH] lavf/ffm: store/restore private codec context

TODO: bump minor

Signed-off-by: Lukasz Marek <lukasz.m.lu...@gmail.com>
---
 libavformat/avformat.h |  9 +++++++++
 libavformat/ffmdec.c   | 36 +++++++++++++++++++++++++++++++-----
 libavformat/ffmenc.c   | 35 +++++++++++++++++++++++++++++++++--
 libavformat/utils.c    |  2 ++
 4 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 3733549..1989016 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -905,6 +905,13 @@ typedef struct AVStream {
     int event_flags;
 #define AVSTREAM_EVENT_FLAG_METADATA_UPDATED 0x0001 ///< The call resulted in updated metadata.
 
+    /**
+     * 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;
+
     /*****************************************************************
      * All fields below this line are not part of the public API. They
      * may not be used outside of libavformat and can be changed and
@@ -1102,6 +1109,8 @@ typedef struct 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
diff --git a/libavformat/ffmdec.c b/libavformat/ffmdec.c
index 448762b..1c848b9 100644
--- a/libavformat/ffmdec.c
+++ b/libavformat/ffmdec.c
@@ -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;
         }
diff --git a/libavformat/ffmenc.c b/libavformat/ffmenc.c
index eb809eb..e0885e7 100644
--- a/libavformat/ffmenc.c
+++ b/libavformat/ffmenc.c
@@ -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;
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 8da8db4..39851fc 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -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 ]);
 }
 
-- 
1.9.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to