diff mbox

[FFmpeg-devel,2/5] avformat/ffmdec: replace most codec uses by codecpar

Message ID 20161202235258.26223-2-michael@niedermayer.cc
State Accepted
Headers show

Commit Message

Michael Niedermayer Dec. 2, 2016, 11:52 p.m. UTC
This is a bit messy as codecar does not support AVOptions so we need
to use AVCodecContext where AVOptions are required and copy back and forth.

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
 libavformat/ffmdec.c | 159 ++++++++++++++++++++++++++-------------------------
 1 file changed, 82 insertions(+), 77 deletions(-)

Comments

Hendrik Leppkes Dec. 2, 2016, 11:57 p.m. UTC | #1
On Sat, Dec 3, 2016 at 12:52 AM, Michael Niedermayer
<michael@niedermayer.cc> wrote:
> This is a bit messy as codecar does not support AVOptions so we need
> to use AVCodecContext where AVOptions are required and copy back and forth.
>

ffmenc can't really write any data that doesn't go into codecpar
either, since thats all muxers get for stream info, so is this really
required? Where do these come from?

- Hendrik
Michael Niedermayer Dec. 3, 2016, 12:18 a.m. UTC | #2
On Sat, Dec 03, 2016 at 12:57:49AM +0100, Hendrik Leppkes wrote:
> On Sat, Dec 3, 2016 at 12:52 AM, Michael Niedermayer
> <michael@niedermayer.cc> wrote:
> > This is a bit messy as codecar does not support AVOptions so we need
> > to use AVCodecContext where AVOptions are required and copy back and forth.
> >
> 

> ffmenc can't really write any data that doesn't go into codecpar
> either, since thats all muxers get for stream info, so is this really
> required? Where do these come from?

ffmenc takes the string from AVStream.recommended_encoder_configuration
and stores it, ffmdec reads it back into
AVStream.recommended_encoder_configuration

It is just needed to make sure codecpar matches this, which would be
easier if AVOptions would work with codecpar as then it could be
directly set from the string description.

[...]
Andreas Cadhalpun Dec. 3, 2016, 12:19 a.m. UTC | #3
On 03.12.2016 00:52, Michael Niedermayer wrote:
> This is a bit messy as codecar does not support AVOptions so we need
> to use AVCodecContext where AVOptions are required and copy back and forth.
> 
> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
> ---
>  libavformat/ffmdec.c | 159 ++++++++++++++++++++++++++-------------------------
>  1 file changed, 82 insertions(+), 77 deletions(-)
> 
> diff --git a/libavformat/ffmdec.c b/libavformat/ffmdec.c
> index 9192bff507..25edeebb7e 100644
> --- a/libavformat/ffmdec.c
> +++ b/libavformat/ffmdec.c
> @@ -250,11 +250,6 @@ static void adjust_write_index(AVFormatContext *s)
>  
>  static int ffm_close(AVFormatContext *s)
>  {
> -    int i;
> -
> -    for (i = 0; i < s->nb_streams; i++)
> -        av_freep(&s->streams[i]->codec->rc_eq);
> -
>      return 0;
>  }

Why not remove the entire function?

> @@ -514,9 +518,6 @@ static int ffm2_read_header(AVFormatContext *s)
>          avio_seek(pb, next, SEEK_SET);
>      }
>  
> -    for (i = 0; i < s->nb_streams; i++)
> -        avcodec_parameters_from_context(s->streams[i]->codecpar, s->streams[i]->codec);
> -

This loop is the only place the variable i is used, so please remove it's
declaration, too.

> @@ -539,7 +542,8 @@ static int ffm_read_header(AVFormatContext *s)
>      FFMContext *ffm = s->priv_data;
>      AVStream *st;
>      AVIOContext *pb = s->pb;
> -    AVCodecContext *codec;
> +    AVCodecContext *codec, *dummy_codec = NULL;
> +    AVCodecParameters *codecpar;
>      const AVCodecDescriptor *codec_desc;
>      int i, nb_streams, ret;
>      uint32_t tag;
> @@ -562,6 +566,7 @@ static int ffm_read_header(AVFormatContext *s)
>      } else {
>          ffm->file_size = (UINT64_C(1) << 63) - 1;
>      }
> +    dummy_codec = avcodec_alloc_context3(NULL);
>  
>      nb_streams = avio_rb32(pb);
>      avio_rb32(pb); /* total bitrate */
> @@ -577,31 +582,31 @@ static int ffm_read_header(AVFormatContext *s)
>  
>          codec = st->codec;

Here should be:
           codecpar = st->codecpar;

>          /* generic info */
> -        codec->codec_id = avio_rb32(pb);
> -        codec_desc = avcodec_descriptor_get(codec->codec_id);
> +        codecpar->codec_id = avio_rb32(pb);

