diff mbox

[FFmpeg-devel] ffmpeg: switch to codecpar

Message ID 20160920102841.19193-1-u@pkh.me
State Superseded
Headers show

Commit Message

Clément Bœsch Sept. 20, 2016, 10:28 a.m. UTC
From: Clément Bœsch <clement@stupeflix.com>

This commit is largely based on commit 15e84ed3 from Anton Khirnov
<anton@khirnov.net> which was previously skipped in bbf5ef9d.

There are still a bunch of things raising codecpar related warnings that
need fixing, such as:
- the use of codec->debug in the interactive debug mode
- read_ffserver_streams(): it's probably broken now but there is no test
- lowres stuff
- codec copy apparently required by bitstream filters

The matroska references are updated because they now properly forward
the field_order (previously unknown, now progressive).

Thanks to James Almer for fixing a bunch of FATE issues in this commit.

Signed-off-by: Clément Bœsch <clement@stupeflix.com>
Signed-off-by: James Almer <jamrial@gmail.com>
---
 cmdutils.c          |   4 +-
 ffmpeg.c            | 246 +++++++++++++++++++++++++++++-----------------------
 ffmpeg.h            |   1 +
 ffmpeg_filter.c     |  24 ++---
 ffmpeg_opt.c        | 140 +++++++++++++++++-------------
 libavformat/utils.c |   2 +-
 tests/ref/lavf/mkv  |   4 +-
 7 files changed, 237 insertions(+), 184 deletions(-)

Comments

