[FFmpeg-devel] [PATCH 3/9] lavf/ffm: store/restore private codec context

Michael Niedermayer michaelni at gmx.at
Tue Nov 11 14:46:25 CET 2014


On Tue, Nov 11, 2014 at 08:31:25AM +0100, Lukasz Marek wrote:
> TODO: bump micro
> 
> Signed-off-by: Lukasz Marek <lukasz.m.luki2 at gmail.com>
> ---
>  libavformat/ffmdec.c | 41 ++++++++++++++++++++++++++++++++++++-----
>  libavformat/ffmenc.c | 27 +++++++++++++++++++++++++--
>  2 files changed, 61 insertions(+), 7 deletions(-)
> 
> diff --git a/libavformat/ffmdec.c b/libavformat/ffmdec.c
> index 448762b..bba3b36 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;
> +    char *buffer;
>  
>      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,11 +352,33 @@ 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;
> +            }
> +            codec->codec = avcodec_find_encoder(codec->codec_id);
> +            buffer = av_malloc(size + 1);
> +            codec->priv_data = av_mallocz(codec->codec->priv_data_size);
> +            if (!buffer || !codec->priv_data) {
> +                av_free(buffer);
> +                av_freep(&codec->priv_data);
> +                ret = AVERROR(ENOMEM);
> +                goto fail;
>              }
> +            *(const AVClass**)codec->priv_data = codec->codec->priv_class;
> +            av_opt_set_defaults(codec->priv_data);
> +            avio_get_str(pb, size, buffer, size + 1);
> +            av_set_options_string(codec->priv_data, buffer, "=", ",");
> +            av_freep(&buffer);
>              break;
>          }
>          avio_seek(pb, next, SEEK_SET);
> diff --git a/libavformat/ffmenc.c b/libavformat/ffmenc.c
> index eb809eb..f307f8f 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,24 @@ 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, void *priv_data, int type)
> +{
> +    AVIOContext *tmp;
> +    char *buf = NULL;
> +
> +    if (priv_data) {
> +        if (avio_open_dyn_buf(&tmp) < 0)
> +            return AVERROR(ENOMEM);
> +        av_opt_serialize(priv_data, AV_OPT_FLAG_ENCODING_PARAM | type, 1, &buf, '=', ',');
> +        if (buf && strlen(buf)) {
> +            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 +119,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 +216,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->priv_data, 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->priv_data, AV_OPT_FLAG_AUDIO_PARAM)) < 0)
> +                return ret;

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

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

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Those who are too smart to engage in politics are punished by being
governed by those who are dumber. -- Plato 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20141111/541501b7/attachment.asc>


More information about the ffmpeg-devel mailing list