Otherwise codecpar is uninitialized here.

Best regards,
Andreas
Andreas Cadhalpun Dec. 3, 2016, 11:47 a.m. UTC | #4
On 03.12.2016 00:52, Michael Niedermayer wrote:
> @@ -400,16 +398,16 @@ static int ffm2_read_header(AVFormatContext *s)
>                  ret = AVERROR_INVALIDDATA;
>                  goto fail;
>              }
> -            codec->width = avio_rb16(pb);
> -            codec->height = avio_rb16(pb);
> -            ret = av_image_check_size(codec->width, codec->height, 0, s);
> +            codecpar->width = avio_rb16(pb);
> +            codecpar->height = avio_rb16(pb);
> +            ret = av_image_check_size(codecpar->width, codecpar->height, 0, s);
>              if (ret < 0)
>                  goto fail;
>              avio_rb16(pb);
> -            codec->pix_fmt = avio_rb32(pb);
> -            if (!av_pix_fmt_desc_get(codec->pix_fmt)) {
> -                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codec->pix_fmt);
> -                codec->pix_fmt = AV_PIX_FMT_NONE;
> +            codecpar->format = avio_rb32(pb);

This change isn't as simple as it looks, because while the pix_fmt field exclusively
contains AVPixelFormat values, the format field is shared with AVSampleFormat.
Thus there now needs to be a check to ensure that codec_type is AVMEDIA_TYPE_VIDEO.

> +            if (!av_pix_fmt_desc_get(codecpar->format)) {
> +                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codecpar->format);
> +                codecpar->format = AV_PIX_FMT_NONE;
>                  goto fail;
>              }
>              avio_r8(pb);


> @@ -610,15 +615,15 @@ static int ffm_read_header(AVFormatContext *s)
>                         codec->time_base.num, codec->time_base.den);
>                  goto fail;
>              }
> -            codec->width = avio_rb16(pb);
> -            codec->height = avio_rb16(pb);
> -            if (av_image_check_size(codec->width, codec->height, 0, s) < 0)
> +            codecpar->width = avio_rb16(pb);
> +            codecpar->height = avio_rb16(pb);
> +            if (av_image_check_size(codecpar->width, codecpar->height, 0, s) < 0)
>                  goto fail;
>              avio_rb16(pb);
> -            codec->pix_fmt = avio_rb32(pb);
> -            if (!av_pix_fmt_desc_get(codec->pix_fmt)) {
> -                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codec->pix_fmt);
> -                codec->pix_fmt = AV_PIX_FMT_NONE;
> +            codecpar->format = avio_rb32(pb);

Same here.

> +            if (!av_pix_fmt_desc_get(codecpar->format)) {
> +                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codecpar->format);
> +                codecpar->format = AV_PIX_FMT_NONE;
>                  goto fail;
>              }
>              avio_r8(pb);

Best regards,
Andreas
Michael Niedermayer Dec. 3, 2016, 12:31 p.m. UTC | #5
On Sat, Dec 03, 2016 at 01:19:05AM +0100, Andreas Cadhalpun wrote:
> On 03.12.2016 00:52, Michael Niedermayer wrote:
> > This is a bit messy as codecar does not support AVOptions so we need
> > to use AVCodecContext where AVOptions are required and copy back and forth.
> > 
> > Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
> > ---
> >  libavformat/ffmdec.c | 159 ++++++++++++++++++++++++++-------------------------
> >  1 file changed, 82 insertions(+), 77 deletions(-)
> > 
> > diff --git a/libavformat/ffmdec.c b/libavformat/ffmdec.c
> > index 9192bff507..25edeebb7e 100644
> > --- a/libavformat/ffmdec.c
> > +++ b/libavformat/ffmdec.c
> > @@ -250,11 +250,6 @@ static void adjust_write_index(AVFormatContext *s)
> >  
> >  static int ffm_close(AVFormatContext *s)
> >  {
> > -    int i;
> > -
> > -    for (i = 0; i < s->nb_streams; i++)
> > -        av_freep(&s->streams[i]->codec->rc_eq);
> > -
> >      return 0;
> >  }
> 
> Why not remove the entire function?
> 
> > @@ -514,9 +518,6 @@ static int ffm2_read_header(AVFormatContext *s)
> >          avio_seek(pb, next, SEEK_SET);
> >      }
> >  
> > -    for (i = 0; i < s->nb_streams; i++)
> > -        avcodec_parameters_from_context(s->streams[i]->codecpar, s->streams[i]->codec);
> > -
> 
> This loop is the only place the variable i is used, so please remove it's
> declaration, too.
> 
> > @@ -539,7 +542,8 @@ static int ffm_read_header(AVFormatContext *s)
> >      FFMContext *ffm = s->priv_data;
> >      AVStream *st;
> >      AVIOContext *pb = s->pb;
> > -    AVCodecContext *codec;
> > +    AVCodecContext *codec, *dummy_codec = NULL;
> > +    AVCodecParameters *codecpar;
> >      const AVCodecDescriptor *codec_desc;
> >      int i, nb_streams, ret;
> >      uint32_t tag;
> > @@ -562,6 +566,7 @@ static int ffm_read_header(AVFormatContext *s)
> >      } else {
> >          ffm->file_size = (UINT64_C(1) << 63) - 1;
> >      }
> > +    dummy_codec = avcodec_alloc_context3(NULL);
> >  
> >      nb_streams = avio_rb32(pb);
> >      avio_rb32(pb); /* total bitrate */
> > @@ -577,31 +582,31 @@ static int ffm_read_header(AVFormatContext *s)
> >  
> >          codec = st->codec;
> 
> Here should be:
>            codecpar = st->codecpar;
> 
> >          /* generic info */
> > -        codec->codec_id = avio_rb32(pb);
> > -        codec_desc = avcodec_descriptor_get(codec->codec_id);
> > +        codecpar->codec_id = avio_rb32(pb);
> 
> Otherwise codecpar is uninitialized here.

