Merge commit '549d0bdca53af7a6e0c612ab4b03baecf3a5878f'
authorJames Almer <jamrial@gmail.com>
Sat, 22 Apr 2017 23:06:47 +0000 (20:06 -0300)
committerJames Almer <jamrial@gmail.com>
Sat, 22 Apr 2017 23:06:47 +0000 (20:06 -0300)
* commit '549d0bdca53af7a6e0c612ab4b03baecf3a5878f':
  decode: be more explicit about storing the last packet properties

Also copy pkt->size in extract_packet_props(), as it's needed for
AVFrame.pkt_size

Merged-by: James Almer <jamrial@gmail.com>
1  2 
libavcodec/decode.c
libavcodec/internal.h
libavcodec/pthread_frame.c
libavcodec/rawdec.c
libavcodec/utils.c

@@@ -118,6 -99,14 +118,19 @@@ fail2
      return 0;
  }
  
 -    if (pkt)
 -        return av_packet_copy_props(avci->last_pkt_props, pkt);
 -    return 0;
+ static int extract_packet_props(AVCodecInternal *avci, const AVPacket *pkt)
+ {
++    int ret = 0;
++
+     av_packet_unref(avci->last_pkt_props);
++    if (pkt) {
++        ret = av_packet_copy_props(avci->last_pkt_props, pkt);
++        if (!ret)
++            avci->last_pkt_props->size = pkt->size; // HACK: Needed for ff_init_buffer_info().
++    }
++    return ret;
+ }
  static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame)
  {
      int ret;
@@@ -390,11 -312,10 +403,13 @@@ int attribute_align_arg avcodec_decode_
          return AVERROR(ENOSYS);
      }
  
-     avctx->internal->pkt = avpkt;
 +    *got_picture_ptr = 0;
 +    if ((avctx->coded_width || avctx->coded_height) && av_image_check_size2(avctx->coded_width, avctx->coded_height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx))
 +        return AVERROR(EINVAL);
 +
 -
+     ret = extract_packet_props(avci, avpkt);
+     if (ret < 0)
+         return ret;
      ret = apply_param_change(avctx, avpkt);
      if (ret < 0)
          return ret;
  
      if ((avctx->codec->capabilities & AV_CODEC_CAP_DELAY) || avpkt->size ||
          (avctx->active_thread_type & FF_THREAD_FRAME)) {
-         avctx->internal->pkt = &tmp;
 +#if FF_API_MERGE_SD
 +FF_DISABLE_DEPRECATION_WARNINGS
 +        int did_split = av_packet_split_side_data(&tmp);
 +FF_ENABLE_DEPRECATION_WARNINGS
 +#endif
 +        ret = apply_param_change(avctx, &tmp);
 +        if (ret < 0)
 +            goto fail;
 +
++        ret = extract_packet_props(avci, &tmp);
++        if (ret < 0)
++            return ret;
          if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
              ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr,
 -                                         avpkt);
 +                                         &tmp);
          else {
              ret = avctx->codec->decode(avctx, picture, got_picture_ptr,
 -                                       avpkt);
 +                                       &tmp);
              if (!(avctx->codec->caps_internal & FF_CODEC_CAP_SETS_PKT_DTS))
                  picture->pkt_dts = avpkt->dts;
 +
 +            if(!avctx->has_b_frames){
 +                av_frame_set_pkt_pos(picture, avpkt->pos);
 +            }
 +            //FIXME these should be under if(!avctx->has_b_frames)
              /* get_buffer is supposed to set frame parameters */
              if (!(avctx->codec->capabilities & AV_CODEC_CAP_DR1)) {
 -                picture->sample_aspect_ratio = avctx->sample_aspect_ratio;
 -                picture->width               = avctx->width;
 -                picture->height              = avctx->height;
 -                picture->format              = avctx->pix_fmt;
 +                if (!picture->sample_aspect_ratio.num)    picture->sample_aspect_ratio = avctx->sample_aspect_ratio;
 +                if (!picture->width)                      picture->width               = avctx->width;
 +                if (!picture->height)                     picture->height              = avctx->height;
 +                if (picture->format == AV_PIX_FMT_NONE)   picture->format              = avctx->pix_fmt;
              }
          }
  
 +fail:
          emms_c(); //needed to avoid an emms_c() call before every return;
  