Hendrik Leppkes Sept. 20, 2016, 11:46 a.m. UTC | #1
On Tue, Sep 20, 2016 at 12:28 PM, Clément Bœsch <u@pkh.me> wrote:
> From: Clément Bœsch <clement@stupeflix.com>
>
> This commit is largely based on commit 15e84ed3 from Anton Khirnov
> <anton@khirnov.net> which was previously skipped in bbf5ef9d.
>
> There are still a bunch of things raising codecpar related warnings that
> need fixing, such as:
> - the use of codec->debug in the interactive debug mode
> - read_ffserver_streams(): it's probably broken now but there is no test
> - lowres stuff
> - codec copy apparently required by bitstream filters
>
> The matroska references are updated because they now properly forward
> the field_order (previously unknown, now progressive).
>
> Thanks to James Almer for fixing a bunch of FATE issues in this commit.
>
> Signed-off-by: Clément Bœsch <clement@stupeflix.com>
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>  cmdutils.c          |   4 +-
>  ffmpeg.c            | 246 +++++++++++++++++++++++++++++-----------------------
>  ffmpeg.h            |   1 +
>  ffmpeg_filter.c     |  24 ++---
>  ffmpeg_opt.c        | 140 +++++++++++++++++-------------
>  libavformat/utils.c |   2 +-
>  tests/ref/lavf/mkv  |   4 +-
>  7 files changed, 237 insertions(+), 184 deletions(-)
>
> diff --git a/cmdutils.c b/cmdutils.c
> index 44f44cd..68deed9 100644
> --- a/cmdutils.c
> +++ b/cmdutils.c
> @@ -1993,7 +1993,7 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id,
>          codec            = s->oformat ? avcodec_find_encoder(codec_id)
>                                        : avcodec_find_decoder(codec_id);
>
> -    switch (st->codec->codec_type) {
> +    switch (st->codecpar->codec_type) {
>      case AVMEDIA_TYPE_VIDEO:
>          prefix  = 'v';
>          flags  |= AV_OPT_FLAG_VIDEO_PARAM;
> @@ -2051,7 +2051,7 @@ AVDictionary **setup_find_stream_info_opts(AVFormatContext *s,
>          return NULL;
>      }
>      for (i = 0; i < s->nb_streams; i++)
> -        opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codec->codec_id,
> +        opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id,
>                                      s, s->streams[i], NULL);
>      return opts;
>  }
> diff --git a/ffmpeg.c b/ffmpeg.c
> index 5d7d32a..c025eb6 100644
> --- a/ffmpeg.c
> +++ b/ffmpeg.c
> @@ -530,6 +530,7 @@ static void ffmpeg_cleanup(int ret)
>          av_dict_free(&ost->sws_dict);
>
>          avcodec_free_context(&ost->enc_ctx);
> +        avcodec_parameters_free(&ost->ref_par);
>
>          av_freep(&output_streams[i]);
>      }
> @@ -634,20 +635,13 @@ static void close_all_output_streams(OutputStream *ost, OSTFinished this_stream,
>
>  static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
>  {
> +    AVStream *st = ost->st;
>      AVBitStreamFilterContext *bsfc = ost->bitstream_filters;
>      AVCodecContext          *avctx = ost->encoding_needed ? ost->enc_ctx : ost->st->codec;
>      int ret;
>
> -    if (!ost->st->codec->extradata_size && ost->enc_ctx->extradata_size) {
> -        ost->st->codec->extradata = av_mallocz(ost->enc_ctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
> -        if (ost->st->codec->extradata) {
> -            memcpy(ost->st->codec->extradata, ost->enc_ctx->extradata, ost->enc_ctx->extradata_size);
> -            ost->st->codec->extradata_size = ost->enc_ctx->extradata_size;
> -        }
> -    }
> -
> -    if ((avctx->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) ||
> -        (avctx->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0))
> +    if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) ||
> +        (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0))
>          pkt->pts = pkt->dts = AV_NOPTS_VALUE;
>
>      /*
> @@ -657,14 +651,14 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
>       * Counting encoded video frames needs to be done separately because of
>       * reordering, see do_video_out()
>       */
> -    if (!(avctx->codec_type == AVMEDIA_TYPE_VIDEO && avctx->codec)) {
> +    if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed)) {
>          if (ost->frame_number >= ost->max_frames) {
>              av_packet_unref(pkt);
>              return;
>          }
>          ost->frame_number++;
>      }
> -    if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
> +    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
>          int i;
>          uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS,
>                                                NULL);
> @@ -696,14 +690,14 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
>      }
>      if (pkt->size == 0 && pkt->side_data_elems == 0)
>          return;
> -    if (!ost->st->codecpar->extradata && avctx->extradata) {
> -        ost->st->codecpar->extradata = av_malloc(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
> -        if (!ost->st->codecpar->extradata) {
> +    if (!st->codecpar->extradata_size && ost->enc_ctx->extradata_size) {
> +        st->codecpar->extradata = av_mallocz(ost->enc_ctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
> +        if (!st->codecpar->extradata) {
>              av_log(NULL, AV_LOG_ERROR, "Could not allocate extradata buffer to copy parser data.\n");
>              exit_program(1);
>          }
> -        ost->st->codecpar->extradata_size = avctx->extradata_size;
> -        memcpy(ost->st->codecpar->extradata, avctx->extradata, avctx->extradata_size);
> +        st->codecpar->extradata_size = ost->enc_ctx->extradata_size;
> +        memcpy(st->codecpar->extradata, ost->enc_ctx->extradata, ost->enc_ctx->extradata_size);
>      }
>
>      if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) {
> @@ -718,13 +712,13 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
>                       - FFMIN3(pkt->pts, pkt->dts, ost->last_mux_dts + 1)
>                       - FFMAX3(pkt->pts, pkt->dts, ost->last_mux_dts + 1);
>          }
> -        if ((avctx->codec_type == AVMEDIA_TYPE_AUDIO || avctx->codec_type == AVMEDIA_TYPE_VIDEO) &&
> +        if ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
>              pkt->dts != AV_NOPTS_VALUE &&
> -            !(avctx->codec_id == AV_CODEC_ID_VP9 && ost->stream_copy) &&
> +            !(st->codecpar->codec_id == AV_CODEC_ID_VP9 && ost->stream_copy) &&
>              ost->last_mux_dts != AV_NOPTS_VALUE) {
>              int64_t max = ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT);
>              if (pkt->dts < max) {
> -                int loglevel = max - pkt->dts > 2 || avctx->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG;
> +                int loglevel = max - pkt->dts > 2 || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG;
>                  av_log(s, loglevel, "Non-monotonous DTS in output stream "
>                         "%d:%d; previous: %"PRId64", current: %"PRId64"; ",
>                         ost->file_index, ost->st->index, ost->last_mux_dts, pkt->dts);
> @@ -932,7 +926,7 @@ static void do_video_out(AVFormatContext *s,
>      int ret, format_video_sync;
>      AVPacket pkt;
>      AVCodecContext *enc = ost->enc_ctx;
> -    AVCodecContext *mux_enc = ost->st->codec;
> +    AVCodecParameters *mux_par = ost->st->codecpar;
>      int nb_frames, nb0_frames, i;
>      double delta, delta0;
>      double duration = 0;
> @@ -1093,9 +1087,9 @@ static void do_video_out(AVFormatContext *s,
>             avoid any copies. We support temporarily the older
>             method. */
>          if (in_picture->interlaced_frame)
> -            mux_enc->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT;
> +            mux_par->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT;
>          else
> -            mux_enc->field_order = AV_FIELD_PROGRESSIVE;
> +            mux_par->field_order = AV_FIELD_PROGRESSIVE;
>          pkt.data   = (uint8_t *)in_picture;
>          pkt.size   =  sizeof(AVPicture);
>          pkt.pts    = av_rescale_q(in_picture->pts, enc->time_base, ost->st->time_base);
> @@ -1114,11 +1108,11 @@ static void do_video_out(AVFormatContext *s,
>
>          if (in_picture->interlaced_frame) {
>              if (enc->codec->id == AV_CODEC_ID_MJPEG)
> -                mux_enc->field_order = in_picture->top_field_first ? AV_FIELD_TT:AV_FIELD_BB;
> +                mux_par->field_order = in_picture->top_field_first ? AV_FIELD_TT:AV_FIELD_BB;
>              else
> -                mux_enc->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT;
> +                mux_par->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT;
>          } else
> -            mux_enc->field_order = AV_FIELD_PROGRESSIVE;
> +            mux_par->field_order = AV_FIELD_PROGRESSIVE;
>
>          in_picture->quality = enc->global_quality;
>          in_picture->pict_type = 0;
> @@ -1850,7 +1844,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
>          opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base);
>      opkt.dts -= ost_tb_start_time;
>
> -    if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && pkt->dts != AV_NOPTS_VALUE) {
> +    if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && pkt->dts != AV_NOPTS_VALUE) {
>          int duration = av_get_audio_frame_duration(ist->dec_ctx, pkt->size);
>          if(!duration)
>              duration = ist->dec_ctx->frame_size;
> @@ -1862,10 +1856,10 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
>      opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base);
>      opkt.flags    = pkt->flags;
>      // FIXME remove the following 2 lines they shall be replaced by the bitstream filters
> -    if (  ost->st->codec->codec_id != AV_CODEC_ID_H264
> -       && ost->st->codec->codec_id != AV_CODEC_ID_MPEG1VIDEO
> -       && ost->st->codec->codec_id != AV_CODEC_ID_MPEG2VIDEO
> -       && ost->st->codec->codec_id != AV_CODEC_ID_VC1
> +    if (  ost->st->codecpar->codec_id != AV_CODEC_ID_H264
> +       && ost->st->codecpar->codec_id != AV_CODEC_ID_MPEG1VIDEO
> +       && ost->st->codecpar->codec_id != AV_CODEC_ID_MPEG2VIDEO
> +       && ost->st->codecpar->codec_id != AV_CODEC_ID_VC1
>         ) {
>          int ret = av_parser_change(ost->parser, ost->st->codec,
>                               &opkt.data, &opkt.size,
> @@ -1888,11 +1882,11 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
>      av_copy_packet_side_data(&opkt, pkt);
>
>  #if FF_API_LAVF_FMT_RAWPICTURE
> -    if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
> -        ost->st->codec->codec_id == AV_CODEC_ID_RAWVIDEO &&
> +    if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
> +        ost->st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO &&
>          (of->ctx->oformat->flags & AVFMT_RAWPICTURE)) {
>          /* store AVPicture in AVPacket, as expected by the output format */
> -        int ret = avpicture_fill(&pict, opkt.data, ost->st->codec->pix_fmt, ost->st->codec->width, ost->st->codec->height);
> +        int ret = avpicture_fill(&pict, opkt.data, ost->st->codecpar->format, ost->st->codecpar->width, ost->st->codecpar->height);
>          if (ret < 0) {
>              av_log(NULL, AV_LOG_FATAL, "avpicture_fill failed: %s\n",
>                     av_err2str(ret));
> @@ -2089,17 +2083,17 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
>
>      // The following line may be required in some cases where there is no parser
>      // or the parser does not has_b_frames correctly
> -    if (ist->st->codec->has_b_frames < ist->dec_ctx->has_b_frames) {
> +    if (ist->st->codecpar->video_delay < ist->dec_ctx->has_b_frames) {
>          if (ist->dec_ctx->codec_id == AV_CODEC_ID_H264) {
> -            ist->st->codec->has_b_frames = ist->dec_ctx->has_b_frames;
> +            ist->st->codecpar->video_delay = ist->dec_ctx->has_b_frames;
>          } else
>              av_log(ist->dec_ctx, AV_LOG_WARNING,
> -                   "has_b_frames is larger in decoder than demuxer %d > %d.\n"
> +                   "video_delay is larger in decoder than demuxer %d > %d.\n"
>                     "If you want to help, upload a sample "
>                     "of this file to ftp://upload.ffmpeg.org/incoming/ "
>                     "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)",
>                     ist->dec_ctx->has_b_frames,
> -                   ist->st->codec->has_b_frames);
> +                   ist->st->codecpar->video_delay);
>      }
>
>      check_decode_result(ist, got_output, ret);
> @@ -2560,6 +2554,23 @@ static int init_input_stream(int ist_index, char *error, int error_len)
>
>          av_dict_set(&ist->decoder_opts, "sub_text_format", "ass", AV_DICT_DONT_OVERWRITE);
>
> +        /*
> +         * For subtitles, this is required by the decoding process in order to
> +         * rescale the timestamps: in the current API the decoded subtitles
> +         * have their pts expressed in AV_TIME_BASE, and thus the lavc
> +         * internals need to know the stream time base in order to achieve the
> +         * rescaling.
> +         *
> +         * That API is old and needs to be reworked to match behaviour with A/V
> +         * (FIXME).
> +         *
> +         * For Audio, this is apparently required for the
> +         * fate-gaplessenc-itunes-to-ipod-aac test (FIXME).
> +         */
> +        if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE ||
> +            ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO)
> +            av_codec_set_pkt_timebase(ist->dec_ctx, ist->st->time_base);
> +

I didn't look at the surrounding code much, so maybe I'm out of
context here, but I would think setting pkt_timebase on the decoder is
generally not a bad thing, for any type of codec?
Audio uses it to skip samples, subtitles for rescaling timestamps, at
least the cuvid video decoder uses it to rescale timestamps for the
external API as well.

So maybe set it unconditionally? Setting pkt_timebase is not a bad
thing, I would think. It was probably copied from the st->codec
before, as well.

>          if (!av_dict_get(ist->decoder_opts, "threads", NULL, 0))
>              av_dict_set(&ist->decoder_opts, "threads", "auto", 0);
>          if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) {
> @@ -2644,12 +2655,20 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len)
>              av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low."
>                                           " It takes bits/s as argument, not kbits/s\n");
>
> -        ret = avcodec_copy_context(ost->st->codec, ost->enc_ctx);
> +        ret = avcodec_parameters_from_context(ost->st->codecpar, ost->enc_ctx);
>          if (ret < 0) {
>              av_log(NULL, AV_LOG_FATAL,
>                     "Error initializing the output stream codec context.\n");
>              exit_program(1);
>          }
> +        /*
> +         * FIXME: this is only so that the bitstream filters and parsers (that still
> +         * work with a codec context) get the parameter values.
> +         * This should go away with the new BSF/parser API.
> +         */
> +        ret = avcodec_copy_context(ost->st->codec, ost->enc_ctx);
> +        if (ret < 0)
> +            return ret;
>
>          if (ost->enc_ctx->nb_coded_side_data) {
>              int i;
> @@ -2677,14 +2696,17 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len)
>          ost->st->time_base = av_add_q(ost->enc_ctx->time_base, (AVRational){0, 1});
>          ost->st->codec->codec= ost->enc_ctx->codec;
>      } else if (ost->stream_copy) {
> -        ret = av_opt_set_dict(ost->st->codec, &ost->encoder_opts);
> -        if (ret < 0) {
> -           av_log(NULL, AV_LOG_FATAL,
> -                  "Error setting up codec context options.\n");
> -           return ret;
> -        }
>          // copy timebase while removing common factors
>          ost->st->time_base = av_add_q(ost->st->codec->time_base, (AVRational){0, 1});
> +
> +        /*
> +         * FIXME: this is only so that the bitstream filters and parsers (that still
> +         * work with a codec context) get the parameter values.
> +         * This should go away with the new BSF/parser API.
> +         */
> +        ret = avcodec_parameters_to_context(ost->st->codec, ost->st->codecpar);
> +        if (ret < 0)
> +            return ret;
>      }
>
>      return ret;
> @@ -2762,7 +2784,7 @@ static void report_new_stream(int input_index, AVPacket *pkt)
>          return;
>      av_log(file->ctx, AV_LOG_WARNING,
>             "New %s stream %d:%d at pos:%"PRId64" and DTS:%ss\n",
> -           av_get_media_type_string(st->codec->codec_type),
> +           av_get_media_type_string(st->codecpar->codec_type),
>             input_index, pkt->stream_index,
>             pkt->pos, av_ts2timestr(pkt->dts, &st->time_base));
>      file->nb_streams_warn = pkt->stream_index + 1;
> @@ -2843,8 +2865,6 @@ static int transcode_init(void)
>
>      /* for each output stream, we compute the right encoding parameters */
>      for (i = 0; i < nb_output_streams; i++) {
> -        AVCodecContext *enc_ctx;
> -        AVCodecContext *dec_ctx = NULL;
>          ost = output_streams[i];
>          oc  = output_files[ost->file_index]->ctx;
>          ist = get_input_stream(ost);
> @@ -2852,67 +2872,75 @@ static int transcode_init(void)
>          if (ost->attachment_filename)
>              continue;
>
> -        enc_ctx = ost->stream_copy ? ost->st->codec : ost->enc_ctx;
> -
>          if (ist) {
> -            dec_ctx = ist->dec_ctx;
> -
>              ost->st->disposition          = ist->st->disposition;
> -            enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location;
>          } else {
>              for (j=0; j<oc->nb_streams; j++) {
>                  AVStream *st = oc->streams[j];
> -                if (st != ost->st && st->codec->codec_type == enc_ctx->codec_type)
> +                if (st != ost->st && st->codecpar->codec_type == ost->st->codecpar->codec_type)
>                      break;
>              }
>              if (j == oc->nb_streams)
> -                if (enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO || enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO)
> +                if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ||
> +                    ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
>                      ost->st->disposition = AV_DISPOSITION_DEFAULT;
>          }
>
>          if (ost->stream_copy) {
> +            AVCodecParameters *par_dst = ost->st->codecpar;
> +            AVCodecParameters *par_src = ost->ref_par;
>              AVRational sar;
>              uint64_t extra_size;
>
>              av_assert0(ist && !ost->filter);
>
> -            extra_size = (uint64_t)dec_ctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE;
> +            avcodec_parameters_to_context(ost->enc_ctx, ist->st->codecpar);
> +            ret = av_opt_set_dict(ost->enc_ctx, &ost->encoder_opts);
> +            if (ret < 0) {
> +                av_log(NULL, AV_LOG_FATAL,
> +                       "Error setting up codec context options.\n");
> +                return ret;
> +            }
> +            avcodec_parameters_from_context(par_src, ost->enc_ctx);
> +
> +            extra_size = (uint64_t)par_src->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE;
>
>              if (extra_size > INT_MAX) {
>                  return AVERROR(EINVAL);
>              }
>
>              /* if stream_copy is selected, no need to decode or encode */
> -            enc_ctx->codec_id   = dec_ctx->codec_id;
> -            enc_ctx->codec_type = dec_ctx->codec_type;
> +            par_dst->codec_id   = par_src->codec_id;
> +            par_dst->codec_type = par_src->codec_type;
>
> -            if (!enc_ctx->codec_tag) {
> +            if (!par_dst->codec_tag) {
>                  unsigned int codec_tag;
>                  if (!oc->oformat->codec_tag ||
> -                     av_codec_get_id (oc->oformat->codec_tag, dec_ctx->codec_tag) == enc_ctx->codec_id ||
> -                     !av_codec_get_tag2(oc->oformat->codec_tag, dec_ctx->codec_id, &codec_tag))
> -                    enc_ctx->codec_tag = dec_ctx->codec_tag;
> +                     av_codec_get_id (oc->oformat->codec_tag, par_src->codec_tag) == par_dst->codec_id ||
> +                     !av_codec_get_tag2(oc->oformat->codec_tag, par_src->codec_id, &codec_tag))
> +                    par_dst->codec_tag = par_src->codec_tag;
>              }
>
> -            enc_ctx->bit_rate       = dec_ctx->bit_rate;
> -            enc_ctx->rc_max_rate    = dec_ctx->rc_max_rate;
> -            enc_ctx->rc_buffer_size = dec_ctx->rc_buffer_size;
> -            enc_ctx->field_order    = dec_ctx->field_order;
> -            if (dec_ctx->extradata_size) {
> -                enc_ctx->extradata      = av_mallocz(extra_size);
> -                if (!enc_ctx->extradata) {
> +            par_dst->bit_rate        = par_src->bit_rate;
> +            par_dst->field_order     = par_src->field_order;
> +            par_dst->chroma_location = par_src->chroma_location;
> +            if (par_src->extradata_size) {
> +                par_dst->extradata      = av_mallocz(extra_size);
> +                if (!par_dst->extradata) {
>                      return AVERROR(ENOMEM);
>                  }
> -                memcpy(enc_ctx->extradata, dec_ctx->extradata, dec_ctx->extradata_size);
> +                memcpy(par_dst->extradata, par_src->extradata, par_src->extradata_size);
>              }
> -            enc_ctx->extradata_size= dec_ctx->extradata_size;
> -            enc_ctx->bits_per_coded_sample  = dec_ctx->bits_per_coded_sample;
> -            enc_ctx->bits_per_raw_sample    = dec_ctx->bits_per_raw_sample;
> +            par_dst->extradata_size= par_src->extradata_size;
> +            par_dst->bits_per_coded_sample  = par_src->bits_per_coded_sample;
> +            par_dst->bits_per_raw_sample    = par_src->bits_per_raw_sample;
>
>              if (!ost->frame_rate.num)
>                  ost->frame_rate = ist->framerate;
>              ost->st->avg_frame_rate = ost->frame_rate;
>
> +            ost->st->time_base = ist->st->time_base;
> +
>              ret = avformat_transfer_internal_stream_timing_info(oc->oformat, ost->st, ist->st, copy_tb);
>              if (ret < 0)
>                  return ret;
> @@ -2941,59 +2969,54 @@ static int transcode_init(void)
>                  }
>              }
>
> -            ost->parser = av_parser_init(enc_ctx->codec_id);
> +            ost->parser = av_parser_init(par_dst->codec_id);
>
> -            switch (enc_ctx->codec_type) {
> +            switch (par_dst->codec_type) {
>              case AVMEDIA_TYPE_AUDIO:
>                  if (audio_volume != 256) {
>                      av_log(NULL, AV_LOG_FATAL, "-acodec copy and -vol are incompatible (frames are not decoded)\n");
>                      exit_program(1);
>                  }
> -                enc_ctx->channel_layout     = dec_ctx->channel_layout;
> -                enc_ctx->sample_rate        = dec_ctx->sample_rate;
> -                enc_ctx->channels           = dec_ctx->channels;
> -                enc_ctx->frame_size         = dec_ctx->frame_size;
> -                enc_ctx->audio_service_type = dec_ctx->audio_service_type;
> -                enc_ctx->block_align        = dec_ctx->block_align;
> -                enc_ctx->initial_padding    = dec_ctx->delay;
> -                enc_ctx->trailing_padding   = dec_ctx->trailing_padding;
> -                enc_ctx->profile            = dec_ctx->profile;
> -#if FF_API_AUDIOENC_DELAY
> -                enc_ctx->delay              = dec_ctx->delay;
> -#endif
> -                if((enc_ctx->block_align == 1 || enc_ctx->block_align == 1152 || enc_ctx->block_align == 576) && enc_ctx->codec_id == AV_CODEC_ID_MP3)
> -                    enc_ctx->block_align= 0;
> -                if(enc_ctx->codec_id == AV_CODEC_ID_AC3)
> -                    enc_ctx->block_align= 0;
> +                par_dst->channel_layout     = par_src->channel_layout;
> +                par_dst->sample_rate        = par_src->sample_rate;
> +                par_dst->channels           = par_src->channels;
> +                par_dst->block_align        = par_src->block_align;
> +                par_dst->initial_padding    = par_src->initial_padding;
> +                par_dst->trailing_padding   = par_src->trailing_padding;
> +                par_dst->profile            = par_src->profile;
> +                if((par_dst->block_align == 1 || par_dst->block_align == 1152 || par_dst->block_align == 576) && par_dst->codec_id == AV_CODEC_ID_MP3)
> +                    par_dst->block_align= 0;
> +                if(par_dst->codec_id == AV_CODEC_ID_AC3)
> +                    par_dst->block_align= 0;
>                  break;
>              case AVMEDIA_TYPE_VIDEO:
> -                enc_ctx->pix_fmt            = dec_ctx->pix_fmt;
> -                enc_ctx->colorspace         = dec_ctx->colorspace;
> -                enc_ctx->color_range        = dec_ctx->color_range;
> -                enc_ctx->color_primaries    = dec_ctx->color_primaries;
> -                enc_ctx->color_trc          = dec_ctx->color_trc;
> -                enc_ctx->width              = dec_ctx->width;
> -                enc_ctx->height             = dec_ctx->height;
> -                enc_ctx->has_b_frames       = dec_ctx->has_b_frames;
> -                enc_ctx->profile            = dec_ctx->profile;
> +                par_dst->format             = par_src->format;
> +                par_dst->color_space        = par_src->color_space;
> +                par_dst->color_range        = par_src->color_range;
> +                par_dst->color_primaries    = par_src->color_primaries;
> +                par_dst->color_trc          = par_src->color_trc;
> +                par_dst->width              = par_src->width;
> +                par_dst->height             = par_src->height;
> +                par_dst->video_delay        = par_src->video_delay;
> +                par_dst->profile            = par_src->profile;
>                  if (ost->frame_aspect_ratio.num) { // overridden by the -aspect cli option
>                      sar =
>                          av_mul_q(ost->frame_aspect_ratio,
> -                                 (AVRational){ enc_ctx->height, enc_ctx->width });
> +                                 (AVRational){ par_dst->height, par_dst->width });
>                      av_log(NULL, AV_LOG_WARNING, "Overriding aspect ratio "
>                             "with stream copy may produce invalid files\n");
>                  }
>                  else if (ist->st->sample_aspect_ratio.num)
>                      sar = ist->st->sample_aspect_ratio;
>                  else
> -                    sar = dec_ctx->sample_aspect_ratio;
> -                ost->st->sample_aspect_ratio = enc_ctx->sample_aspect_ratio = sar;
> +                    sar = par_src->sample_aspect_ratio;
> +                ost->st->sample_aspect_ratio = par_dst->sample_aspect_ratio = sar;
>                  ost->st->avg_frame_rate = ist->st->avg_frame_rate;
>                  ost->st->r_frame_rate = ist->st->r_frame_rate;
>                  break;
>              case AVMEDIA_TYPE_SUBTITLE:
> -                enc_ctx->width  = dec_ctx->width;
> -                enc_ctx->height = dec_ctx->height;
> +                par_dst->width  = par_src->width;
> +                par_dst->height = par_src->height;
>                  break;
>              case AVMEDIA_TYPE_UNKNOWN:
>              case AVMEDIA_TYPE_DATA:
> @@ -3003,8 +3026,17 @@ static int transcode_init(void)
>                  abort();
>              }
>          } else {
> +            AVCodecContext *enc_ctx = ost->enc_ctx;
> +            AVCodecContext *dec_ctx = NULL;
> +
>              set_encoder_id(output_files[ost->file_index], ost);
>
> +            if (ist) {
> +                dec_ctx = ist->dec_ctx;
> +
> +                enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location;
> +            }
> +
>  #if CONFIG_LIBMFX
>              if (qsv_transcode_init(ost))
>                  exit_program(1);
> @@ -3136,8 +3168,8 @@ static int transcode_init(void)
>              case AVMEDIA_TYPE_SUBTITLE:
>                  enc_ctx->time_base = (AVRational){1, 1000};
>                  if (!enc_ctx->width) {
> -                    enc_ctx->width     = input_streams[ost->source_index]->st->codec->width;
> -                    enc_ctx->height    = input_streams[ost->source_index]->st->codec->height;
> +                    enc_ctx->width     = input_streams[ost->source_index]->st->codecpar->width;
> +                    enc_ctx->height    = input_streams[ost->source_index]->st->codecpar->height;
>                  }
>                  break;
>              case AVMEDIA_TYPE_DATA:
> diff --git a/ffmpeg.h b/ffmpeg.h
> index 49d65d8..5caf584 100644
> --- a/ffmpeg.h
> +++ b/ffmpeg.h
> @@ -418,6 +418,7 @@ typedef struct OutputStream {
>      int64_t last_mux_dts;
>      AVBitStreamFilterContext *bitstream_filters;
>      AVCodecContext *enc_ctx;
> +    AVCodecParameters *ref_par; /* associated input codec parameters with encoders options applied */
>      AVCodec *enc;
>      int64_t max_frames;
>      AVFrame *filtered_frame;
> diff --git a/ffmpeg_filter.c b/ffmpeg_filter.c
> index 76030cf..27aeca0 100644
> --- a/ffmpeg_filter.c
> +++ b/ffmpeg_filter.c
> @@ -94,19 +94,19 @@ void choose_sample_fmt(AVStream *st, AVCodec *codec)
>      if (codec && codec->sample_fmts) {
>          const enum AVSampleFormat *p = codec->sample_fmts;
>          for (; *p != -1; p++) {
> -            if (*p == st->codec->sample_fmt)
> +            if (*p == st->codecpar->format)
>                  break;
>          }
>          if (*p == -1) {
> -            if((codec->capabilities & AV_CODEC_CAP_LOSSLESS) && av_get_sample_fmt_name(st->codec->sample_fmt) > av_get_sample_fmt_name(codec->sample_fmts[0]))
> +            if((codec->capabilities & AV_CODEC_CAP_LOSSLESS) && av_get_sample_fmt_name(st->codecpar->format) > av_get_sample_fmt_name(codec->sample_fmts[0]))
>                  av_log(NULL, AV_LOG_ERROR, "Conversion will not be lossless.\n");
> -            if(av_get_sample_fmt_name(st->codec->sample_fmt))
> +            if(av_get_sample_fmt_name(st->codecpar->format))
>              av_log(NULL, AV_LOG_WARNING,
>                     "Incompatible sample format '%s' for codec '%s', auto-selecting format '%s'\n",
> -                   av_get_sample_fmt_name(st->codec->sample_fmt),
> +                   av_get_sample_fmt_name(st->codecpar->format),
>                     codec->name,
>                     av_get_sample_fmt_name(codec->sample_fmts[0]));
> -            st->codec->sample_fmt = codec->sample_fmts[0];
> +            st->codecpar->format = codec->sample_fmts[0];
>          }
>      }
>  }
> @@ -251,7 +251,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
>          s = input_files[file_idx]->ctx;
>
>          for (i = 0; i < s->nb_streams; i++) {
> -            enum AVMediaType stream_type = s->streams[i]->codec->codec_type;
> +            enum AVMediaType stream_type = s->streams[i]->codecpar->codec_type;
>              if (stream_type != type &&
>                  !(stream_type == AVMEDIA_TYPE_SUBTITLE &&
>                    type == AVMEDIA_TYPE_VIDEO /* sub2video hack */))
> @@ -611,7 +611,7 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter,
>          int i;
>
>          for (i=0; i<of->ctx->nb_streams; i++)
> -            if (of->ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
> +            if (of->ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
>                  break;
>
>          if (i<of->ctx->nb_streams) {
> @@ -673,15 +673,15 @@ static int sub2video_prepare(InputStream *ist)
>      int i, w, h;
>
>      /* Compute the size of the canvas for the subtitles stream.
> -       If the subtitles codec has set a size, use it. Otherwise use the
> +       If the subtitles codecpar has set a size, use it. Otherwise use the
>         maximum dimensions of the video streams in the same file. */
>      w = ist->dec_ctx->width;
>      h = ist->dec_ctx->height;
>      if (!(w && h)) {
>          for (i = 0; i < avf->nb_streams; i++) {
> -            if (avf->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
> -                w = FFMAX(w, avf->streams[i]->codec->width);
> -                h = FFMAX(h, avf->streams[i]->codec->height);
> +            if (avf->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
> +                w = FFMAX(w, avf->streams[i]->codecpar->width);
> +                h = FFMAX(h, avf->streams[i]->codecpar->height);
>              }
>          }
>          if (!(w && h)) {
> @@ -1081,7 +1081,7 @@ int configure_filtergraph(FilterGraph *fg)
>              /* identical to the same check in ffmpeg.c, needed because
>                 complex filter graphs are initialized earlier */
>              av_log(NULL, AV_LOG_ERROR, "Encoder (codec %s) not found for output stream #%d:%d\n",
> -                     avcodec_get_name(ost->st->codec->codec_id), ost->file_index, ost->index);
> +                     avcodec_get_name(ost->st->codecpar->codec_id), ost->file_index, ost->index);
>              return AVERROR(EINVAL);
>          }
>          if (ost->enc->type == AVMEDIA_TYPE_AUDIO &&
> diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c
> index 0c0d3a6..81e3979 100644
> --- a/ffmpeg_opt.c
> +++ b/ffmpeg_opt.c
> @@ -429,12 +429,12 @@ static int opt_map_channel(void *optctx, const char *opt, const char *arg)
>          exit_program(1);
>      }
>      st = input_files[m->file_idx]->ctx->streams[m->stream_idx];
> -    if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
> +    if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
>          av_log(NULL, AV_LOG_FATAL, "mapchan: stream #%d.%d is not an audio stream.\n",
>                 m->file_idx, m->stream_idx);
>          exit_program(1);
>      }
> -    if (m->channel_idx < 0 || m->channel_idx >= st->codec->channels) {
> +    if (m->channel_idx < 0 || m->channel_idx >= st->codecpar->channels) {
>          av_log(NULL, AV_LOG_FATAL, "mapchan: invalid audio channel #%d.%d.%d\n",
>                 m->file_idx, m->stream_idx, m->channel_idx);
>          exit_program(1);
> @@ -634,11 +634,11 @@ static AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream *
>
>      MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, st);
>      if (codec_name) {
> -        AVCodec *codec = find_codec_or_die(codec_name, st->codec->codec_type, 0);
> -        st->codec->codec_id = codec->id;
> +        AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0);
> +        st->codecpar->codec_id = codec->id;
>          return codec;
>      } else
> -        return avcodec_find_decoder(st->codec->codec_id);
> +        return avcodec_find_decoder(st->codecpar->codec_id);
>  }
>
>  /* Add all the streams from the given input file to the global
> @@ -649,14 +649,15 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
>
>      for (i = 0; i < ic->nb_streams; i++) {
>          AVStream *st = ic->streams[i];
> -        AVCodecContext *dec = st->codec;
> +        AVCodecParameters *par = st->codecpar;
>          InputStream *ist = av_mallocz(sizeof(*ist));
>          char *framerate = NULL, *hwaccel = NULL, *hwaccel_device = NULL;
>          char *hwaccel_output_format = NULL;
>          char *codec_tag = NULL;
>          char *next;
>          char *discard_str = NULL;
> -        const AVOption *discard_opt = av_opt_find(dec, "skip_frame", NULL, 0, 0);
> +        const AVClass *cc = avcodec_get_class();
> +        const AVOption *discard_opt = av_opt_find(&cc, "skip_frame", NULL, 0, 0);
>
>          if (!ist)
>              exit_program(1);
> @@ -683,18 +684,18 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
>              uint32_t tag = strtol(codec_tag, &next, 0);
>              if (*next)
>                  tag = AV_RL32(codec_tag);
> -            st->codec->codec_tag = tag;
> +            st->codecpar->codec_tag = tag;
>          }
>
>          ist->dec = choose_decoder(o, ic, st);
> -        ist->decoder_opts = filter_codec_opts(o->g->codec_opts, ist->st->codec->codec_id, ic, st, ist->dec);
> +        ist->decoder_opts = filter_codec_opts(o->g->codec_opts, ist->st->codecpar->codec_id, ic, st, ist->dec);
>
>          ist->reinit_filters = -1;
>          MATCH_PER_STREAM_OPT(reinit_filters, i, ist->reinit_filters, ic, st);
>
>          MATCH_PER_STREAM_OPT(discard, str, discard_str, ic, st);
>          ist->user_set_discard = AVDISCARD_NONE;
> -        if (discard_str && av_opt_eval_int(dec, discard_opt, discard_str, &ist->user_set_discard) < 0) {
> +        if (discard_str && av_opt_eval_int(&cc, discard_opt, discard_str, &ist->user_set_discard) < 0) {
>              av_log(NULL, AV_LOG_ERROR, "Error parsing discard %s.\n",
>                      discard_str);
>              exit_program(1);
> @@ -708,22 +709,30 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
>              exit_program(1);
>          }
>
> -        ret = avcodec_copy_context(ist->dec_ctx, dec);
> +        ret = avcodec_parameters_to_context(ist->dec_ctx, par);
>          if (ret < 0) {
>              av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n");
>              exit_program(1);
>          }
>
> -        switch (dec->codec_type) {
> +        switch (par->codec_type) {
>          case AVMEDIA_TYPE_VIDEO:
>              if(!ist->dec)
> -                ist->dec = avcodec_find_decoder(dec->codec_id);
> +                ist->dec = avcodec_find_decoder(par->codec_id);
>  #if FF_API_EMU_EDGE
> -            if (av_codec_get_lowres(dec)) {
> -                dec->flags |= CODEC_FLAG_EMU_EDGE;
> +            if (av_codec_get_lowres(st->codec)) {
> +                ist->dec_ctx->lowres = av_codec_get_lowres(st->codec);
> +                ist->dec_ctx->width  = st->codec->width;
> +                ist->dec_ctx->height = st->codec->height;
> +                ist->dec_ctx->coded_width  = st->codec->coded_width;
> +                ist->dec_ctx->coded_height = st->codec->coded_height;
> +                ist->dec_ctx->flags |= CODEC_FLAG_EMU_EDGE;
>              }
>  #endif
>
> +            // avformat_find_stream_info() doesn't set this for us anymore.
> +            ist->dec_ctx->framerate = st->avg_frame_rate;
> +
>              ist->resample_height  = ist->dec_ctx->height;
>              ist->resample_width   = ist->dec_ctx->width;
>              ist->resample_pix_fmt = ist->dec_ctx->pix_fmt;
> @@ -803,7 +812,7 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
>          case AVMEDIA_TYPE_SUBTITLE: {
>              char *canvas_size = NULL;
>              if(!ist->dec)
> -                ist->dec = avcodec_find_decoder(dec->codec_id);
> +                ist->dec = avcodec_find_decoder(par->codec_id);
>              MATCH_PER_STREAM_OPT(fix_sub_duration, i, ist->fix_sub_duration, ic, st);
>              MATCH_PER_STREAM_OPT(canvas_sizes, str, canvas_size, ic, st);
>              if (canvas_size &&
> @@ -819,6 +828,12 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
>          default:
>              abort();
>          }
> +
> +        ret = avcodec_parameters_from_context(par, ist->dec_ctx);
> +        if (ret < 0) {
> +            av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n");
> +            exit_program(1);
> +        }
>      }
>  }
>
> @@ -857,7 +872,7 @@ static void dump_attachment(AVStream *st, const char *filename)
>      AVIOContext *out = NULL;
>      AVDictionaryEntry *e;
>
> -    if (!st->codec->extradata_size) {
> +    if (!st->codecpar->extradata_size) {
>          av_log(NULL, AV_LOG_WARNING, "No extradata to dump in stream #%d:%d.\n",
>                 nb_input_files - 1, st->index);
>          return;
> @@ -878,7 +893,7 @@ static void dump_attachment(AVStream *st, const char *filename)
>          exit_program(1);
>      }
>
> -    avio_write(out, st->codec->extradata, st->codec->extradata_size);
> +    avio_write(out, st->codecpar->extradata, st->codecpar->extradata_size);
>      avio_flush(out);
>      avio_close(out);
>  }
> @@ -1028,8 +1043,8 @@ static int open_input_file(OptionsContext *o, const char *filename)
>          if (!(ic->iformat->flags & AVFMT_SEEK_TO_PTS)) {
>              int dts_heuristic = 0;
>              for (i=0; i<ic->nb_streams; i++) {
> -                AVCodecContext *avctx = ic->streams[i]->codec;
> -                if (avctx->has_b_frames)
> +                const AVCodecParameters *par = ic->streams[i]->codecpar;
> +                if (par->video_delay)
>                      dts_heuristic = 1;
>              }
>              if (dts_heuristic) {
> @@ -1176,28 +1191,28 @@ static int get_preset_file_2(const char *preset_name, const char *codec_name, AV
>
>  static int choose_encoder(OptionsContext *o, AVFormatContext *s, OutputStream *ost)
>  {
> -    enum AVMediaType type = ost->st->codec->codec_type;
> +    enum AVMediaType type = ost->st->codecpar->codec_type;
>      char *codec_name = NULL;
>
>      if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO || type == AVMEDIA_TYPE_SUBTITLE) {
>          MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st);
>          if (!codec_name) {
> -            ost->st->codec->codec_id = av_guess_codec(s->oformat, NULL, s->filename,
> -                                                      NULL, ost->st->codec->codec_type);
> -            ost->enc = avcodec_find_encoder(ost->st->codec->codec_id);
> +            ost->st->codecpar->codec_id = av_guess_codec(s->oformat, NULL, s->filename,
> +                                                         NULL, ost->st->codecpar->codec_type);
> +            ost->enc = avcodec_find_encoder(ost->st->codecpar->codec_id);
>              if (!ost->enc) {
>                  av_log(NULL, AV_LOG_FATAL, "Automatic encoder selection failed for "
>                         "output stream #%d:%d. Default encoder for format %s (codec %s) is "
>                         "probably disabled. Please choose an encoder manually.\n",
>                         ost->file_index, ost->index, s->oformat->name,
> -                       avcodec_get_name(ost->st->codec->codec_id));
> +                       avcodec_get_name(ost->st->codecpar->codec_id));
>                  return AVERROR_ENCODER_NOT_FOUND;
>              }
>          } else if (!strcmp(codec_name, "copy"))
>              ost->stream_copy = 1;
>          else {
> -            ost->enc = find_codec_or_die(codec_name, ost->st->codec->codec_type, 1);
> -            ost->st->codec->codec_id = ost->enc->id;
> +            ost->enc = find_codec_or_die(codec_name, ost->st->codecpar->codec_type, 1);
> +            ost->st->codecpar->codec_id = ost->enc->id;
>          }
>          ost->encoding_needed = !ost->stream_copy;
>      } else {
> @@ -1235,7 +1250,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
>      ost->file_index = nb_output_files - 1;
>      ost->index      = idx;
>      ost->st         = st;
> -    st->codec->codec_type = type;
> +    st->codecpar->codec_type = type;
>
>      ret = choose_encoder(o, oc, ost);
>      if (ret < 0) {
> @@ -1251,6 +1266,12 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
>      }
>      ost->enc_ctx->codec_type = type;
>
> +    ost->ref_par = avcodec_parameters_alloc();
> +    if (!ost->ref_par) {
> +        av_log(NULL, AV_LOG_ERROR, "Error allocating the encoding parameters.\n");
> +        exit_program(1);
> +    }
> +
>      if (ost->enc) {
>          AVIOContext *s = NULL;
>          char *buf = NULL, *arg = NULL, *preset = NULL;
> @@ -1328,7 +1349,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
>          uint32_t tag = strtol(codec_tag, &next, 0);
>          if (*next)
>              tag = AV_RL32(codec_tag);
> -        ost->st->codec->codec_tag =
> +        ost->st->codecpar->codec_tag =
>          ost->enc_ctx->codec_tag = tag;
>      }
>
> @@ -1425,7 +1446,7 @@ static char *get_ost_filters(OptionsContext *o, AVFormatContext *oc,
>      else if (ost->filters)
>          return av_strdup(ost->filters);
>
> -    return av_strdup(st->codec->codec_type == AVMEDIA_TYPE_VIDEO ?
> +    return av_strdup(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ?
>                       "null" : "anull");
>  }
>
> @@ -1857,9 +1878,9 @@ static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const ch
>          AVCodec *codec;
>          const char *enc_config;
>
> -        codec = avcodec_find_encoder(ic->streams[i]->codec->codec_id);
> +        codec = avcodec_find_encoder(ic->streams[i]->codecpar->codec_id);
>          if (!codec) {
> -            av_log(s, AV_LOG_ERROR, "no encoder found for codec id %i\n", ic->streams[i]->codec->codec_id);
> +            av_log(s, AV_LOG_ERROR, "no encoder found for codec id %i\n", ic->streams[i]->codecpar->codec_id);
>              return AVERROR(EINVAL);
>          }
>          if (codec->type == AVMEDIA_TYPE_AUDIO)
> @@ -1878,10 +1899,10 @@ static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const ch
>              av_dict_free(&opts);
>          }
>
> -        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy)
> +        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy)
>              choose_sample_fmt(st, codec);
> -        else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy)
> -            choose_pixel_fmt(st, st->codec, codec, st->codec->pix_fmt);
> +        else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy)
> +            choose_pixel_fmt(st, st->codec, codec, st->codecpar->format);
>          avcodec_copy_context(ost->enc_ctx, st->codec);
>          if (enc_config)
>              av_dict_parse_string(&ost->encoder_opts, enc_config, "=", ",", 0);
> @@ -2053,18 +2074,18 @@ static int open_output_file(OptionsContext *o, const char *filename)
>              ost = output_streams[j];
>              for (i = 0; i < nb_input_streams; i++) {
>                  ist = input_streams[i];
> -                if(ist->st->codec->codec_type == ost->st->codec->codec_type){
> +                if(ist->st->codecpar->codec_type == ost->st->codecpar->codec_type){
>                      ost->sync_ist= ist;
>                      ost->source_index= i;
> -                    if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) ost->avfilter = av_strdup("anull");
> -                    if(ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) ost->avfilter = av_strdup("null");
> +                    if(ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ost->avfilter = av_strdup("anull");
> +                    if(ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) ost->avfilter = av_strdup("null");
>                      ist->discard = 0;
>                      ist->st->discard = ist->user_set_discard;
>                      break;
>                  }
>              }
>              if(!ost->sync_ist){
> -                av_log(NULL, AV_LOG_FATAL, "Missing %s stream which is required by this ffm\n", av_get_media_type_string(ost->st->codec->codec_type));
> +                av_log(NULL, AV_LOG_FATAL, "Missing %s stream which is required by this ffm\n", av_get_media_type_string(ost->st->codecpar->codec_type));
>                  exit_program(1);
>              }
>          }
> @@ -2079,10 +2100,10 @@ static int open_output_file(OptionsContext *o, const char *filename)
>              for (i = 0; i < nb_input_streams; i++) {
>                  int new_area;
>                  ist = input_streams[i];
> -                new_area = ist->st->codec->width * ist->st->codec->height + 100000000*!!ist->st->codec_info_nb_frames;
> +                new_area = ist->st->codecpar->width * ist->st->codecpar->height + 100000000*!!ist->st->codec_info_nb_frames;
>                  if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
>                      new_area = 1;
> -                if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
> +                if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
>                      new_area > area) {
>                      if((qcr==MKTAG('A', 'P', 'I', 'C')) && !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
>                          continue;
> @@ -2100,8 +2121,8 @@ static int open_output_file(OptionsContext *o, const char *filename)
>              for (i = 0; i < nb_input_streams; i++) {
>                  int score;
>                  ist = input_streams[i];
> -                score = ist->st->codec->channels + 100000000*!!ist->st->codec_info_nb_frames;
> -                if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
> +                score = ist->st->codecpar->channels + 100000000*!!ist->st->codec_info_nb_frames;
> +                if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
>                      score > best_score) {
>                      best_score = score;
>                      idx = i;
> @@ -2115,9 +2136,9 @@ static int open_output_file(OptionsContext *o, const char *filename)
>          MATCH_PER_TYPE_OPT(codec_names, str, subtitle_codec_name, oc, "s");
>          if (!o->subtitle_disable && (avcodec_find_encoder(oc->oformat->subtitle_codec) || subtitle_codec_name)) {
>              for (i = 0; i < nb_input_streams; i++)
> -                if (input_streams[i]->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
> +                if (input_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
>                      AVCodecDescriptor const *input_descriptor =
> -                        avcodec_descriptor_get(input_streams[i]->st->codec->codec_id);
> +                        avcodec_descriptor_get(input_streams[i]->st->codecpar->codec_id);
>                      AVCodecDescriptor const *output_descriptor = NULL;
>                      AVCodec const *output_codec =
>                          avcodec_find_encoder(oc->oformat->subtitle_codec);
> @@ -2143,8 +2164,8 @@ static int open_output_file(OptionsContext *o, const char *filename)
>          if (!o->data_disable ) {
>              enum AVCodecID codec_id = av_guess_codec(oc->oformat, NULL, filename, NULL, AVMEDIA_TYPE_DATA);
>              for (i = 0; codec_id != AV_CODEC_ID_NONE && i < nb_input_streams; i++) {
> -                if (input_streams[i]->st->codec->codec_type == AVMEDIA_TYPE_DATA
> -                    && input_streams[i]->st->codec->codec_id == codec_id )
> +                if (input_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_DATA
> +                    && input_streams[i]->st->codecpar->codec_id == codec_id )
>                      new_data_stream(o, oc, i);
>              }
>          }
> @@ -2181,17 +2202,17 @@ loop_end:
>                  int src_idx = input_files[map->file_index]->ist_index + map->stream_index;
>
>                  ist = input_streams[input_files[map->file_index]->ist_index + map->stream_index];
> -                if(o->subtitle_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE)
> +                if(o->subtitle_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
>                      continue;
> -                if(o->   audio_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
> +                if(o->   audio_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
>                      continue;
> -                if(o->   video_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
> +                if(o->   video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
>                      continue;
> -                if(o->    data_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_DATA)
> +                if(o->    data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA)
>                      continue;
>
>                  ost = NULL;
> -                switch (ist->st->codec->codec_type) {
> +                switch (ist->st->codecpar->codec_type) {
>                  case AVMEDIA_TYPE_VIDEO:      ost = new_video_stream     (o, oc, src_idx); break;
>                  case AVMEDIA_TYPE_AUDIO:      ost = new_audio_stream     (o, oc, src_idx); break;
>                  case AVMEDIA_TYPE_SUBTITLE:   ost = new_subtitle_stream  (o, oc, src_idx); break;
> @@ -2247,8 +2268,8 @@ loop_end:
>
>          ost = new_attachment_stream(o, oc, -1);
>          ost->attachment_filename       = o->attachments[i];
> -        ost->st->codec->extradata      = attachment;
> -        ost->st->codec->extradata_size = len;
> +        ost->st->codecpar->extradata      = attachment;
> +        ost->st->codecpar->extradata_size = len;
>
>          p = strrchr(o->attachments[i], '/');
>          av_dict_set(&ost->st->metadata, "filename", (p && *p) ? p + 1 : o->attachments[i], AV_DICT_DONT_OVERWRITE);
> @@ -2322,8 +2343,8 @@ loop_end:
>              InputStream *ist = input_streams[ost->source_index];
>              ist->decoding_needed |= DECODING_FOR_OST;
>
> -            if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
> -                ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
> +            if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
> +                ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
>                  err = init_simple_filtergraph(ist, ost);
>                  if (err < 0) {
>                      av_log(NULL, AV_LOG_ERROR,
> @@ -2570,11 +2591,10 @@ static int opt_target(void *optctx, const char *opt, const char *arg)
>              int i, j, fr;
>              for (j = 0; j < nb_input_files; j++) {
>                  for (i = 0; i < input_files[j]->nb_streams; i++) {
> -                    AVCodecContext *c = input_files[j]->ctx->streams[i]->codec;
> -                    if (c->codec_type != AVMEDIA_TYPE_VIDEO ||
> -                        !c->time_base.num)
> +                    AVStream *st = input_files[j]->ctx->streams[i];
> +                    if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
>                          continue;
> -                    fr = c->time_base.den * 1000 / c->time_base.num;
> +                    fr = st->time_base.den * 1000 / st->time_base.num;
>                      if (fr == 25000) {
>                          norm = PAL;
>                          break;
> diff --git a/libavformat/utils.c b/libavformat/utils.c
> index f043bae..b439273 100644
> --- a/libavformat/utils.c
> +++ b/libavformat/utils.c
> @@ -5339,7 +5339,7 @@ int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt,
>          }
>      }
>
> -    if (enc_ctx->codec_tag == AV_RL32("tmcd")
> +    if (ost->codecpar->codec_tag == AV_RL32("tmcd")
>          && dec_ctx->time_base.num < dec_ctx->time_base.den
>          && dec_ctx->time_base.num > 0
>          && 121LL*dec_ctx->time_base.num > dec_ctx->time_base.den) {
> diff --git a/tests/ref/lavf/mkv b/tests/ref/lavf/mkv
> index 72fc291..5b0d386 100644
> --- a/tests/ref/lavf/mkv
> +++ b/tests/ref/lavf/mkv
> @@ -1,6 +1,6 @@
> -c081514c38735524ab09dbd2a498b7b3 *./tests/data/lavf/lavf.mkv
> +5b982c8dfbadc71f51b206cbd10b9a71 *./tests/data/lavf/lavf.mkv
>  472875 ./tests/data/lavf/lavf.mkv
>  ./tests/data/lavf/lavf.mkv CRC=0xec6c3c68
> -d1fc3a31150d00aebbd674862640f701 *./tests/data/lavf/lavf.mkv
> +b4a295bae8e6cf536563cb840386f3a4 *./tests/data/lavf/lavf.mkv
>  320551 ./tests/data/lavf/lavf.mkv
>  ./tests/data/lavf/lavf.mkv CRC=0xec6c3c68
> --
> 2.10.0

Otherwise looks mostly fine to me, but I'm not an expert on ffmpeg.c

- Hendrik
Clément Bœsch Sept. 20, 2016, 12:44 p.m. UTC | #2
On Tue, Sep 20, 2016 at 01:46:11PM +0200, Hendrik Leppkes wrote:
[...]
> > +        /*
> > +         * For subtitles, this is required by the decoding process in order to
> > +         * rescale the timestamps: in the current API the decoded subtitles
> > +         * have their pts expressed in AV_TIME_BASE, and thus the lavc
> > +         * internals need to know the stream time base in order to achieve the
> > +         * rescaling.
> > +         *
> > +         * That API is old and needs to be reworked to match behaviour with A/V
> > +         * (FIXME).
> > +         *
> > +         * For Audio, this is apparently required for the
> > +         * fate-gaplessenc-itunes-to-ipod-aac test (FIXME).
> > +         */
> > +        if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE ||
> > +            ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO)
> > +            av_codec_set_pkt_timebase(ist->dec_ctx, ist->st->time_base);
> > +
> 
> I didn't look at the surrounding code much, so maybe I'm out of
> context here, but I would think setting pkt_timebase on the decoder is
> generally not a bad thing, for any type of codec?
> Audio uses it to skip samples, subtitles for rescaling timestamps, at
> least the cuvid video decoder uses it to rescale timestamps for the
> external API as well.
> 
> So maybe set it unconditionally? Setting pkt_timebase is not a bad
> thing, I would think. It was probably copied from the st->codec
> before, as well.

If that's fine with everyone I can drop the condition and comment. But
generally speaking, aside from subtitles it looks like it mostly works
when it's not set, so should we warn when the user doesn't set it in order
to avoid random undefined behaviour?

[...]
Michael Niedermayer Sept. 20, 2016, 1:12 p.m. UTC | #3
On Tue, Sep 20, 2016 at 12:28:41PM +0200, Clément Bœsch wrote:
> From: Clément Bœsch <clement@stupeflix.com>
> 
> This commit is largely based on commit 15e84ed3 from Anton Khirnov
> <anton@khirnov.net> which was previously skipped in bbf5ef9d.
> 
> There are still a bunch of things raising codecpar related warnings that
> need fixing, such as:
> - the use of codec->debug in the interactive debug mode
> - read_ffserver_streams(): it's probably broken now but there is no test
> - lowres stuff
> - codec copy apparently required by bitstream filters
> 
> The matroska references are updated because they now properly forward
> the field_order (previously unknown, now progressive).
> 
> Thanks to James Almer for fixing a bunch of FATE issues in this commit.
> 
> Signed-off-by: Clément Bœsch <clement@stupeflix.com>
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>  cmdutils.c          |   4 +-
>  ffmpeg.c            | 246 +++++++++++++++++++++++++++++-----------------------
>  ffmpeg.h            |   1 +
>  ffmpeg_filter.c     |  24 ++---
>  ffmpeg_opt.c        | 140 +++++++++++++++++-------------
>  libavformat/utils.c |   2 +-
>  tests/ref/lavf/mkv  |   4 +-
>  7 files changed, 237 insertions(+), 184 deletions(-)

fails with:
./ffmpeg -f concat -i ~/tickets/3108/concatfile.txt -codec copy  test.avi
./ffmpeg-ref -f concat -i ~/tickets/3108/concatfile.txt -codec copy  test-ref.avi

-rw-r----- 1 michael michael 10707244 Sep 20 15:10 test.avi
-rw-r----- 1 michael michael  2847988 Sep 20 15:10 test-ref.avi

files are in ticket 3108

[...]
wm4 Sept. 23, 2016, 7:41 a.m. UTC | #4
On Tue, 20 Sep 2016 14:44:47 +0200
Clément Bœsch <u@pkh.me> wrote:

> On Tue, Sep 20, 2016 at 01:46:11PM +0200, Hendrik Leppkes wrote:
> [...]
> > > +        /*
> > > +         * For subtitles, this is required by the decoding process in order to
> > > +         * rescale the timestamps: in the current API the decoded subtitles
> > > +         * have their pts expressed in AV_TIME_BASE, and thus the lavc
> > > +         * internals need to know the stream time base in order to achieve the
> > > +         * rescaling.
> > > +         *
> > > +         * That API is old and needs to be reworked to match behaviour with A/V
> > > +         * (FIXME).
> > > +         *
> > > +         * For Audio, this is apparently required for the
> > > +         * fate-gaplessenc-itunes-to-ipod-aac test (FIXME).
> > > +         */
> > > +        if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE ||
> > > +            ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO)
> > > +            av_codec_set_pkt_timebase(ist->dec_ctx, ist->st->time_base);
> > > +  
> > 
> > I didn't look at the surrounding code much, so maybe I'm out of
> > context here, but I would think setting pkt_timebase on the decoder is
> > generally not a bad thing, for any type of codec?
> > Audio uses it to skip samples, subtitles for rescaling timestamps, at
> > least the cuvid video decoder uses it to rescale timestamps for the
> > external API as well.
> > 
> > So maybe set it unconditionally? Setting pkt_timebase is not a bad
> > thing, I would think. It was probably copied from the st->codec
> > before, as well.  

+1

> 
> If that's fine with everyone I can drop the condition and comment. But
> generally speaking, aside from subtitles it looks like it mostly works
> when it's not set, so should we warn when the user doesn't set it in order
> to avoid random undefined behaviour?

You mean within libavcodec? Maybe, but only f the decoder absolutely
needs it, not unconditionally.
diff mbox

Patch

diff --git a/cmdutils.c b/cmdutils.c
index 44f44cd..68deed9 100644
--- a/cmdutils.c
+++ b/cmdutils.c
@@ -1993,7 +1993,7 @@  AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id,
         codec            = s->oformat ? avcodec_find_encoder(codec_id)
                                       : avcodec_find_decoder(codec_id);
 
-    switch (st->codec->codec_type) {
+    switch (st->codecpar->codec_type) {
     case AVMEDIA_TYPE_VIDEO:
         prefix  = 'v';
         flags  |= AV_OPT_FLAG_VIDEO_PARAM;
@@ -2051,7 +2051,7 @@  AVDictionary **setup_find_stream_info_opts(AVFormatContext *s,
         return NULL;
     }
     for (i = 0; i < s->nb_streams; i++)
-        opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codec->codec_id,
+        opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id,
                                     s, s->streams[i], NULL);
     return opts;
 }
diff --git a/ffmpeg.c b/ffmpeg.c
index 5d7d32a..c025eb6 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -530,6 +530,7 @@  static void ffmpeg_cleanup(int ret)
         av_dict_free(&ost->sws_dict);
 
         avcodec_free_context(&ost->enc_ctx);
+        avcodec_parameters_free(&ost->ref_par);
 
         av_freep(&output_streams[i]);
     }
@@ -634,20 +635,13 @@  static void close_all_output_streams(OutputStream *ost, OSTFinished this_stream,
 
 static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
 {
+    AVStream *st = ost->st;
     AVBitStreamFilterContext *bsfc = ost->bitstream_filters;
     AVCodecContext          *avctx = ost->encoding_needed ? ost->enc_ctx : ost->st->codec;
     int ret;
 
-    if (!ost->st->codec->extradata_size && ost->enc_ctx->extradata_size) {
-        ost->st->codec->extradata = av_mallocz(ost->enc_ctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
-        if (ost->st->codec->extradata) {
-            memcpy(ost->st->codec->extradata, ost->enc_ctx->extradata, ost->enc_ctx->extradata_size);
-            ost->st->codec->extradata_size = ost->enc_ctx->extradata_size;
-        }
-    }
-
-    if ((avctx->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) ||
-        (avctx->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0))
+    if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) ||
+        (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0))
         pkt->pts = pkt->dts = AV_NOPTS_VALUE;
 
     /*
@@ -657,14 +651,14 @@  static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
      * Counting encoded video frames needs to be done separately because of
      * reordering, see do_video_out()
      */
-    if (!(avctx->codec_type == AVMEDIA_TYPE_VIDEO && avctx->codec)) {
+    if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed)) {
         if (ost->frame_number >= ost->max_frames) {
             av_packet_unref(pkt);
             return;
         }
         ost->frame_number++;
     }
-    if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
         int i;
         uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS,
                                               NULL);
@@ -696,14 +690,14 @@  static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
     }
     if (pkt->size == 0 && pkt->side_data_elems == 0)
         return;
-    if (!ost->st->codecpar->extradata && avctx->extradata) {
-        ost->st->codecpar->extradata = av_malloc(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
-        if (!ost->st->codecpar->extradata) {
+    if (!st->codecpar->extradata_size && ost->enc_ctx->extradata_size) {
+        st->codecpar->extradata = av_mallocz(ost->enc_ctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
+        if (!st->codecpar->extradata) {
             av_log(NULL, AV_LOG_ERROR, "Could not allocate extradata buffer to copy parser data.\n");
             exit_program(1);
         }
-        ost->st->codecpar->extradata_size = avctx->extradata_size;
-        memcpy(ost->st->codecpar->extradata, avctx->extradata, avctx->extradata_size);
+        st->codecpar->extradata_size = ost->enc_ctx->extradata_size;
+        memcpy(st->codecpar->extradata, ost->enc_ctx->extradata, ost->enc_ctx->extradata_size);
     }
 
     if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) {
@@ -718,13 +712,13 @@  static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
                      - FFMIN3(pkt->pts, pkt->dts, ost->last_mux_dts + 1)
                      - FFMAX3(pkt->pts, pkt->dts, ost->last_mux_dts + 1);
         }
-        if ((avctx->codec_type == AVMEDIA_TYPE_AUDIO || avctx->codec_type == AVMEDIA_TYPE_VIDEO) &&
+        if ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
             pkt->dts != AV_NOPTS_VALUE &&
-            !(avctx->codec_id == AV_CODEC_ID_VP9 && ost->stream_copy) &&
+            !(st->codecpar->codec_id == AV_CODEC_ID_VP9 && ost->stream_copy) &&
             ost->last_mux_dts != AV_NOPTS_VALUE) {
             int64_t max = ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT);
             if (pkt->dts < max) {
-                int loglevel = max - pkt->dts > 2 || avctx->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG;
+                int loglevel = max - pkt->dts > 2 || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG;
                 av_log(s, loglevel, "Non-monotonous DTS in output stream "
                        "%d:%d; previous: %"PRId64", current: %"PRId64"; ",
                        ost->file_index, ost->st->index, ost->last_mux_dts, pkt->dts);
@@ -932,7 +926,7 @@  static void do_video_out(AVFormatContext *s,
     int ret, format_video_sync;
     AVPacket pkt;
     AVCodecContext *enc = ost->enc_ctx;
-    AVCodecContext *mux_enc = ost->st->codec;
+    AVCodecParameters *mux_par = ost->st->codecpar;
     int nb_frames, nb0_frames, i;
     double delta, delta0;
     double duration = 0;
@@ -1093,9 +1087,9 @@  static void do_video_out(AVFormatContext *s,
            avoid any copies. We support temporarily the older
            method. */
         if (in_picture->interlaced_frame)
-            mux_enc->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT;
+            mux_par->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT;
         else
-            mux_enc->field_order = AV_FIELD_PROGRESSIVE;
+            mux_par->field_order = AV_FIELD_PROGRESSIVE;
         pkt.data   = (uint8_t *)in_picture;
         pkt.size   =  sizeof(AVPicture);
         pkt.pts    = av_rescale_q(in_picture->pts, enc->time_base, ost->st->time_base);
@@ -1114,11 +1108,11 @@  static void do_video_out(AVFormatContext *s,
 
         if (in_picture->interlaced_frame) {
             if (enc->codec->id == AV_CODEC_ID_MJPEG)
-                mux_enc->field_order = in_picture->top_field_first ? AV_FIELD_TT:AV_FIELD_BB;
+                mux_par->field_order = in_picture->top_field_first ? AV_FIELD_TT:AV_FIELD_BB;
             else
-                mux_enc->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT;
+                mux_par->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT;
         } else
-            mux_enc->field_order = AV_FIELD_PROGRESSIVE;
+            mux_par->field_order = AV_FIELD_PROGRESSIVE;
 
         in_picture->quality = enc->global_quality;
         in_picture->pict_type = 0;
@@ -1850,7 +1844,7 @@  static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
         opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base);
     opkt.dts -= ost_tb_start_time;
 
-    if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && pkt->dts != AV_NOPTS_VALUE) {
+    if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && pkt->dts != AV_NOPTS_VALUE) {
         int duration = av_get_audio_frame_duration(ist->dec_ctx, pkt->size);
         if(!duration)
             duration = ist->dec_ctx->frame_size;
@@ -1862,10 +1856,10 @@  static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
     opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base);
     opkt.flags    = pkt->flags;
     // FIXME remove the following 2 lines they shall be replaced by the bitstream filters
-    if (  ost->st->codec->codec_id != AV_CODEC_ID_H264
-       && ost->st->codec->codec_id != AV_CODEC_ID_MPEG1VIDEO
-       && ost->st->codec->codec_id != AV_CODEC_ID_MPEG2VIDEO
-       && ost->st->codec->codec_id != AV_CODEC_ID_VC1
+    if (  ost->st->codecpar->codec_id != AV_CODEC_ID_H264
+       && ost->st->codecpar->codec_id != AV_CODEC_ID_MPEG1VIDEO
+       && ost->st->codecpar->codec_id != AV_CODEC_ID_MPEG2VIDEO
+       && ost->st->codecpar->codec_id != AV_CODEC_ID_VC1
        ) {
         int ret = av_parser_change(ost->parser, ost->st->codec,
                              &opkt.data, &opkt.size,
@@ -1888,11 +1882,11 @@  static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
     av_copy_packet_side_data(&opkt, pkt);
 
 #if FF_API_LAVF_FMT_RAWPICTURE
-    if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
-        ost->st->codec->codec_id == AV_CODEC_ID_RAWVIDEO &&
+    if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
+        ost->st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO &&
         (of->ctx->oformat->flags & AVFMT_RAWPICTURE)) {
         /* store AVPicture in AVPacket, as expected by the output format */
-        int ret = avpicture_fill(&pict, opkt.data, ost->st->codec->pix_fmt, ost->st->codec->width, ost->st->codec->height);
+        int ret = avpicture_fill(&pict, opkt.data, ost->st->codecpar->format, ost->st->codecpar->width, ost->st->codecpar->height);
         if (ret < 0) {
             av_log(NULL, AV_LOG_FATAL, "avpicture_fill failed: %s\n",
                    av_err2str(ret));
@@ -2089,17 +2083,17 @@  static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
 
     // The following line may be required in some cases where there is no parser
     // or the parser does not has_b_frames correctly
-    if (ist->st->codec->has_b_frames < ist->dec_ctx->has_b_frames) {
+    if (ist->st->codecpar->video_delay < ist->dec_ctx->has_b_frames) {
         if (ist->dec_ctx->codec_id == AV_CODEC_ID_H264) {
-            ist->st->codec->has_b_frames = ist->dec_ctx->has_b_frames;
+            ist->st->codecpar->video_delay = ist->dec_ctx->has_b_frames;
         } else
             av_log(ist->dec_ctx, AV_LOG_WARNING,
-                   "has_b_frames is larger in decoder than demuxer %d > %d.\n"
+                   "video_delay is larger in decoder than demuxer %d > %d.\n"
                    "If you want to help, upload a sample "
                    "of this file to ftp://upload.ffmpeg.org/incoming/ "
                    "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)",
                    ist->dec_ctx->has_b_frames,
-                   ist->st->codec->has_b_frames);
+                   ist->st->codecpar->video_delay);
     }
 
     check_decode_result(ist, got_output, ret);
@@ -2560,6 +2554,23 @@  static int init_input_stream(int ist_index, char *error, int error_len)
 
         av_dict_set(&ist->decoder_opts, "sub_text_format", "ass", AV_DICT_DONT_OVERWRITE);
 
+        /*
+         * For subtitles, this is required by the decoding process in order to
+         * rescale the timestamps: in the current API the decoded subtitles
+         * have their pts expressed in AV_TIME_BASE, and thus the lavc
+         * internals need to know the stream time base in order to achieve the
+         * rescaling.
+         *
+         * That API is old and needs to be reworked to match behaviour with A/V
+         * (FIXME).
+         *
+         * For Audio, this is apparently required for the
+         * fate-gaplessenc-itunes-to-ipod-aac test (FIXME).
+         */
+        if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE ||
+            ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO)
+            av_codec_set_pkt_timebase(ist->dec_ctx, ist->st->time_base);
+
         if (!av_dict_get(ist->decoder_opts, "threads", NULL, 0))
             av_dict_set(&ist->decoder_opts, "threads", "auto", 0);
         if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) {
@@ -2644,12 +2655,20 @@  static int init_output_stream(OutputStream *ost, char *error, int error_len)
             av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low."
                                          " It takes bits/s as argument, not kbits/s\n");
 
-        ret = avcodec_copy_context(ost->st->codec, ost->enc_ctx);
+        ret = avcodec_parameters_from_context(ost->st->codecpar, ost->enc_ctx);
         if (ret < 0) {
             av_log(NULL, AV_LOG_FATAL,
                    "Error initializing the output stream codec context.\n");
             exit_program(1);
         }
+        /*
+         * FIXME: this is only so that the bitstream filters and parsers (that still
+         * work with a codec context) get the parameter values.
+         * This should go away with the new BSF/parser API.
+         */
+        ret = avcodec_copy_context(ost->st->codec, ost->enc_ctx);
+        if (ret < 0)
+            return ret;
 
         if (ost->enc_ctx->nb_coded_side_data) {
             int i;
@@ -2677,14 +2696,17 @@  static int init_output_stream(OutputStream *ost, char *error, int error_len)
         ost->st->time_base = av_add_q(ost->enc_ctx->time_base, (AVRational){0, 1});
         ost->st->codec->codec= ost->enc_ctx->codec;
     } else if (ost->stream_copy) {
-        ret = av_opt_set_dict(ost->st->codec, &ost->encoder_opts);
-        if (ret < 0) {
-           av_log(NULL, AV_LOG_FATAL,
-                  "Error setting up codec context options.\n");
-           return ret;
-        }
         // copy timebase while removing common factors
         ost->st->time_base = av_add_q(ost->st->codec->time_base, (AVRational){0, 1});
+
+        /*
+         * FIXME: this is only so that the bitstream filters and parsers (that still
+         * work with a codec context) get the parameter values.
+         * This should go away with the new BSF/parser API.
+         */
+        ret = avcodec_parameters_to_context(ost->st->codec, ost->st->codecpar);
+        if (ret < 0)
+            return ret;
     }
 
     return ret;
@@ -2762,7 +2784,7 @@  static void report_new_stream(int input_index, AVPacket *pkt)
         return;
     av_log(file->ctx, AV_LOG_WARNING,
            "New %s stream %d:%d at pos:%"PRId64" and DTS:%ss\n",
-           av_get_media_type_string(st->codec->codec_type),
+           av_get_media_type_string(st->codecpar->codec_type),
            input_index, pkt->stream_index,
            pkt->pos, av_ts2timestr(pkt->dts, &st->time_base));
     file->nb_streams_warn = pkt->stream_index + 1;
@@ -2843,8 +2865,6 @@  static int transcode_init(void)
 
     /* for each output stream, we compute the right encoding parameters */
     for (i = 0; i < nb_output_streams; i++) {
-        AVCodecContext *enc_ctx;
-        AVCodecContext *dec_ctx = NULL;
         ost = output_streams[i];
         oc  = output_files[ost->file_index]->ctx;
         ist = get_input_stream(ost);
@@ -2852,67 +2872,75 @@  static int transcode_init(void)
         if (ost->attachment_filename)
             continue;
 
-        enc_ctx = ost->stream_copy ? ost->st->codec : ost->enc_ctx;
-
         if (ist) {
-            dec_ctx = ist->dec_ctx;
-
             ost->st->disposition          = ist->st->disposition;
-            enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location;
         } else {
             for (j=0; j<oc->nb_streams; j++) {
                 AVStream *st = oc->streams[j];
-                if (st != ost->st && st->codec->codec_type == enc_ctx->codec_type)
+                if (st != ost->st && st->codecpar->codec_type == ost->st->codecpar->codec_type)
                     break;
             }
             if (j == oc->nb_streams)
-                if (enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO || enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO)
+                if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ||
+                    ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
                     ost->st->disposition = AV_DISPOSITION_DEFAULT;
         }
 
         if (ost->stream_copy) {
+            AVCodecParameters *par_dst = ost->st->codecpar;
+            AVCodecParameters *par_src = ost->ref_par;
             AVRational sar;
             uint64_t extra_size;
 
             av_assert0(ist && !ost->filter);
 
-            extra_size = (uint64_t)dec_ctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE;
+            avcodec_parameters_to_context(ost->enc_ctx, ist->st->codecpar);
+            ret = av_opt_set_dict(ost->enc_ctx, &ost->encoder_opts);
+            if (ret < 0) {
+                av_log(NULL, AV_LOG_FATAL,
+                       "Error setting up codec context options.\n");
+                return ret;
+            }
+            avcodec_parameters_from_context(par_src, ost->enc_ctx);
+
+            extra_size = (uint64_t)par_src->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE;
 
             if (extra_size > INT_MAX) {
                 return AVERROR(EINVAL);
             }
 
             /* if stream_copy is selected, no need to decode or encode */
-            enc_ctx->codec_id   = dec_ctx->codec_id;
-            enc_ctx->codec_type = dec_ctx->codec_type;
+            par_dst->codec_id   = par_src->codec_id;
+            par_dst->codec_type = par_src->codec_type;
 
-            if (!enc_ctx->codec_tag) {
+            if (!par_dst->codec_tag) {
                 unsigned int codec_tag;
                 if (!oc->oformat->codec_tag ||
-                     av_codec_get_id (oc->oformat->codec_tag, dec_ctx->codec_tag) == enc_ctx->codec_id ||
-                     !av_codec_get_tag2(oc->oformat->codec_tag, dec_ctx->codec_id, &codec_tag))
-                    enc_ctx->codec_tag = dec_ctx->codec_tag;
+                     av_codec_get_id (oc->oformat->codec_tag, par_src->codec_tag) == par_dst->codec_id ||
+                     !av_codec_get_tag2(oc->oformat->codec_tag, par_src->codec_id, &codec_tag))
+                    par_dst->codec_tag = par_src->codec_tag;
             }
 
-            enc_ctx->bit_rate       = dec_ctx->bit_rate;
-            enc_ctx->rc_max_rate    = dec_ctx->rc_max_rate;
-            enc_ctx->rc_buffer_size = dec_ctx->rc_buffer_size;
-            enc_ctx->field_order    = dec_ctx->field_order;
-            if (dec_ctx->extradata_size) {
-                enc_ctx->extradata      = av_mallocz(extra_size);
-                if (!enc_ctx->extradata) {
+            par_dst->bit_rate        = par_src->bit_rate;
+            par_dst->field_order     = par_src->field_order;
+            par_dst->chroma_location = par_src->chroma_location;
+            if (par_src->extradata_size) {
+                par_dst->extradata      = av_mallocz(extra_size);
+                if (!par_dst->extradata) {
                     return AVERROR(ENOMEM);
                 }
-                memcpy(enc_ctx->extradata, dec_ctx->extradata, dec_ctx->extradata_size);
+                memcpy(par_dst->extradata, par_src->extradata, par_src->extradata_size);
             }
-            enc_ctx->extradata_size= dec_ctx->extradata_size;
-            enc_ctx->bits_per_coded_sample  = dec_ctx->bits_per_coded_sample;
-            enc_ctx->bits_per_raw_sample    = dec_ctx->bits_per_raw_sample;
+            par_dst->extradata_size= par_src->extradata_size;
+            par_dst->bits_per_coded_sample  = par_src->bits_per_coded_sample;
+            par_dst->bits_per_raw_sample    = par_src->bits_per_raw_sample;
 
             if (!ost->frame_rate.num)
                 ost->frame_rate = ist->framerate;
             ost->st->avg_frame_rate = ost->frame_rate;
 
+            ost->st->time_base = ist->st->time_base;
+
             ret = avformat_transfer_internal_stream_timing_info(oc->oformat, ost->st, ist->st, copy_tb);
             if (ret < 0)
                 return ret;
@@ -2941,59 +2969,54 @@  static int transcode_init(void)
                 }
             }
 
-            ost->parser = av_parser_init(enc_ctx->codec_id);
+            ost->parser = av_parser_init(par_dst->codec_id);
 
-            switch (enc_ctx->codec_type) {
+            switch (par_dst->codec_type) {
             case AVMEDIA_TYPE_AUDIO:
                 if (audio_volume != 256) {
                     av_log(NULL, AV_LOG_FATAL, "-acodec copy and -vol are incompatible (frames are not decoded)\n");
                     exit_program(1);
                 }
-                enc_ctx->channel_layout     = dec_ctx->channel_layout;
-                enc_ctx->sample_rate        = dec_ctx->sample_rate;
-                enc_ctx->channels           = dec_ctx->channels;
-                enc_ctx->frame_size         = dec_ctx->frame_size;
-                enc_ctx->audio_service_type = dec_ctx->audio_service_type;
-                enc_ctx->block_align        = dec_ctx->block_align;
-                enc_ctx->initial_padding    = dec_ctx->delay;
-                enc_ctx->trailing_padding   = dec_ctx->trailing_padding;
-                enc_ctx->profile            = dec_ctx->profile;
-#if FF_API_AUDIOENC_DELAY
-                enc_ctx->delay              = dec_ctx->delay;
-#endif
-                if((enc_ctx->block_align == 1 || enc_ctx->block_align == 1152 || enc_ctx->block_align == 576) && enc_ctx->codec_id == AV_CODEC_ID_MP3)
-                    enc_ctx->block_align= 0;
-                if(enc_ctx->codec_id == AV_CODEC_ID_AC3)
-                    enc_ctx->block_align= 0;
+                par_dst->channel_layout     = par_src->channel_layout;
+                par_dst->sample_rate        = par_src->sample_rate;
+                par_dst->channels           = par_src->channels;
+                par_dst->block_align        = par_src->block_align;
+                par_dst->initial_padding    = par_src->initial_padding;
+                par_dst->trailing_padding   = par_src->trailing_padding;
+                par_dst->profile            = par_src->profile;
+                if((par_dst->block_align == 1 || par_dst->block_align == 1152 || par_dst->block_align == 576) && par_dst->codec_id == AV_CODEC_ID_MP3)
+                    par_dst->block_align= 0;
+                if(par_dst->codec_id == AV_CODEC_ID_AC3)
+                    par_dst->block_align= 0;
                 break;
             case AVMEDIA_TYPE_VIDEO:
-                enc_ctx->pix_fmt            = dec_ctx->pix_fmt;
-                enc_ctx->colorspace         = dec_ctx->colorspace;
-                enc_ctx->color_range        = dec_ctx->color_range;
-                enc_ctx->color_primaries    = dec_ctx->color_primaries;
-                enc_ctx->color_trc          = dec_ctx->color_trc;
-                enc_ctx->width              = dec_ctx->width;
-                enc_ctx->height             = dec_ctx->height;
-                enc_ctx->has_b_frames       = dec_ctx->has_b_frames;
-                enc_ctx->profile            = dec_ctx->profile;
+                par_dst->format             = par_src->format;
+                par_dst->color_space        = par_src->color_space;
+                par_dst->color_range        = par_src->color_range;
+                par_dst->color_primaries    = par_src->color_primaries;
+                par_dst->color_trc          = par_src->color_trc;
+                par_dst->width              = par_src->width;
+                par_dst->height             = par_src->height;
+                par_dst->video_delay        = par_src->video_delay;
+                par_dst->profile            = par_src->profile;
                 if (ost->frame_aspect_ratio.num) { // overridden by the -aspect cli option
                     sar =
                         av_mul_q(ost->frame_aspect_ratio,
-                                 (AVRational){ enc_ctx->height, enc_ctx->width });
+                                 (AVRational){ par_dst->height, par_dst->width });
                     av_log(NULL, AV_LOG_WARNING, "Overriding aspect ratio "
                            "with stream copy may produce invalid files\n");
                 }
                 else if (ist->st->sample_aspect_ratio.num)
                     sar = ist->st->sample_aspect_ratio;
                 else
-                    sar = dec_ctx->sample_aspect_ratio;
-                ost->st->sample_aspect_ratio = enc_ctx->sample_aspect_ratio = sar;
+                    sar = par_src->sample_aspect_ratio;
+                ost->st->sample_aspect_ratio = par_dst->sample_aspect_ratio = sar;
                 ost->st->avg_frame_rate = ist->st->avg_frame_rate;
                 ost->st->r_frame_rate = ist->st->r_frame_rate;
                 break;
             case AVMEDIA_TYPE_SUBTITLE:
-                enc_ctx->width  = dec_ctx->width;
-                enc_ctx->height = dec_ctx->height;
+                par_dst->width  = par_src->width;
+                par_dst->height = par_src->height;
                 break;
             case AVMEDIA_TYPE_UNKNOWN:
             case AVMEDIA_TYPE_DATA:
@@ -3003,8 +3026,17 @@  static int transcode_init(void)
                 abort();
             }
         } else {
+            AVCodecContext *enc_ctx = ost->enc_ctx;
+            AVCodecContext *dec_ctx = NULL;
+
             set_encoder_id(output_files[ost->file_index], ost);
 
+            if (ist) {
+                dec_ctx = ist->dec_ctx;
+
+                enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location;
+            }
+
 #if CONFIG_LIBMFX
             if (qsv_transcode_init(ost))
                 exit_program(1);
@@ -3136,8 +3168,8 @@  static int transcode_init(void)
             case AVMEDIA_TYPE_SUBTITLE:
                 enc_ctx->time_base = (AVRational){1, 1000};
                 if (!enc_ctx->width) {
-                    enc_ctx->width     = input_streams[ost->source_index]->st->codec->width;
-                    enc_ctx->height    = input_streams[ost->source_index]->st->codec->height;
+                    enc_ctx->width     = input_streams[ost->source_index]->st->codecpar->width;
+                    enc_ctx->height    = input_streams[ost->source_index]->st->codecpar->height;
                 }
                 break;
             case AVMEDIA_TYPE_DATA:
diff --git a/ffmpeg.h b/ffmpeg.h
index 49d65d8..5caf584 100644
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -418,6 +418,7 @@  typedef struct OutputStream {
     int64_t last_mux_dts;
     AVBitStreamFilterContext *bitstream_filters;
     AVCodecContext *enc_ctx;
+    AVCodecParameters *ref_par; /* associated input codec parameters with encoders options applied */
     AVCodec *enc;
     int64_t max_frames;
     AVFrame *filtered_frame;
diff --git a/ffmpeg_filter.c b/ffmpeg_filter.c
index 76030cf..27aeca0 100644
--- a/ffmpeg_filter.c
+++ b/ffmpeg_filter.c
@@ -94,19 +94,19 @@  void choose_sample_fmt(AVStream *st, AVCodec *codec)
     if (codec && codec->sample_fmts) {
         const enum AVSampleFormat *p = codec->sample_fmts;
         for (; *p != -1; p++) {
-            if (*p == st->codec->sample_fmt)
+            if (*p == st->codecpar->format)
                 break;
         }
         if (*p == -1) {
-            if((codec->capabilities & AV_CODEC_CAP_LOSSLESS) && av_get_sample_fmt_name(st->codec->sample_fmt) > av_get_sample_fmt_name(codec->sample_fmts[0]))
+            if((codec->capabilities & AV_CODEC_CAP_LOSSLESS) && av_get_sample_fmt_name(st->codecpar->format) > av_get_sample_fmt_name(codec->sample_fmts[0]))
                 av_log(NULL, AV_LOG_ERROR, "Conversion will not be lossless.\n");
-            if(av_get_sample_fmt_name(st->codec->sample_fmt))
+            if(av_get_sample_fmt_name(st->codecpar->format))
             av_log(NULL, AV_LOG_WARNING,
                    "Incompatible sample format '%s' for codec '%s', auto-selecting format '%s'\n",
-                   av_get_sample_fmt_name(st->codec->sample_fmt),
+                   av_get_sample_fmt_name(st->codecpar->format),
                    codec->name,
                    av_get_sample_fmt_name(codec->sample_fmts[0]));
-            st->codec->sample_fmt = codec->sample_fmts[0];
+            st->codecpar->format = codec->sample_fmts[0];
         }
     }
 }
@@ -251,7 +251,7 @@  static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
         s = input_files[file_idx]->ctx;
 
         for (i = 0; i < s->nb_streams; i++) {
-            enum AVMediaType stream_type = s->streams[i]->codec->codec_type;
+            enum AVMediaType stream_type = s->streams[i]->codecpar->codec_type;
             if (stream_type != type &&
                 !(stream_type == AVMEDIA_TYPE_SUBTITLE &&
                   type == AVMEDIA_TYPE_VIDEO /* sub2video hack */))
@@ -611,7 +611,7 @@  static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter,
         int i;
 
         for (i=0; i<of->ctx->nb_streams; i++)
-            if (of->ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+            if (of->ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
                 break;
 
         if (i<of->ctx->nb_streams) {
@@ -673,15 +673,15 @@  static int sub2video_prepare(InputStream *ist)
     int i, w, h;
 
     /* Compute the size of the canvas for the subtitles stream.
-       If the subtitles codec has set a size, use it. Otherwise use the
+       If the subtitles codecpar has set a size, use it. Otherwise use the
        maximum dimensions of the video streams in the same file. */
     w = ist->dec_ctx->width;
     h = ist->dec_ctx->height;
     if (!(w && h)) {
         for (i = 0; i < avf->nb_streams; i++) {
-            if (avf->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
-                w = FFMAX(w, avf->streams[i]->codec->width);
-                h = FFMAX(h, avf->streams[i]->codec->height);
+            if (avf->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+                w = FFMAX(w, avf->streams[i]->codecpar->width);
+                h = FFMAX(h, avf->streams[i]->codecpar->height);
             }
         }
         if (!(w && h)) {
@@ -1081,7 +1081,7 @@  int configure_filtergraph(FilterGraph *fg)
             /* identical to the same check in ffmpeg.c, needed because
                complex filter graphs are initialized earlier */
             av_log(NULL, AV_LOG_ERROR, "Encoder (codec %s) not found for output stream #%d:%d\n",
-                     avcodec_get_name(ost->st->codec->codec_id), ost->file_index, ost->index);
+                     avcodec_get_name(ost->st->codecpar->codec_id), ost->file_index, ost->index);
             return AVERROR(EINVAL);
         }
         if (ost->enc->type == AVMEDIA_TYPE_AUDIO &&
diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c
index 0c0d3a6..81e3979 100644
--- a/ffmpeg_opt.c
+++ b/ffmpeg_opt.c
@@ -429,12 +429,12 @@  static int opt_map_channel(void *optctx, const char *opt, const char *arg)
         exit_program(1);
     }
     st = input_files[m->file_idx]->ctx->streams[m->stream_idx];
-    if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
+    if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
         av_log(NULL, AV_LOG_FATAL, "mapchan: stream #%d.%d is not an audio stream.\n",
                m->file_idx, m->stream_idx);
         exit_program(1);
     }
-    if (m->channel_idx < 0 || m->channel_idx >= st->codec->channels) {
+    if (m->channel_idx < 0 || m->channel_idx >= st->codecpar->channels) {
         av_log(NULL, AV_LOG_FATAL, "mapchan: invalid audio channel #%d.%d.%d\n",
                m->file_idx, m->stream_idx, m->channel_idx);
         exit_program(1);
@@ -634,11 +634,11 @@  static AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream *
 
     MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, st);
     if (codec_name) {
-        AVCodec *codec = find_codec_or_die(codec_name, st->codec->codec_type, 0);
-        st->codec->codec_id = codec->id;
+        AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0);
+        st->codecpar->codec_id = codec->id;
         return codec;
     } else
-        return avcodec_find_decoder(st->codec->codec_id);
+        return avcodec_find_decoder(st->codecpar->codec_id);
 }
 
 /* Add all the streams from the given input file to the global
@@ -649,14 +649,15 @@  static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
 
     for (i = 0; i < ic->nb_streams; i++) {
         AVStream *st = ic->streams[i];
-        AVCodecContext *dec = st->codec;
+        AVCodecParameters *par = st->codecpar;
         InputStream *ist = av_mallocz(sizeof(*ist));
         char *framerate = NULL, *hwaccel = NULL, *hwaccel_device = NULL;
         char *hwaccel_output_format = NULL;
         char *codec_tag = NULL;
         char *next;
         char *discard_str = NULL;
-        const AVOption *discard_opt = av_opt_find(dec, "skip_frame", NULL, 0, 0);
+        const AVClass *cc = avcodec_get_class();
+        const AVOption *discard_opt = av_opt_find(&cc, "skip_frame", NULL, 0, 0);
 
         if (!ist)
             exit_program(1);
@@ -683,18 +684,18 @@  static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
             uint32_t tag = strtol(codec_tag, &next, 0);
             if (*next)
                 tag = AV_RL32(codec_tag);
-            st->codec->codec_tag = tag;
+            st->codecpar->codec_tag = tag;
         }
 
         ist->dec = choose_decoder(o, ic, st);
-        ist->decoder_opts = filter_codec_opts(o->g->codec_opts, ist->st->codec->codec_id, ic, st, ist->dec);
+        ist->decoder_opts = filter_codec_opts(o->g->codec_opts, ist->st->codecpar->codec_id, ic, st, ist->dec);
 
         ist->reinit_filters = -1;
         MATCH_PER_STREAM_OPT(reinit_filters, i, ist->reinit_filters, ic, st);
 
         MATCH_PER_STREAM_OPT(discard, str, discard_str, ic, st);
         ist->user_set_discard = AVDISCARD_NONE;
-        if (discard_str && av_opt_eval_int(dec, discard_opt, discard_str, &ist->user_set_discard) < 0) {
+        if (discard_str && av_opt_eval_int(&cc, discard_opt, discard_str, &ist->user_set_discard) < 0) {
             av_log(NULL, AV_LOG_ERROR, "Error parsing discard %s.\n",
                     discard_str);
             exit_program(1);
@@ -708,22 +709,30 @@  static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
             exit_program(1);
         }
 
-        ret = avcodec_copy_context(ist->dec_ctx, dec);
+        ret = avcodec_parameters_to_context(ist->dec_ctx, par);
         if (ret < 0) {
             av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n");
             exit_program(1);
         }
 
-        switch (dec->codec_type) {
+        switch (par->codec_type) {
         case AVMEDIA_TYPE_VIDEO:
             if(!ist->dec)
-                ist->dec = avcodec_find_decoder(dec->codec_id);
+                ist->dec = avcodec_find_decoder(par->codec_id);
 #if FF_API_EMU_EDGE
-            if (av_codec_get_lowres(dec)) {
-                dec->flags |= CODEC_FLAG_EMU_EDGE;
+            if (av_codec_get_lowres(st->codec)) {
+                ist->dec_ctx->lowres = av_codec_get_lowres(st->codec);
+                ist->dec_ctx->width  = st->codec->width;
+                ist->dec_ctx->height = st->codec->height;
+                ist->dec_ctx->coded_width  = st->codec->coded_width;
+                ist->dec_ctx->coded_height = st->codec->coded_height;
+                ist->dec_ctx->flags |= CODEC_FLAG_EMU_EDGE;
             }
 #endif
 
+            // avformat_find_stream_info() doesn't set this for us anymore.
+            ist->dec_ctx->framerate = st->avg_frame_rate;
+
             ist->resample_height  = ist->dec_ctx->height;
             ist->resample_width   = ist->dec_ctx->width;
             ist->resample_pix_fmt = ist->dec_ctx->pix_fmt;
@@ -803,7 +812,7 @@  static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
         case AVMEDIA_TYPE_SUBTITLE: {
             char *canvas_size = NULL;
             if(!ist->dec)
-                ist->dec = avcodec_find_decoder(dec->codec_id);
+                ist->dec = avcodec_find_decoder(par->codec_id);
             MATCH_PER_STREAM_OPT(fix_sub_duration, i, ist->fix_sub_duration, ic, st);
             MATCH_PER_STREAM_OPT(canvas_sizes, str, canvas_size, ic, st);
             if (canvas_size &&
@@ -819,6 +828,12 @@  static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
         default:
             abort();
         }
+
+        ret = avcodec_parameters_from_context(par, ist->dec_ctx);
+        if (ret < 0) {
+            av_log(NULL, AV_LOG_ERROR, "Error initializing the decoder context.\n");
+            exit_program(1);
+        }
     }
 }
 
@@ -857,7 +872,7 @@  static void dump_attachment(AVStream *st, const char *filename)
     AVIOContext *out = NULL;
     AVDictionaryEntry *e;
 
-    if (!st->codec->extradata_size) {
+    if (!st->codecpar->extradata_size) {
         av_log(NULL, AV_LOG_WARNING, "No extradata to dump in stream #%d:%d.\n",
                nb_input_files - 1, st->index);
         return;
@@ -878,7 +893,7 @@  static void dump_attachment(AVStream *st, const char *filename)
         exit_program(1);
     }
 
-    avio_write(out, st->codec->extradata, st->codec->extradata_size);
+    avio_write(out, st->codecpar->extradata, st->codecpar->extradata_size);
     avio_flush(out);
     avio_close(out);
 }
@@ -1028,8 +1043,8 @@  static int open_input_file(OptionsContext *o, const char *filename)
         if (!(ic->iformat->flags & AVFMT_SEEK_TO_PTS)) {
             int dts_heuristic = 0;
             for (i=0; i<ic->nb_streams; i++) {
-                AVCodecContext *avctx = ic->streams[i]->codec;
-                if (avctx->has_b_frames)
+                const AVCodecParameters *par = ic->streams[i]->codecpar;
+                if (par->video_delay)
                     dts_heuristic = 1;
             }
             if (dts_heuristic) {
@@ -1176,28 +1191,28 @@  static int get_preset_file_2(const char *preset_name, const char *codec_name, AV
 
 static int choose_encoder(OptionsContext *o, AVFormatContext *s, OutputStream *ost)
 {
-    enum AVMediaType type = ost->st->codec->codec_type;
+    enum AVMediaType type = ost->st->codecpar->codec_type;
     char *codec_name = NULL;
 
     if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO || type == AVMEDIA_TYPE_SUBTITLE) {
         MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st);
         if (!codec_name) {
-            ost->st->codec->codec_id = av_guess_codec(s->oformat, NULL, s->filename,
-                                                      NULL, ost->st->codec->codec_type);
-            ost->enc = avcodec_find_encoder(ost->st->codec->codec_id);
+            ost->st->codecpar->codec_id = av_guess_codec(s->oformat, NULL, s->filename,
+                                                         NULL, ost->st->codecpar->codec_type);
+            ost->enc = avcodec_find_encoder(ost->st->codecpar->codec_id);
             if (!ost->enc) {
                 av_log(NULL, AV_LOG_FATAL, "Automatic encoder selection failed for "
                        "output stream #%d:%d. Default encoder for format %s (codec %s) is "
                        "probably disabled. Please choose an encoder manually.\n",
                        ost->file_index, ost->index, s->oformat->name,
-                       avcodec_get_name(ost->st->codec->codec_id));
+                       avcodec_get_name(ost->st->codecpar->codec_id));
                 return AVERROR_ENCODER_NOT_FOUND;
             }
         } else if (!strcmp(codec_name, "copy"))
             ost->stream_copy = 1;
         else {
-            ost->enc = find_codec_or_die(codec_name, ost->st->codec->codec_type, 1);
-            ost->st->codec->codec_id = ost->enc->id;
+            ost->enc = find_codec_or_die(codec_name, ost->st->codecpar->codec_type, 1);
+            ost->st->codecpar->codec_id = ost->enc->id;
         }
         ost->encoding_needed = !ost->stream_copy;
     } else {
@@ -1235,7 +1250,7 @@  static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
     ost->file_index = nb_output_files - 1;
     ost->index      = idx;
     ost->st         = st;
-    st->codec->codec_type = type;
+    st->codecpar->codec_type = type;
 
     ret = choose_encoder(o, oc, ost);
     if (ret < 0) {
@@ -1251,6 +1266,12 @@  static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
     }
     ost->enc_ctx->codec_type = type;
 
+    ost->ref_par = avcodec_parameters_alloc();
+    if (!ost->ref_par) {
+        av_log(NULL, AV_LOG_ERROR, "Error allocating the encoding parameters.\n");
+        exit_program(1);
+    }
+
     if (ost->enc) {
         AVIOContext *s = NULL;
         char *buf = NULL, *arg = NULL, *preset = NULL;
@@ -1328,7 +1349,7 @@  static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
         uint32_t tag = strtol(codec_tag, &next, 0);
         if (*next)
             tag = AV_RL32(codec_tag);
-        ost->st->codec->codec_tag =
+        ost->st->codecpar->codec_tag =
         ost->enc_ctx->codec_tag = tag;
     }
 
@@ -1425,7 +1446,7 @@  static char *get_ost_filters(OptionsContext *o, AVFormatContext *oc,
     else if (ost->filters)
         return av_strdup(ost->filters);
 
-    return av_strdup(st->codec->codec_type == AVMEDIA_TYPE_VIDEO ?
+    return av_strdup(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ?
                      "null" : "anull");
 }
 
@@ -1857,9 +1878,9 @@  static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const ch
         AVCodec *codec;
         const char *enc_config;
 
-        codec = avcodec_find_encoder(ic->streams[i]->codec->codec_id);
+        codec = avcodec_find_encoder(ic->streams[i]->codecpar->codec_id);
         if (!codec) {
-            av_log(s, AV_LOG_ERROR, "no encoder found for codec id %i\n", ic->streams[i]->codec->codec_id);
+            av_log(s, AV_LOG_ERROR, "no encoder found for codec id %i\n", ic->streams[i]->codecpar->codec_id);
             return AVERROR(EINVAL);
         }
         if (codec->type == AVMEDIA_TYPE_AUDIO)
@@ -1878,10 +1899,10 @@  static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const ch
             av_dict_free(&opts);
         }
 
-        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy)
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy)
             choose_sample_fmt(st, codec);
-        else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy)
-            choose_pixel_fmt(st, st->codec, codec, st->codec->pix_fmt);
+        else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy)
+            choose_pixel_fmt(st, st->codec, codec, st->codecpar->format);
         avcodec_copy_context(ost->enc_ctx, st->codec);
         if (enc_config)
             av_dict_parse_string(&ost->encoder_opts, enc_config, "=", ",", 0);
@@ -2053,18 +2074,18 @@  static int open_output_file(OptionsContext *o, const char *filename)
             ost = output_streams[j];
             for (i = 0; i < nb_input_streams; i++) {
                 ist = input_streams[i];
-                if(ist->st->codec->codec_type == ost->st->codec->codec_type){
+                if(ist->st->codecpar->codec_type == ost->st->codecpar->codec_type){
                     ost->sync_ist= ist;
                     ost->source_index= i;
-                    if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) ost->avfilter = av_strdup("anull");
-                    if(ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) ost->avfilter = av_strdup("null");
+                    if(ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ost->avfilter = av_strdup("anull");
+                    if(ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) ost->avfilter = av_strdup("null");
                     ist->discard = 0;
                     ist->st->discard = ist->user_set_discard;
                     break;
                 }
             }
             if(!ost->sync_ist){
-                av_log(NULL, AV_LOG_FATAL, "Missing %s stream which is required by this ffm\n", av_get_media_type_string(ost->st->codec->codec_type));
+                av_log(NULL, AV_LOG_FATAL, "Missing %s stream which is required by this ffm\n", av_get_media_type_string(ost->st->codecpar->codec_type));
                 exit_program(1);
             }
         }
@@ -2079,10 +2100,10 @@  static int open_output_file(OptionsContext *o, const char *filename)
             for (i = 0; i < nb_input_streams; i++) {
                 int new_area;
                 ist = input_streams[i];
-                new_area = ist->st->codec->width * ist->st->codec->height + 100000000*!!ist->st->codec_info_nb_frames;
+                new_area = ist->st->codecpar->width * ist->st->codecpar->height + 100000000*!!ist->st->codec_info_nb_frames;
                 if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
                     new_area = 1;
-                if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+                if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
                     new_area > area) {
                     if((qcr==MKTAG('A', 'P', 'I', 'C')) && !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
                         continue;
@@ -2100,8 +2121,8 @@  static int open_output_file(OptionsContext *o, const char *filename)
             for (i = 0; i < nb_input_streams; i++) {
                 int score;
                 ist = input_streams[i];
-                score = ist->st->codec->channels + 100000000*!!ist->st->codec_info_nb_frames;
-                if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
+                score = ist->st->codecpar->channels + 100000000*!!ist->st->codec_info_nb_frames;
+                if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
                     score > best_score) {
                     best_score = score;
                     idx = i;
@@ -2115,9 +2136,9 @@  static int open_output_file(OptionsContext *o, const char *filename)
         MATCH_PER_TYPE_OPT(codec_names, str, subtitle_codec_name, oc, "s");
         if (!o->subtitle_disable && (avcodec_find_encoder(oc->oformat->subtitle_codec) || subtitle_codec_name)) {
             for (i = 0; i < nb_input_streams; i++)
-                if (input_streams[i]->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+                if (input_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
                     AVCodecDescriptor const *input_descriptor =
-                        avcodec_descriptor_get(input_streams[i]->st->codec->codec_id);
+                        avcodec_descriptor_get(input_streams[i]->st->codecpar->codec_id);
                     AVCodecDescriptor const *output_descriptor = NULL;
                     AVCodec const *output_codec =
                         avcodec_find_encoder(oc->oformat->subtitle_codec);
@@ -2143,8 +2164,8 @@  static int open_output_file(OptionsContext *o, const char *filename)
         if (!o->data_disable ) {
             enum AVCodecID codec_id = av_guess_codec(oc->oformat, NULL, filename, NULL, AVMEDIA_TYPE_DATA);
             for (i = 0; codec_id != AV_CODEC_ID_NONE && i < nb_input_streams; i++) {
-                if (input_streams[i]->st->codec->codec_type == AVMEDIA_TYPE_DATA
-                    && input_streams[i]->st->codec->codec_id == codec_id )
+                if (input_streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_DATA
+                    && input_streams[i]->st->codecpar->codec_id == codec_id )
                     new_data_stream(o, oc, i);
             }
         }
@@ -2181,17 +2202,17 @@  loop_end:
                 int src_idx = input_files[map->file_index]->ist_index + map->stream_index;
 
                 ist = input_streams[input_files[map->file_index]->ist_index + map->stream_index];
-                if(o->subtitle_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE)
+                if(o->subtitle_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
                     continue;
-                if(o->   audio_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+                if(o->   audio_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
                     continue;
-                if(o->   video_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+                if(o->   video_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
                     continue;
-                if(o->    data_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_DATA)
+                if(o->    data_disable && ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA)
                     continue;
 
                 ost = NULL;
-                switch (ist->st->codec->codec_type) {
+                switch (ist->st->codecpar->codec_type) {
                 case AVMEDIA_TYPE_VIDEO:      ost = new_video_stream     (o, oc, src_idx); break;
                 case AVMEDIA_TYPE_AUDIO:      ost = new_audio_stream     (o, oc, src_idx); break;
                 case AVMEDIA_TYPE_SUBTITLE:   ost = new_subtitle_stream  (o, oc, src_idx); break;
@@ -2247,8 +2268,8 @@  loop_end:
 
         ost = new_attachment_stream(o, oc, -1);
         ost->attachment_filename       = o->attachments[i];
-        ost->st->codec->extradata      = attachment;
-        ost->st->codec->extradata_size = len;
+        ost->st->codecpar->extradata      = attachment;
+        ost->st->codecpar->extradata_size = len;
 
         p = strrchr(o->attachments[i], '/');
         av_dict_set(&ost->st->metadata, "filename", (p && *p) ? p + 1 : o->attachments[i], AV_DICT_DONT_OVERWRITE);
@@ -2322,8 +2343,8 @@  loop_end:
             InputStream *ist = input_streams[ost->source_index];
             ist->decoding_needed |= DECODING_FOR_OST;
 
-            if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
-                ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+            if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
+                ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
                 err = init_simple_filtergraph(ist, ost);
                 if (err < 0) {
                     av_log(NULL, AV_LOG_ERROR,
@@ -2570,11 +2591,10 @@  static int opt_target(void *optctx, const char *opt, const char *arg)
             int i, j, fr;
             for (j = 0; j < nb_input_files; j++) {
                 for (i = 0; i < input_files[j]->nb_streams; i++) {
-                    AVCodecContext *c = input_files[j]->ctx->streams[i]->codec;
-                    if (c->codec_type != AVMEDIA_TYPE_VIDEO ||
-                        !c->time_base.num)
+                    AVStream *st = input_files[j]->ctx->streams[i];
+                    if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
                         continue;
-                    fr = c->time_base.den * 1000 / c->time_base.num;
+                    fr = st->time_base.den * 1000 / st->time_base.num;
                     if (fr == 25000) {
                         norm = PAL;
                         break;
diff --git a/libavformat/utils.c b/libavformat/utils.c
index f043bae..b439273 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -5339,7 +5339,7 @@  int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt,
         }
     }
 
-    if (enc_ctx->codec_tag == AV_RL32("tmcd")
+    if (ost->codecpar->codec_tag == AV_RL32("tmcd")
         && dec_ctx->time_base.num < dec_ctx->time_base.den
         && dec_ctx->time_base.num > 0
         && 121LL*dec_ctx->time_base.num > dec_ctx->time_base.den) {
diff --git a/tests/ref/lavf/mkv b/tests/ref/lavf/mkv
index 72fc291..5b0d386 100644
--- a/tests/ref/lavf/mkv
+++ b/tests/ref/lavf/mkv
@@ -1,6 +1,6 @@ 
-c081514c38735524ab09dbd2a498b7b3 *./tests/data/lavf/lavf.mkv
+5b982c8dfbadc71f51b206cbd10b9a71 *./tests/data/lavf/lavf.mkv
 472875 ./tests/data/lavf/lavf.mkv
 ./tests/data/lavf/lavf.mkv CRC=0xec6c3c68
-d1fc3a31150d00aebbd674862640f701 *./tests/data/lavf/lavf.mkv
+b4a295bae8e6cf536563cb840386f3a4 *./tests/data/lavf/lavf.mkv
 320551 ./tests/data/lavf/lavf.mkv
 ./tests/data/lavf/lavf.mkv CRC=0xec6c3c68