all done locally, some of this code is btw not tested by fate

thx


[...]
Michael Niedermayer Dec. 3, 2016, 12:37 p.m. UTC | #6
On Sat, Dec 03, 2016 at 12:47:45PM +0100, Andreas Cadhalpun wrote:
> On 03.12.2016 00:52, Michael Niedermayer wrote:
> > @@ -400,16 +398,16 @@ static int ffm2_read_header(AVFormatContext *s)
> >                  ret = AVERROR_INVALIDDATA;
> >                  goto fail;
> >              }
> > -            codec->width = avio_rb16(pb);
> > -            codec->height = avio_rb16(pb);
> > -            ret = av_image_check_size(codec->width, codec->height, 0, s);
> > +            codecpar->width = avio_rb16(pb);
> > +            codecpar->height = avio_rb16(pb);
> > +            ret = av_image_check_size(codecpar->width, codecpar->height, 0, s);
> >              if (ret < 0)
> >                  goto fail;
> >              avio_rb16(pb);
> > -            codec->pix_fmt = avio_rb32(pb);
> > -            if (!av_pix_fmt_desc_get(codec->pix_fmt)) {
> > -                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codec->pix_fmt);
> > -                codec->pix_fmt = AV_PIX_FMT_NONE;
> > +            codecpar->format = avio_rb32(pb);
> 
> This change isn't as simple as it looks, because while the pix_fmt field exclusively
> contains AVPixelFormat values, the format field is shared with AVSampleFormat.
> Thus there now needs to be a check to ensure that codec_type is AVMEDIA_TYPE_VIDEO.

ill add these checks as a seperate patch so it can be backported
easier

[...]
Michael Niedermayer Dec. 3, 2016, 12:39 p.m. UTC | #7
On Sat, Dec 03, 2016 at 12:47:45PM +0100, Andreas Cadhalpun wrote:
> On 03.12.2016 00:52, Michael Niedermayer wrote:
> > @@ -400,16 +398,16 @@ static int ffm2_read_header(AVFormatContext *s)
> >                  ret = AVERROR_INVALIDDATA;
> >                  goto fail;
> >              }
> > -            codec->width = avio_rb16(pb);
> > -            codec->height = avio_rb16(pb);
> > -            ret = av_image_check_size(codec->width, codec->height, 0, s);
> > +            codecpar->width = avio_rb16(pb);
> > +            codecpar->height = avio_rb16(pb);
> > +            ret = av_image_check_size(codecpar->width, codecpar->height, 0, s);
> >              if (ret < 0)
> >                  goto fail;
> >              avio_rb16(pb);
> > -            codec->pix_fmt = avio_rb32(pb);
> > -            if (!av_pix_fmt_desc_get(codec->pix_fmt)) {
> > -                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codec->pix_fmt);
> > -                codec->pix_fmt = AV_PIX_FMT_NONE;
> > +            codecpar->format = avio_rb32(pb);
> 
> This change isn't as simple as it looks, because while the pix_fmt field exclusively
> contains AVPixelFormat values, the format field is shared with AVSampleFormat.
> Thus there now needs to be a check to ensure that codec_type is AVMEDIA_TYPE_VIDEO.
> 
> > +            if (!av_pix_fmt_desc_get(codecpar->format)) {
> > +                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codecpar->format);
> > +                codecpar->format = AV_PIX_FMT_NONE;
> >                  goto fail;
> >              }
> >              avio_r8(pb);
> 
> 