-         avctx->internal->pkt = NULL;
 +#if FF_API_MERGE_SD
 +        if (did_split) {
 +            av_packet_free_side_data(&tmp);
 +            if(ret == tmp.size)
 +                ret = avpkt->size;
 +        }
 +#endif
 +        if (picture->flags & AV_FRAME_FLAG_DISCARD) {
 +            *got_picture_ptr = 0;
 +        }
          if (*got_picture_ptr) {
              if (!avctx->refcounted_frames) {
                  int err = unrefcount_frame(avci, picture);
@@@ -507,139 -394,14 +523,140 @@@ int attribute_align_arg avcodec_decode_
  
      av_frame_unref(frame);
  
 -    if ((avctx->codec->capabilities & AV_CODEC_CAP_DELAY) || avpkt->size) {
 -        ret = avctx->codec->decode(avctx, frame, got_frame_ptr, avpkt);
 +    if ((avctx->codec->capabilities & AV_CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type & FF_THREAD_FRAME)) {
 +        uint8_t *side;
 +        int side_size;
 +        uint32_t discard_padding = 0;
 +        uint8_t skip_reason = 0;
 +        uint8_t discard_reason = 0;
 +        // copy to ensure we do not change avpkt
 +        AVPacket tmp = *avpkt;
 +#if FF_API_MERGE_SD
 +FF_DISABLE_DEPRECATION_WARNINGS
 +        int did_split = av_packet_split_side_data(&tmp);
 +FF_ENABLE_DEPRECATION_WARNINGS
 +#endif
 +        ret = apply_param_change(avctx, &tmp);
 +        if (ret < 0)
 +            goto fail;
 +
-         avctx->internal->pkt = &tmp;
++        ret = extract_packet_props(avci, &tmp);
++        if (ret < 0)
++            return ret;
 +        if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
 +            ret = ff_thread_decode_frame(avctx, frame, got_frame_ptr, &tmp);
 +        else {
 +            ret = avctx->codec->decode(avctx, frame, got_frame_ptr, &tmp);
 +            av_assert0(ret <= tmp.size);
 +            frame->pkt_dts = avpkt->dts;
 +        }
          if (ret >= 0 && *got_frame_ptr) {
              avctx->frame_number++;
 -            frame->pkt_dts = avpkt->dts;
 +            av_frame_set_best_effort_timestamp(frame,
 +                                               guess_correct_pts(avctx,
 +                                                                 frame->pts,
 +                                                                 frame->pkt_dts));
              if (frame->format == AV_SAMPLE_FMT_NONE)
                  frame->format = avctx->sample_fmt;
-         side= av_packet_get_side_data(avctx->internal->pkt, AV_PKT_DATA_SKIP_SAMPLES, &side_size);
 +            if (!frame->channel_layout)
 +                frame->channel_layout = avctx->channel_layout;
 +            if (!av_frame_get_channels(frame))
 +                av_frame_set_channels(frame, avctx->channels);
 +            if (!frame->sample_rate)
 +                frame->sample_rate = avctx->sample_rate;
 +        }
 +
-         avctx->internal->pkt = NULL;
++        side= av_packet_get_side_data(avci->last_pkt_props, AV_PKT_DATA_SKIP_SAMPLES, &side_size);
 +        if(side && side_size>=10) {
 +            avctx->internal->skip_samples = AV_RL32(side) * avctx->internal->skip_samples_multiplier;
 +            discard_padding = AV_RL32(side + 4);
 +            av_log(avctx, AV_LOG_DEBUG, "skip %d / discard %d samples due to side data\n",
 +                   avctx->internal->skip_samples, (int)discard_padding);
 +            skip_reason = AV_RL8(side + 8);
 +            discard_reason = AV_RL8(side + 9);
 +        }
 +
 +        if ((frame->flags & AV_FRAME_FLAG_DISCARD) && *got_frame_ptr &&
 +            !(avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) {
 +            avctx->internal->skip_samples = FFMAX(0, avctx->internal->skip_samples - frame->nb_samples);
 +            *got_frame_ptr = 0;
 +        }
 +
 +        if (avctx->internal->skip_samples > 0 && *got_frame_ptr &&
 +            !(avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) {
 +            if(frame->nb_samples <= avctx->internal->skip_samples){
 +                *got_frame_ptr = 0;
 +                avctx->internal->skip_samples -= frame->nb_samples;
 +                av_log(avctx, AV_LOG_DEBUG, "skip whole frame, skip left: %d\n",
 +                       avctx->internal->skip_samples);
 +            } else {
 +                av_samples_copy(frame->extended_data, frame->extended_data, 0, avctx->internal->skip_samples,
 +                                frame->nb_samples - avctx->internal->skip_samples, avctx->channels, frame->format);
 +                if(avctx->pkt_timebase.num && avctx->sample_rate) {
 +                    int64_t diff_ts = av_rescale_q(avctx->internal->skip_samples,
 +                                                   (AVRational){1, avctx->sample_rate},
 +                                                   avctx->pkt_timebase);
 +                    if(frame->pts!=AV_NOPTS_VALUE)
 +                        frame->pts += diff_ts;
 +#if FF_API_PKT_PTS
 +FF_DISABLE_DEPRECATION_WARNINGS
 +                    if(frame->pkt_pts!=AV_NOPTS_VALUE)
 +                        frame->pkt_pts += diff_ts;
 +FF_ENABLE_DEPRECATION_WARNINGS
 +#endif
 +                    if(frame->pkt_dts!=AV_NOPTS_VALUE)
 +                        frame->pkt_dts += diff_ts;
 +                    if (av_frame_get_pkt_duration(frame) >= diff_ts)
 +                        av_frame_set_pkt_duration(frame, av_frame_get_pkt_duration(frame) - diff_ts);
 +                } else {
 +                    av_log(avctx, AV_LOG_WARNING, "Could not update timestamps for skipped samples.\n");
 +                }
 +                av_log(avctx, AV_LOG_DEBUG, "skip %d/%d samples\n",
 +                       avctx->internal->skip_samples, frame->nb_samples);
 +                frame->nb_samples -= avctx->internal->skip_samples;
 +                avctx->internal->skip_samples = 0;
 +            }
 +        }
 +
 +        if (discard_padding > 0 && discard_padding <= frame->nb_samples && *got_frame_ptr &&
 +            !(avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) {
 +            if (discard_padding == frame->nb_samples) {
 +                *got_frame_ptr = 0;
 +            } else {
 +                if(avctx->pkt_timebase.num && avctx->sample_rate) {
 +                    int64_t diff_ts = av_rescale_q(frame->nb_samples - discard_padding,
 +                                                   (AVRational){1, avctx->sample_rate},
 +                                                   avctx->pkt_timebase);
 +                    av_frame_set_pkt_duration(frame, diff_ts);
 +                } else {
 +                    av_log(avctx, AV_LOG_WARNING, "Could not update timestamps for discarded samples.\n");
 +                }
 +                av_log(avctx, AV_LOG_DEBUG, "discard %d/%d samples\n",
 +                       (int)discard_padding, frame->nb_samples);
 +                frame->nb_samples -= discard_padding;
 +            }
 +        }
 +
 +        if ((avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL) && *got_frame_ptr) {
 +            AVFrameSideData *fside = av_frame_new_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES, 10);
 +            if (fside) {
 +                AV_WL32(fside->data, avctx->internal->skip_samples);
 +                AV_WL32(fside->data + 4, discard_padding);
 +                AV_WL8(fside->data + 8, skip_reason);
 +                AV_WL8(fside->data + 9, discard_reason);
 +                avctx->internal->skip_samples = 0;
 +            }
 +        }
 +fail:
 +#if FF_API_MERGE_SD
 +        if (did_split) {
 +            av_packet_free_side_data(&tmp);
 +            if(ret == tmp.size)
 +                ret = avpkt->size;
 +        }
 +#endif
  
 +        if (ret >= 0 && *got_frame_ptr) {
              if (!avctx->refcounted_frames) {
                  int err = unrefcount_frame(avci, frame);
                  if (err < 0)
@@@ -821,112 -419,16 +838,113 @@@ int avcodec_decode_subtitle2(AVCodecCon
                               int *got_sub_ptr,
                               AVPacket *avpkt)
  {
 -    int ret;
 +    int i, ret = 0;
  
 -    ret = extract_packet_props(avctx->internal, avpkt);
 -    if (ret < 0)
 -        return ret;
 +    if (!avpkt->data && avpkt->size) {
 +        av_log(avctx, AV_LOG_ERROR, "invalid packet: NULL data, size != 0\n");
 +        return AVERROR(EINVAL);
 +    }
 +    if (!avctx->codec)
 +        return AVERROR(EINVAL);
 +    if (avctx->codec->type != AVMEDIA_TYPE_SUBTITLE) {
 +        av_log(avctx, AV_LOG_ERROR, "Invalid media type for subtitles\n");
 +        return AVERROR(EINVAL);
 +    }
  
      *got_sub_ptr = 0;
 -    ret = avctx->codec->decode(avctx, sub, got_sub_ptr, avpkt);
 -    if (*got_sub_ptr)
 -        avctx->frame_number++;
 +    get_subtitle_defaults(sub);
 +
 +    if ((avctx->codec->capabilities & AV_CODEC_CAP_DELAY) || avpkt->size) {
 +        AVPacket pkt_recoded;
 +        AVPacket tmp = *avpkt;
 +#if FF_API_MERGE_SD
 +FF_DISABLE_DEPRECATION_WARNINGS
 +        int did_split = av_packet_split_side_data(&tmp);
 +        //apply_param_change(avctx, &tmp);
 +
 +        if (did_split) {
 +            /* FFMIN() prevents overflow in case the packet wasn't allocated with
 +             * proper padding.
 +             * If the side data is smaller than the buffer padding size, the
 +             * remaining bytes should have already been filled with zeros by the
 +             * original packet allocation anyway. */
 +            memset(tmp.data + tmp.size, 0,
 +                   FFMIN(avpkt->size - tmp.size, AV_INPUT_BUFFER_PADDING_SIZE));
 +        }
 +FF_ENABLE_DEPRECATION_WARNINGS
 +#endif
 +
 +        pkt_recoded = tmp;
 +        ret = recode_subtitle(avctx, &pkt_recoded, &tmp);
 +        if (ret < 0) {
 +            *got_sub_ptr = 0;
 +        } else {
-             avctx->internal->pkt = &pkt_recoded;
++             ret = extract_packet_props(avctx->internal, &pkt_recoded);
++             if (ret < 0)
++                return ret;
 +
 +            if (avctx->pkt_timebase.num && avpkt->pts != AV_NOPTS_VALUE)
 +                sub->pts = av_rescale_q(avpkt->pts,
 +                                        avctx->pkt_timebase, AV_TIME_BASE_Q);
 +            ret = avctx->codec->decode(avctx, sub, got_sub_ptr, &pkt_recoded);
 +            av_assert1((ret >= 0) >= !!*got_sub_ptr &&
 +                       !!*got_sub_ptr >= !!sub->num_rects);
 +
 +#if FF_API_ASS_TIMING
 +            if (avctx->sub_text_format == FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS
 +                && *got_sub_ptr && sub->num_rects) {
 +                const AVRational tb = avctx->pkt_timebase.num ? avctx->pkt_timebase
 +                                                              : avctx->time_base;
 +                int err = convert_sub_to_old_ass_form(sub, avpkt, tb);
 +                if (err < 0)
 +                    ret = err;
 +            }
 +#endif
 +
 +            if (sub->num_rects && !sub->end_display_time && avpkt->duration &&
 +                avctx->pkt_timebase.num) {
 +                AVRational ms = { 1, 1000 };
 +                sub->end_display_time = av_rescale_q(avpkt->duration,
 +                                                     avctx->pkt_timebase, ms);
 +            }
 +
 +            if (avctx->codec_descriptor->props & AV_CODEC_PROP_BITMAP_SUB)
 +                sub->format = 0;
 +            else if (avctx->codec_descriptor->props & AV_CODEC_PROP_TEXT_SUB)
 +                sub->format = 1;
 +
 +            for (i = 0; i < sub->num_rects; i++) {
 +                if (sub->rects[i]->ass && !utf8_check(sub->rects[i]->ass)) {
 +                    av_log(avctx, AV_LOG_ERROR,
 +                           "Invalid UTF-8 in decoded subtitles text; "
 +                           "maybe missing -sub_charenc option\n");
 +                    avsubtitle_free(sub);
 +                    ret = AVERROR_INVALIDDATA;
 +                    break;
 +                }
 +            }
 +
 +            if (tmp.data != pkt_recoded.data) { // did we recode?
 +                /* prevent from destroying side data from original packet */
 +                pkt_recoded.side_data = NULL;
 +                pkt_recoded.side_data_elems = 0;
 +
 +                av_packet_unref(&pkt_recoded);
 +            }
-             avctx->internal->pkt = NULL;
 +        }
 +
 +#if FF_API_MERGE_SD
 +        if (did_split) {
 +            av_packet_free_side_data(&tmp);
 +            if(ret == tmp.size)
 +                ret = avpkt->size;
 +        }
 +#endif
 +
 +        if (*got_sub_ptr)
 +            avctx->frame_number++;
 +    }
 +
      return ret;
  }
  
@@@ -1278,93 -753,68 +1296,83 @@@ int avcodec_default_get_buffer2(AVCodec
      }
  }
  
 -int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame)
 +static int add_metadata_from_side_data(const AVPacket *avpkt, AVFrame *frame)
  {
 -    AVPacket *pkt = avctx->internal->last_pkt_props;
 +    int size;
 +    const uint8_t *side_metadata;
 +
 +    AVDictionary **frame_md = avpriv_frame_get_metadatap(frame);
 +
 +    side_metadata = av_packet_get_side_data(avpkt,
 +                                            AV_PKT_DATA_STRINGS_METADATA, &size);
 +    return av_packet_unpack_dictionary(side_metadata, size, frame_md);
 +}
 +
 +int ff_init_buffer_info(AVCodecContext *avctx, AVFrame *frame)
 +{
-     const AVPacket *pkt = avctx->internal->pkt;
++    const AVPacket *pkt = avctx->internal->last_pkt_props;
      int i;
 -    struct {
 +    static const struct {
          enum AVPacketSideDataType packet;
          enum AVFrameSideDataType frame;
      } sd[] = {
 -        { AV_PKT_DATA_REPLAYGAIN ,   AV_FRAME_DATA_REPLAYGAIN },
 -        { AV_PKT_DATA_DISPLAYMATRIX, AV_FRAME_DATA_DISPLAYMATRIX },
 -        { AV_PKT_DATA_SPHERICAL,     AV_FRAME_DATA_SPHERICAL },
 -        { AV_PKT_DATA_STEREO3D,      AV_FRAME_DATA_STEREO3D },
 -        { AV_PKT_DATA_AUDIO_SERVICE_TYPE, AV_FRAME_DATA_AUDIO_SERVICE_TYPE },
 +        { AV_PKT_DATA_REPLAYGAIN ,                AV_FRAME_DATA_REPLAYGAIN },
 +        { AV_PKT_DATA_DISPLAYMATRIX,              AV_FRAME_DATA_DISPLAYMATRIX },
 +        { AV_PKT_DATA_SPHERICAL,                  AV_FRAME_DATA_SPHERICAL },
 +        { AV_PKT_DATA_STEREO3D,                   AV_FRAME_DATA_STEREO3D },
 +        { AV_PKT_DATA_AUDIO_SERVICE_TYPE,         AV_FRAME_DATA_AUDIO_SERVICE_TYPE },
 +        { AV_PKT_DATA_MASTERING_DISPLAY_METADATA, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA },
 +        { AV_PKT_DATA_CONTENT_LIGHT_LEVEL,        AV_FRAME_DATA_CONTENT_LIGHT_LEVEL },
      };
  
 -    frame->color_primaries = avctx->color_primaries;
 -    frame->color_trc       = avctx->color_trc;
 -    frame->colorspace      = avctx->colorspace;
 -    frame->color_range     = avctx->color_range;
 -    frame->chroma_location = avctx->chroma_sample_location;
 -
 -    frame->reordered_opaque = avctx->reordered_opaque;
 -
 +    if (pkt) {
 +        frame->pts = pkt->pts;
  #if FF_API_PKT_PTS
  FF_DISABLE_DEPRECATION_WARNINGS
 -    frame->pkt_pts = pkt->pts;
 +        frame->pkt_pts = pkt->pts;
  FF_ENABLE_DEPRECATION_WARNINGS
  #endif
 -    frame->pts     = pkt->pts;
 -
 -    for (i = 0; i < FF_ARRAY_ELEMS(sd); i++) {
 -        int size;
 -        uint8_t *packet_sd = av_packet_get_side_data(pkt, sd[i].packet, &size);
 -        if (packet_sd) {
 -            AVFrameSideData *frame_sd = av_frame_new_side_data(frame,
 -                                                               sd[i].frame,
 -                                                               size);
 -            if (!frame_sd)
 -                return AVERROR(ENOMEM);
 +        av_frame_set_pkt_pos     (frame, pkt->pos);
 +        av_frame_set_pkt_duration(frame, pkt->duration);
 +        av_frame_set_pkt_size    (frame, pkt->size);
 +
 +        for (i = 0; i < FF_ARRAY_ELEMS(sd); i++) {
 +            int size;
 +            uint8_t *packet_sd = av_packet_get_side_data(pkt, sd[i].packet, &size);
 +            if (packet_sd) {
 +                AVFrameSideData *frame_sd = av_frame_new_side_data(frame,
 +                                                                   sd[i].frame,
 +                                                                   size);
 +                if (!frame_sd)
 +                    return AVERROR(ENOMEM);
 +
 +                memcpy(frame_sd->data, packet_sd, size);
 +            }
 +        }
 +        add_metadata_from_side_data(pkt, frame);
  
 -            memcpy(frame_sd->data, packet_sd, size);
 +        if (pkt->flags & AV_PKT_FLAG_DISCARD) {
 +            frame->flags |= AV_FRAME_FLAG_DISCARD;
 +        } else {
 +            frame->flags = (frame->flags & ~AV_FRAME_FLAG_DISCARD);
          }
-     } else {
-         frame->pts = AV_NOPTS_VALUE;
- #if FF_API_PKT_PTS
- FF_DISABLE_DEPRECATION_WARNINGS
-         frame->pkt_pts = AV_NOPTS_VALUE;
- FF_ENABLE_DEPRECATION_WARNINGS
- #endif
-         av_frame_set_pkt_pos     (frame, -1);
-         av_frame_set_pkt_duration(frame, 0);
-         av_frame_set_pkt_size    (frame, -1);
      }
 +    frame->reordered_opaque = avctx->reordered_opaque;
  
 -    return 0;
 -}
 -
 -int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
 -{
 -    const AVHWAccel *hwaccel = avctx->hwaccel;
 -    int override_dimensions = 1;
 -    int ret;
 -
 -    switch (avctx->codec_type) {
 +    if (frame->color_primaries == AVCOL_PRI_UNSPECIFIED)
 +        frame->color_primaries = avctx->color_primaries;
 +    if (frame->color_trc == AVCOL_TRC_UNSPECIFIED)
 +        frame->color_trc = avctx->color_trc;
 +    if (av_frame_get_colorspace(frame) == AVCOL_SPC_UNSPECIFIED)
 +        av_frame_set_colorspace(frame, avctx->colorspace);
 +    if (av_frame_get_color_range(frame) == AVCOL_RANGE_UNSPECIFIED)
 +        av_frame_set_color_range(frame, avctx->color_range);
 +    if (frame->chroma_location == AVCHROMA_LOC_UNSPECIFIED)
 +        frame->chroma_location = avctx->chroma_sample_location;
 +
 +    switch (avctx->codec->type) {
      case AVMEDIA_TYPE_VIDEO:
 -        if (frame->width <= 0 || frame->height <= 0) {
 -            frame->width  = FFMAX(avctx->width, avctx->coded_width);
 -            frame->height = FFMAX(avctx->height, avctx->coded_height);
 -            override_dimensions = 0;
 -        }
 -        if (frame->format < 0)
 -            frame->format              = avctx->pix_fmt;
 +        frame->format              = avctx->pix_fmt;
          if (!frame->sample_aspect_ratio.num)
              frame->sample_aspect_ratio = avctx->sample_aspect_ratio;
  
@@@ -138,25 -131,12 +138,25 @@@ typedef struct AVCodecInternal 
      void *thread_ctx;
  
      /**
-      * Current packet as passed into the decoder, to avoid having to pass the
-      * packet into every function.
+      * Properties (timestamps+side data) extracted from the last packet passed
+      * for decoding.
       */
-     const AVPacket *pkt;
+     AVPacket *last_pkt_props;
  
      /**
 +     * temporary buffer used for encoders to store their bitstream
 +     */
 +    uint8_t *byte_buffer;
 +    unsigned int byte_buffer_size;
 +
 +    void *frame_thread_encoder;
 +
 +    /**
 +     * Number of audio samples to skip at the start of the next decoded frame
 +     */
 +    int skip_samples;
 +
 +    /**
       * hwaccel-specific private data
       */
      void *hwaccel_priv_data;
Simple merge
@@@ -237,19 -156,12 +237,19 @@@ static int raw_decode(AVCodecContext *a
      if (res < 0)
          return res;
  
-     av_frame_set_pkt_pos     (frame, avctx->internal->pkt->pos);
-     av_frame_set_pkt_duration(frame, avctx->internal->pkt->duration);
 -    if (buf_size < context->frame_size - (avctx->pix_fmt == AV_PIX_FMT_PAL8 ?
 -                                          AVPALETTE_SIZE : 0))
 -        return -1;
++    av_frame_set_pkt_pos     (frame, avctx->internal->last_pkt_props->pos);
++    av_frame_set_pkt_duration(frame, avctx->internal->last_pkt_props->duration);
 +
 +    if (context->tff >= 0) {
 +        frame->interlaced_frame = 1;
 +        frame->top_field_first  = context->tff;
 +    }
 +
 +    if ((res = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
 +        return res;
  
      if (need_copy)
 -        frame->buf[0] = av_buffer_alloc(context->frame_size);
 +        frame->buf[0] = av_buffer_alloc(FFMAX(context->frame_size, buf_size));
      else
          frame->buf[0] = av_buffer_ref(avpkt->buf);
      if (!frame->buf[0])
@@@ -684,8 -433,12 +684,14 @@@ int attribute_align_arg avcodec_open2(A
          goto free_and_end;
      }
  
+     avctx->internal->last_pkt_props = av_packet_alloc();
+     if (!avctx->internal->last_pkt_props) {
+         ret = AVERROR(ENOMEM);
+         goto free_and_end;
+     }
 +    avctx->internal->skip_samples_multiplier = 1;
 +
      if (codec->priv_data_size > 0) {
          if (!avctx->priv_data) {
              avctx->priv_data = av_mallocz(codec->priv_data_size);