> > @@ -610,15 +615,15 @@ static int ffm_read_header(AVFormatContext *s)
> >                         codec->time_base.num, codec->time_base.den);
> >                  goto fail;
> >              }
> > -            codec->width = avio_rb16(pb);
> > -            codec->height = avio_rb16(pb);
> > -            if (av_image_check_size(codec->width, codec->height, 0, s) < 0)
> > +            codecpar->width = avio_rb16(pb);
> > +            codecpar->height = avio_rb16(pb);
> > +            if (av_image_check_size(codecpar->width, codecpar->height, 0, s) < 0)
> >                  goto fail;
> >              avio_rb16(pb);
> > -            codec->pix_fmt = avio_rb32(pb);
> > -            if (!av_pix_fmt_desc_get(codec->pix_fmt)) {
> > -                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codec->pix_fmt);
> > -                codec->pix_fmt = AV_PIX_FMT_NONE;
> > +            codecpar->format = avio_rb32(pb);
> 
> Same here.

not the same, this is under a codec_type check

[...]
Andreas Cadhalpun Dec. 3, 2016, 1:07 p.m. UTC | #8
On 03.12.2016 13:31, Michael Niedermayer wrote:
> all done locally,

Thanks, patch is OK then.

> some of this code is btw not tested by fate

Yes, the FFM1 code path is not tested by FATE.

Personally I think it would make more sense to remove support for FFM1
than adding a FATE test for it.
The commit message of 9829ec1 introducing FFM2 in 2012 said:
"Currently FFM files generated with one versions of ffmpeg generally
cannot be read by another."

So if there are still any FFM1 files from that time, I doubt current
ffmpeg could decode them correctly.

Best regards,
Andreas
Andreas Cadhalpun Dec. 3, 2016, 1:07 p.m. UTC | #9
On 03.12.2016 13:37, Michael Niedermayer wrote:
> On Sat, Dec 03, 2016 at 12:47:45PM +0100, Andreas Cadhalpun wrote:
>> On 03.12.2016 00:52, Michael Niedermayer wrote:
>>> @@ -400,16 +398,16 @@ static int ffm2_read_header(AVFormatContext *s)
>>>                  ret = AVERROR_INVALIDDATA;
>>>                  goto fail;
>>>              }
>>> -            codec->width = avio_rb16(pb);
>>> -            codec->height = avio_rb16(pb);
>>> -            ret = av_image_check_size(codec->width, codec->height, 0, s);
>>> +            codecpar->width = avio_rb16(pb);
>>> +            codecpar->height = avio_rb16(pb);
>>> +            ret = av_image_check_size(codecpar->width, codecpar->height, 0, s);
>>>              if (ret < 0)
>>>                  goto fail;
>>>              avio_rb16(pb);
>>> -            codec->pix_fmt = avio_rb32(pb);
>>> -            if (!av_pix_fmt_desc_get(codec->pix_fmt)) {
>>> -                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codec->pix_fmt);
>>> -                codec->pix_fmt = AV_PIX_FMT_NONE;
>>> +            codecpar->format = avio_rb32(pb);
>>
>> This change isn't as simple as it looks, because while the pix_fmt field exclusively
>> contains AVPixelFormat values, the format field is shared with AVSampleFormat.
>> Thus there now needs to be a check to ensure that codec_type is AVMEDIA_TYPE_VIDEO.
> 
> ill add these checks as a seperate patch so it can be backported
> easier

OK.

Best regards,
Andreas
Andreas Cadhalpun Dec. 3, 2016, 1:08 p.m. UTC | #10
On 03.12.2016 13:39, Michael Niedermayer wrote:
> On Sat, Dec 03, 2016 at 12:47:45PM +0100, Andreas Cadhalpun wrote:
>> On 03.12.2016 00:52, Michael Niedermayer wrote:
>>> @@ -400,16 +398,16 @@ static int ffm2_read_header(AVFormatContext *s)
>>>                  ret = AVERROR_INVALIDDATA;
>>>                  goto fail;
>>>              }
>>> -            codec->width = avio_rb16(pb);
>>> -            codec->height = avio_rb16(pb);
>>> -            ret = av_image_check_size(codec->width, codec->height, 0, s);
>>> +            codecpar->width = avio_rb16(pb);
>>> +            codecpar->height = avio_rb16(pb);
>>> +            ret = av_image_check_size(codecpar->width, codecpar->height, 0, s);
>>>              if (ret < 0)
>>>                  goto fail;
>>>              avio_rb16(pb);
>>> -            codec->pix_fmt = avio_rb32(pb);
>>> -            if (!av_pix_fmt_desc_get(codec->pix_fmt)) {
>>> -                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codec->pix_fmt);
>>> -                codec->pix_fmt = AV_PIX_FMT_NONE;
>>> +            codecpar->format = avio_rb32(pb);
>>
>> This change isn't as simple as it looks, because while the pix_fmt field exclusively
>> contains AVPixelFormat values, the format field is shared with AVSampleFormat.
>> Thus there now needs to be a check to ensure that codec_type is AVMEDIA_TYPE_VIDEO.
>>
>>> +            if (!av_pix_fmt_desc_get(codecpar->format)) {
>>> +                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codecpar->format);
>>> +                codecpar->format = AV_PIX_FMT_NONE;
>>>                  goto fail;
>>>              }
>>>              avio_r8(pb);
>>
>>
> 
>>> @@ -610,15 +615,15 @@ static int ffm_read_header(AVFormatContext *s)
>>>                         codec->time_base.num, codec->time_base.den);
>>>                  goto fail;
>>>              }
>>> -            codec->width = avio_rb16(pb);
>>> -            codec->height = avio_rb16(pb);
>>> -            if (av_image_check_size(codec->width, codec->height, 0, s) < 0)
>>> +            codecpar->width = avio_rb16(pb);
>>> +            codecpar->height = avio_rb16(pb);
>>> +            if (av_image_check_size(codecpar->width, codecpar->height, 0, s) < 0)
>>>                  goto fail;
>>>              avio_rb16(pb);
>>> -            codec->pix_fmt = avio_rb32(pb);
>>> -            if (!av_pix_fmt_desc_get(codec->pix_fmt)) {
>>> -                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codec->pix_fmt);
>>> -                codec->pix_fmt = AV_PIX_FMT_NONE;
>>> +            codecpar->format = avio_rb32(pb);
>>
>> Same here.
> 
> not the same, this is under a codec_type check

Indeed.

Best regards,
Andreas
diff mbox

Patch

diff --git a/libavformat/ffmdec.c b/libavformat/ffmdec.c
index 9192bff507..25edeebb7e 100644
--- a/libavformat/ffmdec.c
+++ b/libavformat/ffmdec.c
@@ -250,11 +250,6 @@  static void adjust_write_index(AVFormatContext *s)
 
 static int ffm_close(AVFormatContext *s)
 {
-    int i;
-
-    for (i = 0; i < s->nb_streams; i++)
-        av_freep(&s->streams[i]->codec->rc_eq);
-
     return 0;
 }
 
@@ -281,7 +276,7 @@  static int ffm_append_recommended_configuration(AVStream *st, char **conf)
 
 #define VALIDATE_PARAMETER(parameter, name, check) {                              \
     if (check) {                                                                  \
-        av_log(codec, AV_LOG_ERROR, "Invalid " name " %d\n", codec->parameter);   \
+        av_log(codec, AV_LOG_ERROR, "Invalid " name " %d\n", codecpar->parameter);   \
         ret = AVERROR_INVALIDDATA;                                                \
         goto fail;                                                                \
     }                                                                             \
@@ -292,7 +287,8 @@  static int ffm2_read_header(AVFormatContext *s)
     FFMContext *ffm = s->priv_data;
     AVStream *st;
     AVIOContext *pb = s->pb;
-    AVCodecContext *codec;
+    AVCodecContext *codec, *dummy_codec = NULL;
+    AVCodecParameters *codecpar;
     const AVCodecDescriptor *codec_desc;
     int ret, i;
     int f_main = 0, f_cprv = -1, f_stvi = -1, f_stau = -1;
@@ -316,6 +312,7 @@  static int ffm2_read_header(AVFormatContext *s)
     } else {
         ffm->file_size = (UINT64_C(1) << 63) - 1;
     }
+    dummy_codec = avcodec_alloc_context3(NULL);
 
     while(!avio_feof(pb)) {
         unsigned id = avio_rb32(pb);
@@ -346,27 +343,28 @@  static int ffm2_read_header(AVFormatContext *s)
             avpriv_set_pts_info(st, 64, 1, 1000000);
 
             codec = st->codec;
+            codecpar = st->codecpar;
             /* generic info */
-            codec->codec_id = avio_rb32(pb);
-            codec_desc = avcodec_descriptor_get(codec->codec_id);
+            codecpar->codec_id = avio_rb32(pb);
+            codec_desc = avcodec_descriptor_get(codecpar->codec_id);
             if (!codec_desc) {
-                av_log(s, AV_LOG_ERROR, "Invalid codec id: %d\n", codec->codec_id);
-                codec->codec_id = AV_CODEC_ID_NONE;
+                av_log(s, AV_LOG_ERROR, "Invalid codec id: %d\n", codecpar->codec_id);
+                codecpar->codec_id = AV_CODEC_ID_NONE;
                 ret = AVERROR_INVALIDDATA;
                 goto fail;
             }
-            codec->codec_type = avio_r8(pb);
-            if (codec->codec_type != codec_desc->type) {
+            codecpar->codec_type = avio_r8(pb);
+            if (codecpar->codec_type != codec_desc->type) {
                 av_log(s, AV_LOG_ERROR, "Codec type mismatch: expected %d, found %d\n",
-                       codec_desc->type, codec->codec_type);
-                codec->codec_id = AV_CODEC_ID_NONE;
-                codec->codec_type = AVMEDIA_TYPE_UNKNOWN;
+                       codec_desc->type, codecpar->codec_type);
+                codecpar->codec_id = AV_CODEC_ID_NONE;
+                codecpar->codec_type = AVMEDIA_TYPE_UNKNOWN;
                 ret = AVERROR_INVALIDDATA;
                 goto fail;
             }
-            codec->bit_rate = avio_rb32(pb);
-            if (codec->bit_rate < 0) {
-                av_log(codec, AV_LOG_ERROR, "Invalid bit rate %"PRId64"\n", codec->bit_rate);
+            codecpar->bit_rate = avio_rb32(pb);
+            if (codecpar->bit_rate < 0) {
+                av_log(codec, AV_LOG_ERROR, "Invalid bit rate %"PRId64"\n", codecpar->bit_rate);
                 ret = AVERROR_INVALIDDATA;
                 goto fail;
             }
@@ -380,11 +378,11 @@  static int ffm2_read_header(AVFormatContext *s)
                     ret = AVERROR_INVALIDDATA;
                     goto fail;
                 }
-                codec->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
-                if (!codec->extradata)
+                codecpar->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
+                if (!codecpar->extradata)
                     return AVERROR(ENOMEM);
-                codec->extradata_size = size;
-                avio_read(pb, codec->extradata, size);
+                codecpar->extradata_size = size;
+                avio_read(pb, codecpar->extradata, size);
             }
             break;
         case MKBETAG('S', 'T', 'V', 'I'):
@@ -400,16 +398,16 @@  static int ffm2_read_header(AVFormatContext *s)
                 ret = AVERROR_INVALIDDATA;
                 goto fail;
             }
-            codec->width = avio_rb16(pb);
-            codec->height = avio_rb16(pb);
-            ret = av_image_check_size(codec->width, codec->height, 0, s);
+            codecpar->width = avio_rb16(pb);
+            codecpar->height = avio_rb16(pb);
+            ret = av_image_check_size(codecpar->width, codecpar->height, 0, s);
             if (ret < 0)
                 goto fail;
             avio_rb16(pb);
-            codec->pix_fmt = avio_rb32(pb);
-            if (!av_pix_fmt_desc_get(codec->pix_fmt)) {
-                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codec->pix_fmt);
-                codec->pix_fmt = AV_PIX_FMT_NONE;
+            codecpar->format = avio_rb32(pb);
+            if (!av_pix_fmt_desc_get(codecpar->format)) {
+                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codecpar->format);
+                codecpar->format = AV_PIX_FMT_NONE;
                 goto fail;
             }
             avio_r8(pb);
@@ -437,7 +435,7 @@  static int ffm2_read_header(AVFormatContext *s)
             avio_rb32(pb);
             avio_rb32(pb);
             avio_rb64(pb);
-            codec->codec_tag = avio_rb32(pb);
+            codecpar->codec_tag = avio_rb32(pb);
             avio_r8(pb);
             avio_rb32(pb);
             avio_rb32(pb);
@@ -456,19 +454,19 @@  static int ffm2_read_header(AVFormatContext *s)
                 ret = AVERROR(EINVAL);
                 goto fail;
             }
-            codec->sample_rate = avio_rb32(pb);
-            VALIDATE_PARAMETER(sample_rate, "sample rate",        codec->sample_rate < 0)
-            codec->channels = avio_rl16(pb);
-            VALIDATE_PARAMETER(channels,    "number of channels", codec->channels < 0)
-            codec->frame_size = avio_rl16(pb);
-            VALIDATE_PARAMETER(frame_size,  "frame size",         codec->frame_size < 0)
+            codecpar->sample_rate = avio_rb32(pb);
+            VALIDATE_PARAMETER(sample_rate, "sample rate",        codecpar->sample_rate < 0)
+            codecpar->channels = avio_rl16(pb);
+            VALIDATE_PARAMETER(channels,    "number of channels", codecpar->channels < 0)
+            codecpar->frame_size = avio_rl16(pb);
+            VALIDATE_PARAMETER(frame_size,  "frame size",         codecpar->frame_size < 0)
             break;
         case MKBETAG('C', 'P', 'R', 'V'):
             if (f_cprv++) {
                 ret = AVERROR(EINVAL);
                 goto fail;
             }
-            enc = avcodec_find_encoder(codec->codec_id);
+            enc = avcodec_find_encoder(codecpar->codec_id);
             if (enc && enc->priv_data_size && enc->priv_class) {
                 buffer = av_malloc(size + 1);
                 if (!buffer) {
@@ -491,7 +489,10 @@  static int ffm2_read_header(AVFormatContext *s)
                 goto fail;
             }
             avio_get_str(pb, INT_MAX, buffer, size);
-            av_set_options_string(codec, buffer, "=", ",");
+            // The lack of AVOptions support in AVCodecParameters makes this back and forth copying needed
+            avcodec_parameters_to_context(dummy_codec, codecpar);
+            av_set_options_string(dummy_codec, buffer, "=", ",");
+            avcodec_parameters_from_context(codecpar, dummy_codec);
             if ((ret = ffm_append_recommended_configuration(st, &buffer)) < 0)
                 goto fail;
             break;
@@ -506,7 +507,10 @@  static int ffm2_read_header(AVFormatContext *s)
                 goto fail;
             }
             avio_get_str(pb, INT_MAX, buffer, size);
-            av_set_options_string(codec, buffer, "=", ",");
+            // The lack of AVOptions support in AVCodecParameters makes this back and forth copying needed
+            avcodec_parameters_to_context(dummy_codec, codecpar);
+            av_set_options_string(dummy_codec, buffer, "=", ",");
+            avcodec_parameters_from_context(codecpar, dummy_codec);
             if ((ret = ffm_append_recommended_configuration(st, &buffer)) < 0)
                 goto fail;
             break;
@@ -514,9 +518,6 @@  static int ffm2_read_header(AVFormatContext *s)
         avio_seek(pb, next, SEEK_SET);
     }
 
-    for (i = 0; i < s->nb_streams; i++)
-        avcodec_parameters_from_context(s->streams[i]->codecpar, s->streams[i]->codec);
-
     /* get until end of block reached */
     while ((avio_tell(pb) % ffm->packet_size) != 0 && !pb->eof_reached)
         avio_r8(pb);
@@ -528,8 +529,10 @@  static int ffm2_read_header(AVFormatContext *s)
     ffm->dts = 0;
     ffm->read_state = READ_HEADER;
     ffm->first_packet = 1;
+    avcodec_free_context(&dummy_codec);
     return 0;
  fail:
+    avcodec_free_context(&dummy_codec);
     ffm_close(s);
     return ret;
 }
@@ -539,7 +542,8 @@  static int ffm_read_header(AVFormatContext *s)
     FFMContext *ffm = s->priv_data;
     AVStream *st;
     AVIOContext *pb = s->pb;
-    AVCodecContext *codec;
+    AVCodecContext *codec, *dummy_codec = NULL;
+    AVCodecParameters *codecpar;
     const AVCodecDescriptor *codec_desc;
     int i, nb_streams, ret;
     uint32_t tag;
@@ -562,6 +566,7 @@  static int ffm_read_header(AVFormatContext *s)
     } else {
         ffm->file_size = (UINT64_C(1) << 63) - 1;
     }
+    dummy_codec = avcodec_alloc_context3(NULL);
 
     nb_streams = avio_rb32(pb);
     avio_rb32(pb); /* total bitrate */
@@ -577,31 +582,31 @@  static int ffm_read_header(AVFormatContext *s)
 
         codec = st->codec;
         /* generic info */
-        codec->codec_id = avio_rb32(pb);
-        codec_desc = avcodec_descriptor_get(codec->codec_id);
+        codecpar->codec_id = avio_rb32(pb);
+        codec_desc = avcodec_descriptor_get(codecpar->codec_id);
         if (!codec_desc) {
-            av_log(s, AV_LOG_ERROR, "Invalid codec id: %d\n", codec->codec_id);
-            codec->codec_id = AV_CODEC_ID_NONE;
+            av_log(s, AV_LOG_ERROR, "Invalid codec id: %d\n", codecpar->codec_id);
+            codecpar->codec_id = AV_CODEC_ID_NONE;
             goto fail;
         }
-        codec->codec_type = avio_r8(pb); /* codec_type */
-        if (codec->codec_type != codec_desc->type) {
+        codecpar->codec_type = avio_r8(pb); /* codec_type */
+        if (codecpar->codec_type != codec_desc->type) {
             av_log(s, AV_LOG_ERROR, "Codec type mismatch: expected %d, found %d\n",
-                   codec_desc->type, codec->codec_type);
-            codec->codec_id = AV_CODEC_ID_NONE;
-            codec->codec_type = AVMEDIA_TYPE_UNKNOWN;
+                   codec_desc->type, codecpar->codec_type);
+            codecpar->codec_id = AV_CODEC_ID_NONE;
+            codecpar->codec_type = AVMEDIA_TYPE_UNKNOWN;
             goto fail;
         }
-        codec->bit_rate = avio_rb32(pb);
-        if (codec->bit_rate < 0) {
-            av_log(codec, AV_LOG_WARNING, "Invalid bit rate %"PRId64"\n", codec->bit_rate);
+        codecpar->bit_rate = avio_rb32(pb);
+        if (codecpar->bit_rate < 0) {
+            av_log(codec, AV_LOG_WARNING, "Invalid bit rate %"PRId64"\n", codecpar->bit_rate);
             goto fail;
         }
         codec->flags = avio_rb32(pb);
         codec->flags2 = avio_rb32(pb);
         codec->debug = avio_rb32(pb);
         /* specific info */
-        switch(codec->codec_type) {
+        switch(codecpar->codec_type) {
         case AVMEDIA_TYPE_VIDEO:
             codec->time_base.num = avio_rb32(pb);
             codec->time_base.den = avio_rb32(pb);
@@ -610,15 +615,15 @@  static int ffm_read_header(AVFormatContext *s)
                        codec->time_base.num, codec->time_base.den);
                 goto fail;
             }
-            codec->width = avio_rb16(pb);
-            codec->height = avio_rb16(pb);
-            if (av_image_check_size(codec->width, codec->height, 0, s) < 0)
+            codecpar->width = avio_rb16(pb);
+            codecpar->height = avio_rb16(pb);
+            if (av_image_check_size(codecpar->width, codecpar->height, 0, s) < 0)
                 goto fail;
             avio_rb16(pb);
-            codec->pix_fmt = avio_rb32(pb);
-            if (!av_pix_fmt_desc_get(codec->pix_fmt)) {
-                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codec->pix_fmt);
-                codec->pix_fmt = AV_PIX_FMT_NONE;
+            codecpar->format = avio_rb32(pb);
+            if (!av_pix_fmt_desc_get(codecpar->format)) {
+                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codecpar->format);
+                codecpar->format = AV_PIX_FMT_NONE;
                 goto fail;
             }
             avio_r8(pb);
@@ -646,7 +651,7 @@  static int ffm_read_header(AVFormatContext *s)
             avio_rb32(pb);
             avio_rb32(pb);
             avio_rb64(pb);
-            codec->codec_tag = avio_rb32(pb);
+            codecpar->codec_tag = avio_rb32(pb);
             avio_r8(pb);
             avio_rb32(pb);
             avio_rb32(pb);
@@ -661,12 +666,12 @@  static int ffm_read_header(AVFormatContext *s)
             avio_rb32(pb);
             break;
         case AVMEDIA_TYPE_AUDIO:
-            codec->sample_rate = avio_rb32(pb);
-            VALIDATE_PARAMETER(sample_rate, "sample rate",        codec->sample_rate < 0)
-            codec->channels = avio_rl16(pb);
-            VALIDATE_PARAMETER(channels,    "number of channels", codec->channels < 0)
-            codec->frame_size = avio_rl16(pb);
-            VALIDATE_PARAMETER(frame_size,  "frame size",         codec->frame_size < 0)
+            codecpar->sample_rate = avio_rb32(pb);
+            VALIDATE_PARAMETER(sample_rate, "sample rate",        codecpar->sample_rate < 0)
+            codecpar->channels = avio_rl16(pb);
+            VALIDATE_PARAMETER(channels,    "number of channels", codecpar->channels < 0)
+            codecpar->frame_size = avio_rl16(pb);
+            VALIDATE_PARAMETER(frame_size,  "frame size",         codecpar->frame_size < 0)
             break;
         default:
             goto fail;
@@ -677,14 +682,12 @@  static int ffm_read_header(AVFormatContext *s)
                 av_log(s, AV_LOG_ERROR, "Invalid extradata size %d\n", size);
                 goto fail;
             }
-            codec->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
-            if (!codec->extradata)
+            codecpar->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
+            if (!codecpar->extradata)
                 return AVERROR(ENOMEM);
-            codec->extradata_size = size;
-            avio_read(pb, codec->extradata, size);
+            codecpar->extradata_size = size;
+            avio_read(pb, codecpar->extradata, size);
         }
-
-        avcodec_parameters_from_context(st->codecpar, codec);
     }
 
     /* get until end of block reached */
@@ -698,8 +701,10 @@  static int ffm_read_header(AVFormatContext *s)
     ffm->dts = 0;
     ffm->read_state = READ_HEADER;
     ffm->first_packet = 1;
+    avcodec_free_context(&dummy_codec);
     return 0;
  fail:
+    avcodec_free_context(&dummy_codec);
     ffm_close(s);
     return -1;
 }