Merge commit 'a0f2946068c62e18cb05ac25c0df3d86077251a6'
authorMichael Niedermayer <michaelni@gmx.at>
Wed, 29 Apr 2015 13:44:21 +0000 (15:44 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Wed, 29 Apr 2015 14:35:24 +0000 (16:35 +0200)
* commit 'a0f2946068c62e18cb05ac25c0df3d86077251a6':
  h264: use properly allocated AVFrames

Conflicts:
libavcodec/h264.c
libavcodec/h264.h
libavcodec/h264_refs.c
libavcodec/h264_slice.c
libavcodec/svq3.c
libavcodec/vda_h264.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
12 files changed:
1  2 
libavcodec/dxva2_h264.c
libavcodec/h264.c
libavcodec/h264.h
libavcodec/h264_mb_template.c
libavcodec/h264_picture.c
libavcodec/h264_refs.c
libavcodec/h264_slice.c
libavcodec/svq3.c
libavcodec/vaapi_h264.c
libavcodec/vda_h264.c
libavcodec/vdpau.c
libavcodec/vdpau_h264.c

Simple merge
@@@ -621,10 -590,16 +621,20 @@@ static int h264_init_context(AVCodecCon
          return AVERROR(ENOMEM);
      }
  
-     for (i = 0; i < H264_MAX_PICTURE_COUNT; i++)
-         av_frame_unref(&h->DPB[i].f);
-     av_frame_unref(&h->cur_pic.f);
+     for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) {
+         h->DPB[i].f = av_frame_alloc();
+         if (!h->DPB[i].f)
+             return AVERROR(ENOMEM);
+     }
+     h->cur_pic.f = av_frame_alloc();
+     if (!h->cur_pic.f)
+         return AVERROR(ENOMEM);
++    h->last_pic_for_ec.f = av_frame_alloc();
++    if (!h->last_pic_for_ec.f)
++        return AVERROR(ENOMEM);
 +
      for (i = 0; i < h->nb_slice_ctx; i++)
          h->slice_ctx[i].h264 = h;
  
@@@ -720,8 -686,9 +730,8 @@@ static void decode_postinit(H264Contex
      H264Picture *out = h->cur_pic_ptr;
      H264Picture *cur = h->cur_pic_ptr;
      int i, pics, out_of_order, out_idx;
 -    int invalid = 0, cnt = 0;
  
-     h->cur_pic_ptr->f.pict_type = h->pict_type;
+     h->cur_pic_ptr->f->pict_type = h->pict_type;
  
      if (h->next_output_pic)
          return;
           * yet, so we assume the worst for now. */
          // if (setup_finished)
          //    ff_thread_finish_setup(h->avctx);
 -        return;
 +        if (cur->field_poc[0] == INT_MAX && cur->field_poc[1] == INT_MAX)
 +            return;
 +        if (h->avctx->hwaccel || h->missing_fields <=1)
 +            return;
      }
  
-     cur->f.interlaced_frame = 0;
-     cur->f.repeat_pict      = 0;
+     cur->f->interlaced_frame = 0;
+     cur->f->repeat_pict      = 0;
  
      /* Signal interlacing information externally. */
      /* Prioritize picture timing SEI information over used
          h->frame_packing_arrangement_type <= 6 &&
          h->content_interpretation_type > 0 &&
          h->content_interpretation_type < 3) {
-         AVStereo3D *stereo = av_stereo3d_create_side_data(&cur->f);
+         AVStereo3D *stereo = av_stereo3d_create_side_data(cur->f);
 -        if (!stereo)
 -            return;
 -
 +        if (stereo) {
          switch (h->frame_packing_arrangement_type) {
          case 0:
              stereo->type = AV_STEREO3D_CHECKERBOARD;
      if (h->sei_display_orientation_present &&
          (h->sei_anticlockwise_rotation || h->sei_hflip || h->sei_vflip)) {
          double angle = h->sei_anticlockwise_rotation * 360 / (double) (1 << 16);
-         AVFrameSideData *rotation = av_frame_new_side_data(&cur->f,
+         AVFrameSideData *rotation = av_frame_new_side_data(cur->f,
                                                             AV_FRAME_DATA_DISPLAYMATRIX,
                                                             sizeof(int32_t) * 9);
 -        if (!rotation)
 -            return;
 -
 -        av_display_rotation_set((int32_t *)rotation->data, angle);
 -        av_display_matrix_flip((int32_t *)rotation->data,
 -                               h->sei_hflip, h->sei_vflip);
 +        if (rotation) {
 +            av_display_rotation_set((int32_t *)rotation->data, angle);
 +            av_display_matrix_flip((int32_t *)rotation->data,
 +                                   h->sei_hflip, h->sei_vflip);
 +        }
      }
  
 +    cur->mmco_reset = h->mmco_reset;
 +    h->mmco_reset = 0;
 +
      // FIXME do something with unavailable reference frames
  
      /* Sort B-frames into display order */
          h->low_delay           = 0;
      }
  
-     if(   cur->f.pict_type == AV_PICTURE_TYPE_B
 +    for (i = 0; 1; i++) {
 +        if(i == MAX_DELAYED_PIC_COUNT || cur->poc < h->last_pocs[i]){
 +            if(i)
 +                h->last_pocs[i-1] = cur->poc;
 +            break;
 +        } else if(i) {
 +            h->last_pocs[i-1]= h->last_pocs[i];
 +        }
 +    }
 +    out_of_order = MAX_DELAYED_PIC_COUNT - i;
++    if(   cur->f->pict_type == AV_PICTURE_TYPE_B
 +       || (h->last_pocs[MAX_DELAYED_PIC_COUNT-2] > INT_MIN && h->last_pocs[MAX_DELAYED_PIC_COUNT-1] - h->last_pocs[MAX_DELAYED_PIC_COUNT-2] > 2))
 +        out_of_order = FFMAX(out_of_order, 1);
 +    if (out_of_order == MAX_DELAYED_PIC_COUNT) {
 +        av_log(h->avctx, AV_LOG_VERBOSE, "Invalid POC %d<%d\n", cur->poc, h->last_pocs[0]);
 +        for (i = 1; i < MAX_DELAYED_PIC_COUNT; i++)
 +            h->last_pocs[i] = INT_MIN;
 +        h->last_pocs[0] = cur->poc;
 +        cur->mmco_reset = 1;
 +    } else if(h->avctx->has_b_frames < out_of_order && !h->sps.bitstream_restriction_flag){
 +        av_log(h->avctx, AV_LOG_VERBOSE, "Increasing reorder buffer to %d\n", out_of_order);
 +        h->avctx->has_b_frames = out_of_order;
 +        h->low_delay = 0;
 +    }
 +
      pics = 0;
      while (h->delayed_pic[pics])
          pics++;
      if (cur->reference == 0)
          cur->reference = DELAYED_PIC_REF;
  
 -    /* Frame reordering. This code takes pictures from coding order and sorts
 -     * them by their incremental POC value into display order. It supports POC
 -     * gaps, MMCO reset codes and random resets.
 -     * A "display group" can start either with a IDR frame (f.key_frame = 1),
 -     * and/or can be closed down with a MMCO reset code. In sequences where
 -     * there is no delay, we can't detect that (since the frame was already
 -     * output to the user), so we also set h->mmco_reset to detect the MMCO
 -     * reset code.
 -     * FIXME: if we detect insufficient delays (as per h->avctx->has_b_frames),
 -     * we increase the delay between input and output. All frames affected by
 -     * the lag (e.g. those that should have been output before another frame
 -     * that we already returned to the user) will be dropped. This is a bug
 -     * that we will fix later. */
 -    for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) {
 -        cnt     += out->poc < h->last_pocs[i];
 -        invalid += out->poc == INT_MIN;
 -    }
 -    if (!h->mmco_reset && !cur->f->key_frame &&
 -        cnt + invalid == MAX_DELAYED_PIC_COUNT && cnt > 0) {
 -        h->mmco_reset = 2;
 -        if (pics > 1)
 -            h->delayed_pic[pics - 2]->mmco_reset = 2;
 -    }
 -    if (h->mmco_reset || cur->f->key_frame) {
 -        for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++)
 -            h->last_pocs[i] = INT_MIN;
 -        cnt     = 0;
 -        invalid = MAX_DELAYED_PIC_COUNT;
 -    }
      out     = h->delayed_pic[0];
      out_idx = 0;
 -    for (i = 1; i < MAX_DELAYED_PIC_COUNT &&
 -                h->delayed_pic[i] &&
 -                !h->delayed_pic[i - 1]->mmco_reset &&
 -                !h->delayed_pic[i]->f->key_frame;
 +    for (i = 1; h->delayed_pic[i] &&
-                 !h->delayed_pic[i]->f.key_frame &&
++                !h->delayed_pic[i]->f->key_frame &&
 +                !h->delayed_pic[i]->mmco_reset;
           i++)
          if (h->delayed_pic[i]->poc < out->poc) {
              out     = h->delayed_pic[i];
              out_idx = i;
          }
      if (h->avctx->has_b_frames == 0 &&
-         (h->delayed_pic[0]->f.key_frame || h->delayed_pic[0]->mmco_reset))
 -        (h->delayed_pic[0]->f->key_frame || h->mmco_reset))
++        (h->delayed_pic[0]->f->key_frame || h->delayed_pic[0]->mmco_reset))
          h->next_outputed_poc = INT_MIN;
 -    out_of_order = !out->f->key_frame && !h->mmco_reset &&
 -                   (out->poc < h->next_outputed_poc);
 +    out_of_order = out->poc < h->next_outputed_poc;
  
 -    if (h->sps.bitstream_restriction_flag &&
 -        h->avctx->has_b_frames >= h->sps.num_reorder_frames) {
 -    } else if (out_of_order && pics - 1 == h->avctx->has_b_frames &&
 -               h->avctx->has_b_frames < MAX_DELAYED_PIC_COUNT) {
 -        if (invalid + cnt < MAX_DELAYED_PIC_COUNT) {
 -            h->avctx->has_b_frames = FFMAX(h->avctx->has_b_frames, cnt);
 -        }
 -        h->low_delay = 0;
 -    } else if (h->low_delay &&
 -               ((h->next_outputed_poc != INT_MIN &&
 -                 out->poc > h->next_outputed_poc + 2) ||
 -                cur->f->pict_type == AV_PICTURE_TYPE_B)) {
 -        h->low_delay = 0;
 -        h->avctx->has_b_frames++;
 -    }
 -
 -    if (pics > h->avctx->has_b_frames) {
 +    if (out_of_order || pics > h->avctx->has_b_frames) {
          out->reference &= ~DELAYED_PIC_REF;
          // for frame threading, the owner must be the second field's thread or
          // else the first thread can release the picture and reuse it unsafely
          for (i = out_idx; h->delayed_pic[i]; i++)
              h->delayed_pic[i] = h->delayed_pic[i + 1];
      }
 -    memmove(h->last_pocs, &h->last_pocs[1],
 -            sizeof(*h->last_pocs) * (MAX_DELAYED_PIC_COUNT - 1));
 -    h->last_pocs[MAX_DELAYED_PIC_COUNT - 1] = cur->poc;
      if (!out_of_order && pics > h->avctx->has_b_frames) {
          h->next_output_pic = out;
-         if (out_idx == 0 && h->delayed_pic[0] && (h->delayed_pic[0]->f.key_frame || h->delayed_pic[0]->mmco_reset)) {
 -        if (out->mmco_reset) {
 -            if (out_idx > 0) {
 -                h->next_outputed_poc                    = out->poc;
 -                h->delayed_pic[out_idx - 1]->mmco_reset = out->mmco_reset;
 -            } else {
 -                h->next_outputed_poc = INT_MIN;
 -            }
 -        } else {
 -            if (out_idx == 0 && pics > 1 && h->delayed_pic[0]->f->key_frame) {
 -                h->next_outputed_poc = INT_MIN;
 -            } else {
 -                h->next_outputed_poc = out->poc;
 -            }
 -        }
 -        h->mmco_reset = 0;
++        if (out_idx == 0 && h->delayed_pic[0] && (h->delayed_pic[0]->f->key_frame || h->delayed_pic[0]->mmco_reset)) {
 +            h->next_outputed_poc = INT_MIN;
 +        } else
 +            h->next_outputed_poc = out->poc;
      } else {
 -        av_log(h->avctx, AV_LOG_DEBUG, "no picture\n");
 +        av_log(h->avctx, AV_LOG_DEBUG, "no picture %s\n", out_of_order ? "ooo" : "");
      }
  
      if (h->next_output_pic) {
@@@ -1483,21 -1446,14 +1493,21 @@@ again
                  if ((err = ff_h264_decode_slice_header(h, sl)))
                      break;
  
 -                if (h->sei_recovery_frame_cnt >= 0 && h->recovery_frame < 0) {
 -                    h->recovery_frame = (h->frame_num + h->sei_recovery_frame_cnt) &
 -                                        ((1 << h->sps.log2_max_frame_num) - 1);
 +                if (h->sei_recovery_frame_cnt >= 0) {
 +                    if (h->frame_num != h->sei_recovery_frame_cnt || sl->slice_type_nos != AV_PICTURE_TYPE_I)
 +                        h->valid_recovery_point = 1;
 +
 +                    if (   h->recovery_frame < 0
 +                        || av_mod_uintp2(h->recovery_frame - h->frame_num, h->sps.log2_max_frame_num) > h->sei_recovery_frame_cnt) {
 +                        h->recovery_frame = av_mod_uintp2(h->frame_num + h->sei_recovery_frame_cnt, h->sps.log2_max_frame_num);
 +
 +                        if (!h->valid_recovery_point)
 +                            h->recovery_frame = h->frame_num;
 +                    }
                  }
  
-                 h->cur_pic_ptr->f.key_frame |=
+                 h->cur_pic_ptr->f->key_frame |=
 -                    (h->nal_unit_type == NAL_IDR_SLICE) ||
 -                    (h->sei_recovery_frame_cnt >= 0);
 +                    (h->nal_unit_type == NAL_IDR_SLICE);
  
                  if (h->nal_unit_type == NAL_IDR_SLICE ||
                      h->recovery_frame == h->frame_num) {
                                                             &buf[buf_index - consumed],
                                                             consumed);
                          if (ret < 0)
 -                            return ret;
 +                            goto end;
 +                    } else if (CONFIG_H264_VDPAU_DECODER &&
 +                               h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) {
-                         ff_vdpau_add_data_chunk(h->cur_pic_ptr->f.data[0],
++                        ff_vdpau_add_data_chunk(h->cur_pic_ptr->f->data[0],
 +                                                start_code,
 +                                                sizeof(start_code));
-                         ff_vdpau_add_data_chunk(h->cur_pic_ptr->f.data[0],
++                        ff_vdpau_add_data_chunk(h->cur_pic_ptr->f->data[0],
 +                                                &buf[buf_index - consumed],
 +                                                consumed);
                      } else
                          context_count++;
                  }
@@@ -1656,10 -1587,8 +1666,10 @@@ static int get_consumed_bytes(int pos, 
      return pos;
  }
  
 -static int output_frame(H264Context *h, AVFrame *dst, AVFrame *src)
 +static int output_frame(H264Context *h, AVFrame *dst, H264Picture *srcp)
  {
-     AVFrame *src = &srcp->f;
++    AVFrame *src = srcp->f;
 +    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(src->format);
      int i;
      int ret = av_frame_ref(dst, src);
      if (ret < 0)
@@@ -1788,37 -1676,13 +1798,37 @@@ static int h264_decode_frame(AVCodecCon
  
          ff_h264_field_end(h, &h->slice_ctx[0], 0);
  
 +        /* Wait for second field. */
          *got_frame = 0;
 -        if (h->next_output_pic && ((avctx->flags & CODEC_FLAG_OUTPUT_CORRUPT) ||
 +        if (h->next_output_pic && (
                                     h->next_output_pic->recovered)) {
              if (!h->next_output_pic->recovered)
-                 h->next_output_pic->f.flags |= AV_FRAME_FLAG_CORRUPT;
+                 h->next_output_pic->f->flags |= AV_FRAME_FLAG_CORRUPT;
  
 -            ret = output_frame(h, pict, h->next_output_pic->f);
 +            if (!h->avctx->hwaccel &&
 +                 (h->next_output_pic->field_poc[0] == INT_MAX ||
 +                  h->next_output_pic->field_poc[1] == INT_MAX)
 +            ) {
 +                int p;
-                 AVFrame *f = &h->next_output_pic->f;
++                AVFrame *f = h->next_output_pic->f;
 +                int field = h->next_output_pic->field_poc[0] == INT_MAX;
 +                uint8_t *dst_data[4];
 +                int linesizes[4];
 +                const uint8_t *src_data[4];
 +
 +                av_log(h->avctx, AV_LOG_DEBUG, "Duplicating field %d to fill missing\n", field);
 +
 +                for (p = 0; p<4; p++) {
 +                    dst_data[p] = f->data[p] + (field^1)*f->linesize[p];
 +                    src_data[p] = f->data[p] +  field   *f->linesize[p];
 +                    linesizes[p] = 2*f->linesize[p];
 +                }
 +
 +                av_image_copy(dst_data, linesizes, src_data, linesizes,
 +                              f->format, f->width, f->height>>1);
 +            }
 +
 +            ret = output_frame(h, pict, h->next_output_pic);
              if (ret < 0)
                  return ret;
              *got_frame = 1;
@@@ -1846,9 -1700,10 +1856,11 @@@ av_cold void ff_h264_free_context(H264C
  
      ff_h264_free_tables(h);
  
-     for (i = 0; i < H264_MAX_PICTURE_COUNT; i++)
+     for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) {
          ff_h264_unref_picture(h, &h->DPB[i]);
+         av_frame_free(&h->DPB[i].f);
+     }
 +    memset(h->delayed_pic, 0, sizeof(h->delayed_pic));
  
      h->cur_pic_ptr = NULL;
  
@@@ -1872,7 -1726,7 +1884,9 @@@ static av_cold int h264_decode_end(AVCo
      ff_h264_free_context(h);
  
      ff_h264_unref_picture(h, &h->cur_pic);
+     av_frame_free(&h->cur_pic.f);
 +    ff_h264_unref_picture(h, &h->last_pic_for_ec);
++    av_frame_free(&h->last_pic_for_ec.f);
  
      return 0;
  }
Simple merge
Simple merge
@@@ -195,30 -182,13 +195,30 @@@ int ff_h264_field_end(H264Context *h, H
       * past end by one (callers fault) and resync_mb_y != 0
       * causes problems for the first MB line, too.
       */
 -    if (!FIELD_PICTURE(h) && h->enable_er) {
 -        h264_set_erpic(&sl->er.cur_pic, h->cur_pic_ptr);
 -        h264_set_erpic(&sl->er.last_pic,
 -                       sl->ref_count[0] ? sl->ref_list[0][0].parent : NULL);
 -        h264_set_erpic(&sl->er.next_pic,
 -                       sl->ref_count[1] ? sl->ref_list[1][0].parent : NULL);
 +    if (!FIELD_PICTURE(h) && h->current_slice && !h->sps.new && h->enable_er) {
-         int use_last_pic = h->last_pic_for_ec.f.buf[0] && !sl->ref_count[0];
++        int use_last_pic = h->last_pic_for_ec.f->buf[0] && !sl->ref_count[0];
 +
 +        ff_h264_set_erpic(&sl->er.cur_pic, h->cur_pic_ptr);
 +
 +        if (use_last_pic) {
 +            ff_h264_set_erpic(&sl->er.last_pic, &h->last_pic_for_ec);
 +            sl->ref_list[0][0].parent = &h->last_pic_for_ec;
-             memcpy(sl->ref_list[0][0].data, h->last_pic_for_ec.f.data, sizeof(sl->ref_list[0][0].data));
-             memcpy(sl->ref_list[0][0].linesize, h->last_pic_for_ec.f.linesize, sizeof(sl->ref_list[0][0].linesize));
++            memcpy(sl->ref_list[0][0].data, h->last_pic_for_ec.f->data, sizeof(sl->ref_list[0][0].data));
++            memcpy(sl->ref_list[0][0].linesize, h->last_pic_for_ec.f->linesize, sizeof(sl->ref_list[0][0].linesize));
 +            sl->ref_list[0][0].reference = h->last_pic_for_ec.reference;
 +        } else if (sl->ref_count[0]) {
 +            ff_h264_set_erpic(&sl->er.last_pic, sl->ref_list[0][0].parent);
 +        } else
 +            ff_h264_set_erpic(&sl->er.last_pic, NULL);
 +
 +        if (sl->ref_count[1])
 +            ff_h264_set_erpic(&sl->er.next_pic, sl->ref_list[1][0].parent);
 +
 +        sl->er.ref_count = sl->ref_count[0];
 +
          ff_er_frame_end(&sl->er);
 +        if (use_last_pic)
 +            memset(&sl->ref_list[0][0], 0, sizeof(sl->ref_list[0][0]));
      }
  #endif /* CONFIG_ERROR_RESILIENCE */
  
@@@ -175,16 -170,16 +175,16 @@@ int ff_h264_fill_default_ref_list(H264C
  #ifdef TRACE
      for (i = 0; i < sl->ref_count[0]; i++) {
          ff_tlog(h->avctx, "List0: %s fn:%d 0x%p\n",
 -                (h->default_ref_list[0][i].long_ref ? "LT" : "ST"),
 +                h->default_ref_list[0][i].parent ? (h->default_ref_list[0][i].parent->long_ref ? "LT" : "ST") : "NULL",
                  h->default_ref_list[0][i].pic_id,
-                 h->default_ref_list[0][i].parent ? h->default_ref_list[0][i].parent->f.data[0] : 0);
 -                h->default_ref_list[0][i].f->data[0]);
++                h->default_ref_list[0][i].parent ? h->default_ref_list[0][i].parent->f->data[0] : 0);
      }
      if (sl->slice_type_nos == AV_PICTURE_TYPE_B) {
          for (i = 0; i < sl->ref_count[1]; i++) {
              ff_tlog(h->avctx, "List1: %s fn:%d 0x%p\n",
 -                    (h->default_ref_list[1][i].long_ref ? "LT" : "ST"),
 +                    h->default_ref_list[1][i].parent ? (h->default_ref_list[1][i].parent->long_ref ? "LT" : "ST") : "NULL",
                      h->default_ref_list[1][i].pic_id,
-                     h->default_ref_list[1][i].parent ? h->default_ref_list[1][i].parent->f.data[0] : 0);
 -                    h->default_ref_list[1][i].f->data[0]);
++                    h->default_ref_list[1][i].parent ? h->default_ref_list[1][i].parent->f->data[0] : 0);
          }
      }
  #endif
@@@ -341,7 -331,6 +341,7 @@@ int ff_h264_decode_ref_pic_list_reorder
                  else
                      return -1;
              }
-             av_assert0(av_buffer_get_ref_count(sl->ref_list[list][index].parent->f.buf[0]) > 0);
++            av_assert0(av_buffer_get_ref_count(sl->ref_list[list][index].parent->f->buf[0]) > 0);
          }
      }
  
@@@ -497,11 -486,6 +497,11 @@@ void ff_h264_remove_all_refs(H264Contex
      }
      assert(h->long_ref_count == 0);
  
-     if (h->short_ref_count && !h->last_pic_for_ec.f.data[0]) {
++    if (h->short_ref_count && !h->last_pic_for_ec.f->data[0]) {
 +        ff_h264_unref_picture(h, &h->last_pic_for_ec);
 +        ff_h264_ref_picture(h, &h->last_pic_for_ec, h->short_ref[0]);
 +    }
 +
      for (i = 0; i < h->short_ref_count; i++) {
          unreference_pic(h, h->short_ref[i], 0);
          h->short_ref[i] = NULL;
@@@ -769,32 -732,8 +769,32 @@@ int ff_h264_execute_ref_pic_marking(H26
          }
      }
  
 +    for (i = 0; i<h->short_ref_count; i++) {
 +        pic = h->short_ref[i];
 +        if (pic->invalid_gap) {
 +            int d = av_mod_uintp2(h->cur_pic_ptr->frame_num - pic->frame_num, h->sps.log2_max_frame_num);
 +            if (d > h->sps.ref_frame_count)
 +                remove_short(h, pic->frame_num, 0);
 +        }
 +    }
 +
      print_short_term(h);
      print_long_term(h);
-         && h->cur_pic_ptr->f.pict_type == AV_PICTURE_TYPE_I){
 +
 +    pps_count = 0;
 +    for (i = 0; i < FF_ARRAY_ELEMS(h->pps_buffers); i++)
 +        pps_count += !!h->pps_buffers[i];
 +
 +    if (   err >= 0
 +        && h->long_ref_count==0
 +        && (h->short_ref_count<=2 || h->pps.ref_count[0] <= 1 && h->pps.ref_count[1] <= 1 && pps_count == 1)
 +        && h->pps.ref_count[0]<=2 + (h->picture_structure != PICT_FRAME) + (2*!h->has_recovery_point)
++        && h->cur_pic_ptr->f->pict_type == AV_PICTURE_TYPE_I){
 +        h->cur_pic_ptr->recovered |= 1;
 +        if(!h->avctx->has_b_frames)
 +            h->frame_recovered |= FRAME_RECOVERED_SEI;
 +    }
 +
      return (h->avctx->err_recognition & AV_EF_EXPLODE) ? err : 0;
  }
  
@@@ -246,18 -238,6 +246,18 @@@ static int alloc_picture(H264Context *h
              pic->hwaccel_picture_private = pic->hwaccel_priv_buf->data;
          }
      }
-     if (CONFIG_GRAY && !h->avctx->hwaccel && h->flags & CODEC_FLAG_GRAY && pic->f.data[2]) {
++    if (CONFIG_GRAY && !h->avctx->hwaccel && h->flags & CODEC_FLAG_GRAY && pic->f->data[2]) {
 +        int h_chroma_shift, v_chroma_shift;
-         av_pix_fmt_get_chroma_sub_sample(pic->f.format,
++        av_pix_fmt_get_chroma_sub_sample(pic->f->format,
 +                                         &h_chroma_shift, &v_chroma_shift);
 +
 +        for(i=0; i<FF_CEIL_RSHIFT(h->avctx->height, v_chroma_shift); i++) {
-             memset(pic->f.data[1] + pic->f.linesize[1]*i,
++            memset(pic->f->data[1] + pic->f->linesize[1]*i,
 +                   0x80, FF_CEIL_RSHIFT(h->avctx->width, h_chroma_shift));
-             memset(pic->f.data[2] + pic->f.linesize[2]*i,
++            memset(pic->f->data[2] + pic->f->linesize[2]*i,
 +                   0x80, FF_CEIL_RSHIFT(h->avctx->width, h_chroma_shift));
 +        }
 +    }
  
      if (!h->qscale_table_pool) {
          ret = init_table_pools(h);
@@@ -594,25 -556,19 +594,25 @@@ static int h264_frame_start(H264Contex
      pic = &h->DPB[i];
  
      pic->reference              = h->droppable ? 0 : h->picture_structure;
-     pic->f.coded_picture_number = h->coded_picture_number++;
+     pic->f->coded_picture_number = h->coded_picture_number++;
      pic->field_picture          = h->picture_structure != PICT_FRAME;
 +
      /*
       * Zero key_frame here; IDR markings per slice in frame or fields are ORed
       * in later.
       * See decode_nal_units().
       */
-     pic->f.key_frame = 0;
+     pic->f->key_frame = 0;
      pic->mmco_reset  = 0;
      pic->recovered   = 0;
 +    pic->invalid_gap = 0;
 +    pic->sei_recovery_frame_cnt = h->sei_recovery_frame_cnt;
  
      if ((ret = alloc_picture(h, pic)) < 0)
          return ret;
-         avpriv_color_frame(&pic->f, c);
 +    if(!h->frame_recovered && !h->avctx->hwaccel &&
 +       !(h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU))
++        avpriv_color_frame(pic->f, c);
  
      h->cur_pic_ptr = pic;
      ff_h264_unref_picture(h, &h->cur_pic);
      if ((ret = ff_h264_ref_picture(h, &h->cur_pic, h->cur_pic_ptr)) < 0)
          return ret;
  
 -    if (CONFIG_ERROR_RESILIENCE && h->enable_er)
 +    for (i = 0; i < h->nb_slice_ctx; i++) {
-         h->slice_ctx[i].linesize   = h->cur_pic_ptr->f.linesize[0];
-         h->slice_ctx[i].uvlinesize = h->cur_pic_ptr->f.linesize[1];
++        h->slice_ctx[i].linesize   = h->cur_pic_ptr->f->linesize[0];
++        h->slice_ctx[i].uvlinesize = h->cur_pic_ptr->f->linesize[1];
 +    }
 +
 +    if (CONFIG_ERROR_RESILIENCE && h->enable_er) {
          ff_er_frame_start(&h->slice_ctx[0].er);
 +        ff_h264_set_erpic(&h->slice_ctx[0].er.last_pic, NULL);
 +        ff_h264_set_erpic(&h->slice_ctx[0].er.next_pic, NULL);
 +    }
  
      for (i = 0; i < 16; i++) {
-         h->block_offset[i]           = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 4 * pic->f.linesize[0] * ((scan8[i] - scan8[0]) >> 3);
-         h->block_offset[48 + i]      = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 8 * pic->f.linesize[0] * ((scan8[i] - scan8[0]) >> 3);
+         h->block_offset[i]           = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 4 * pic->f->linesize[0] * ((scan8[i] - scan8[0]) >> 3);
+         h->block_offset[48 + i]      = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 8 * pic->f->linesize[0] * ((scan8[i] - scan8[0]) >> 3);
      }
      for (i = 0; i < 16; i++) {
          h->block_offset[16 + i]      =
-         h->block_offset[32 + i]      = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 4 * pic->f.linesize[1] * ((scan8[i] - scan8[0]) >> 3);
+         h->block_offset[32 + i]      = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 4 * pic->f->linesize[1] * ((scan8[i] - scan8[0]) >> 3);
          h->block_offset[48 + 16 + i] =
-         h->block_offset[48 + 32 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 8 * pic->f.linesize[1] * ((scan8[i] - scan8[0]) >> 3);
+         h->block_offset[48 + 32 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 8 * pic->f->linesize[1] * ((scan8[i] - scan8[0]) >> 3);
      }
  
 -    /* Some macroblocks can be accessed before they're available in case
 -     * of lost slices, MBAFF or threading. */
 -    memset(h->slice_table, -1,
 -           (h->mb_height * h->mb_stride - 1) * sizeof(*h->slice_table));
 -
      /* We mark the current picture as non-reference after allocating it, so
       * that if we break out due to an error it can be released automatically
       * in the next ff_mpv_frame_start().
@@@ -1457,18 -1275,12 +1457,18 @@@ int ff_h264_decode_slice_header(H264Con
           * Here, we're using that to see if we should mark previously
           * decode frames as "finished".
           * We have to do that before the "dummy" in-between frame allocation,
 -         * since that can modify s->current_picture_ptr. */
 +         * since that can modify h->cur_pic_ptr. */
          if (h->first_field) {
 -            assert(h->cur_pic_ptr);
 -            assert(h->cur_pic_ptr->f->buf[0]);
 +            av_assert0(h->cur_pic_ptr);
-             av_assert0(h->cur_pic_ptr->f.buf[0]);
++            av_assert0(h->cur_pic_ptr->f->buf[0]);
              assert(h->cur_pic_ptr->reference != DELAYED_PIC_REF);
  
 +            /* Mark old field/frame as completed */
 +            if (h->cur_pic_ptr->tf.owner == h->avctx) {
 +                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
 +                                          last_pic_structure == PICT_BOTTOM_FIELD);
 +            }
 +
              /* figure out if we have a complementary field pair */
              if (!FIELD_PICTURE(h) || h->picture_structure == last_pic_structure) {
                  /* Previous field is unmatched. Don't display it, but let it
           * We're using that to see whether to continue decoding in that
           * frame, or to allocate a new one. */
          if (h->first_field) {
 -            assert(h->cur_pic_ptr);
 -            assert(h->cur_pic_ptr->f->buf[0]);
 +            av_assert0(h->cur_pic_ptr);
-             av_assert0(h->cur_pic_ptr->f.buf[0]);
++            av_assert0(h->cur_pic_ptr->f->buf[0]);
              assert(h->cur_pic_ptr->reference != DELAYED_PIC_REF);
  
              /* figure out if we have a complementary field pair */
@@@ -886,15 -878,27 +886,24 @@@ static av_cold int svq3_decode_init(AVC
      s->last_pic = av_mallocz(sizeof(*s->last_pic));
      s->next_pic = av_mallocz(sizeof(*s->next_pic));
      if (!s->next_pic || !s->last_pic || !s->cur_pic) {
 -        av_freep(&s->cur_pic);
 -        av_freep(&s->last_pic);
 -        av_freep(&s->next_pic);
 -        return AVERROR(ENOMEM);
 +        ret = AVERROR(ENOMEM);
 +        goto fail;
      }
  
 -    if (ff_h264_decode_init(avctx) < 0)
 -        return -1;
+     s->cur_pic->f  = av_frame_alloc();
+     s->last_pic->f = av_frame_alloc();
+     s->next_pic->f = av_frame_alloc();
+     if (!s->cur_pic->f || !s->last_pic->f || !s->next_pic->f)
+         return AVERROR(ENOMEM);
 +    if ((ret = ff_h264_decode_init(avctx)) < 0)
 +        goto fail;
  
+     // we will overwrite it later during decoding
+     av_frame_free(&h->cur_pic.f);
      ff_h264dsp_init(&h->h264dsp, 8, 1);
 -    ff_h264chroma_init(&h->h264chroma, 8);
 -    ff_h264qpel_init(&h->h264qpel, 8);
 +    av_assert0(h->sps.bit_depth_chroma == 0);
      ff_h264_pred_init(&h->hpc, AV_CODEC_ID_SVQ3, 8, 1);
      ff_videodsp_init(&h->vdsp, 8);
  
@@@ -1130,7 -1117,7 +1139,7 @@@ static int get_buffer(AVCodecContext *a
          goto fail;
  
      if (!sl->edge_emu_buffer) {
-         sl->edge_emu_buffer = av_mallocz_array(pic->f.linesize[0], 17);
 -        sl->edge_emu_buffer = av_mallocz(pic->f->linesize[0] * 17);
++        sl->edge_emu_buffer = av_mallocz_array(pic->f->linesize[0], 17);
          if (!sl->edge_emu_buffer)
              return AVERROR(ENOMEM);
      }
@@@ -1218,22 -1190,20 +1223,22 @@@ static int svq3_decode_frame(AVCodecCon
      }
  
      if (h->pict_type != AV_PICTURE_TYPE_I) {
-         if (!s->last_pic->f.data[0]) {
+         if (!s->last_pic->f->data[0]) {
              av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n");
-             av_frame_unref(&s->last_pic->f);
++            av_frame_unref(s->last_pic->f);
              ret = get_buffer(avctx, s->last_pic);
              if (ret < 0)
                  return ret;
-             memset(s->last_pic->f.data[0], 0, avctx->height * s->last_pic->f.linesize[0]);
-             memset(s->last_pic->f.data[1], 0x80, (avctx->height / 2) *
-                    s->last_pic->f.linesize[1]);
-             memset(s->last_pic->f.data[2], 0x80, (avctx->height / 2) *
-                    s->last_pic->f.linesize[2]);
+             memset(s->last_pic->f->data[0], 0, avctx->height * s->last_pic->f->linesize[0]);
+             memset(s->last_pic->f->data[1], 0x80, (avctx->height / 2) *
+                    s->last_pic->f->linesize[1]);
+             memset(s->last_pic->f->data[2], 0x80, (avctx->height / 2) *
+                    s->last_pic->f->linesize[2]);
          }
  
-         if (h->pict_type == AV_PICTURE_TYPE_B && !s->next_pic->f.data[0]) {
+         if (h->pict_type == AV_PICTURE_TYPE_B && !s->next_pic->f->data[0]) {
              av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n");
-             av_frame_unref(&s->next_pic->f);
++            av_frame_unref(s->next_pic->f);
              ret = get_buffer(avctx, s->next_pic);
              if (ret < 0)
                  return ret;
                             h->low_delay);
      }
  
 +    left = buf_size*8 - get_bits_count(&h->gb);
 +
 +    if (sl->mb_y != h->mb_height || sl->mb_x != h->mb_width) {
 +        av_log(avctx, AV_LOG_INFO, "frame num %d incomplete pic x %d y %d left %d\n", avctx->frame_number, sl->mb_y, sl->mb_x, left);
 +        //av_hex_dump(stderr, buf+buf_size-8, 8);
 +    }
 +
 +    if (left < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "frame num %d left %d\n", avctx->frame_number, left);
 +        return -1;
 +    }
 +
      if (h->pict_type == AV_PICTURE_TYPE_B || h->low_delay)
-         ret = av_frame_ref(data, &s->cur_pic->f);
-     else if (s->last_pic->f.data[0])
-         ret = av_frame_ref(data, &s->last_pic->f);
+         ret = av_frame_ref(data, s->cur_pic->f);
+     else if (s->last_pic->f->data[0])
+         ret = av_frame_ref(data, s->last_pic->f);
      if (ret < 0)
          return ret;
  
Simple merge
@@@ -143,9 -129,7 +143,9 @@@ static int vda_old_h264_end_frame(AVCod
      H264Context *h                      = avctx->priv_data;
      VDAContext *vda                     = avctx->internal->hwaccel_priv_data;
      struct vda_context *vda_ctx         = avctx->hwaccel_context;
-     AVFrame *frame                      = &h->cur_pic_ptr->f;
+     AVFrame *frame                      = h->cur_pic_ptr->f;
 +    struct vda_buffer *context;
 +    AVBufferRef *buffer;
      int status;
  
      if (!vda_ctx->decoder || !vda->bitstream)
@@@ -355,343 -318,6 +355,343 @@@ int ff_vdpau_add_buffer(struct vdpau_pi
      return 0;
  }
  
-     render = (struct vdpau_render_state *)h->cur_pic_ptr->f.data[0];
 +/* Obsolete non-hwaccel VDPAU support below... */
 +
 +void ff_vdpau_h264_set_reference_frames(H264Context *h)
 +{
 +    struct vdpau_render_state *render, *render_ref;
 +    VdpReferenceFrameH264 *rf, *rf2;
 +    H264Picture *pic;
 +    int i, list, pic_frame_idx;
 +
-             render_ref = (struct vdpau_render_state *)pic->f.data[0];
++    render = (struct vdpau_render_state *)h->cur_pic_ptr->f->data[0];
 +    assert(render);
 +
 +    rf = &render->info.h264.referenceFrames[0];
 +#define H264_RF_COUNT FF_ARRAY_ELEMS(render->info.h264.referenceFrames)
 +
 +    for (list = 0; list < 2; ++list) {
 +        H264Picture **lp = list ? h->long_ref : h->short_ref;
 +        int ls = list ? 16 : h->short_ref_count;
 +
 +        for (i = 0; i < ls; ++i) {
 +            pic = lp[i];
 +            if (!pic || !pic->reference)
 +                continue;
 +            pic_frame_idx = pic->long_ref ? pic->pic_id : pic->frame_num;
 +
-     render = (struct vdpau_render_state *)h->cur_pic_ptr->f.data[0];
++            render_ref = (struct vdpau_render_state *)pic->f->data[0];
 +            assert(render_ref);
 +
 +            rf2 = &render->info.h264.referenceFrames[0];
 +            while (rf2 != rf) {
 +                if (
 +                    (rf2->surface == render_ref->surface)
 +                    && (rf2->is_long_term == pic->long_ref)
 +                    && (rf2->frame_idx == pic_frame_idx)
 +                )
 +                    break;
 +                ++rf2;
 +            }
 +            if (rf2 != rf) {
 +                rf2->top_is_reference    |= (pic->reference & PICT_TOP_FIELD)    ? VDP_TRUE : VDP_FALSE;
 +                rf2->bottom_is_reference |= (pic->reference & PICT_BOTTOM_FIELD) ? VDP_TRUE : VDP_FALSE;
 +                continue;
 +            }
 +
 +            if (rf >= &render->info.h264.referenceFrames[H264_RF_COUNT])
 +                continue;
 +
 +            rf->surface             = render_ref->surface;
 +            rf->is_long_term        = pic->long_ref;
 +            rf->top_is_reference    = (pic->reference & PICT_TOP_FIELD)    ? VDP_TRUE : VDP_FALSE;
 +            rf->bottom_is_reference = (pic->reference & PICT_BOTTOM_FIELD) ? VDP_TRUE : VDP_FALSE;
 +            rf->field_order_cnt[0]  = pic->field_poc[0];
 +            rf->field_order_cnt[1]  = pic->field_poc[1];
 +            rf->frame_idx           = pic_frame_idx;
 +
 +            ++rf;
 +        }
 +    }
 +
 +    for (; rf < &render->info.h264.referenceFrames[H264_RF_COUNT]; ++rf) {
 +        rf->surface             = VDP_INVALID_HANDLE;
 +        rf->is_long_term        = 0;
 +        rf->top_is_reference    = 0;
 +        rf->bottom_is_reference = 0;
 +        rf->field_order_cnt[0]  = 0;
 +        rf->field_order_cnt[1]  = 0;
 +        rf->frame_idx           = 0;
 +    }
 +}
 +
 +void ff_vdpau_add_data_chunk(uint8_t *data, const uint8_t *buf, int buf_size)
 +{
 +    struct vdpau_render_state *render = (struct vdpau_render_state*)data;
 +    assert(render);
 +
 +    render->bitstream_buffers= av_fast_realloc(
 +        render->bitstream_buffers,
 +        &render->bitstream_buffers_allocated,
 +        sizeof(*render->bitstream_buffers)*(render->bitstream_buffers_used + 1)
 +    );
 +
 +    render->bitstream_buffers[render->bitstream_buffers_used].struct_version  = VDP_BITSTREAM_BUFFER_VERSION;
 +    render->bitstream_buffers[render->bitstream_buffers_used].bitstream       = buf;
 +    render->bitstream_buffers[render->bitstream_buffers_used].bitstream_bytes = buf_size;
 +    render->bitstream_buffers_used++;
 +}
 +
 +#if CONFIG_H264_VDPAU_DECODER
 +void ff_vdpau_h264_picture_start(H264Context *h)
 +{
 +    struct vdpau_render_state *render;
 +    int i;
 +
-     render = (struct vdpau_render_state *)h->cur_pic_ptr->f.data[0];
++    render = (struct vdpau_render_state *)h->cur_pic_ptr->f->data[0];
 +    assert(render);
 +
 +    for (i = 0; i < 2; ++i) {
 +        int foc = h->cur_pic_ptr->field_poc[i];
 +        if (foc == INT_MAX)
 +            foc = 0;
 +        render->info.h264.field_order_cnt[i] = foc;
 +    }
 +
 +    render->info.h264.frame_num = h->frame_num;
 +}
 +
 +void ff_vdpau_h264_picture_complete(H264Context *h)
 +{
 +    struct vdpau_render_state *render;
 +
++    render = (struct vdpau_render_state *)h->cur_pic_ptr->f->data[0];
 +    assert(render);
 +
 +    render->info.h264.slice_count = h->current_slice;
 +    if (render->info.h264.slice_count < 1)
 +        return;
 +
 +    render->info.h264.is_reference                           = (h->cur_pic_ptr->reference & 3) ? VDP_TRUE : VDP_FALSE;
 +    render->info.h264.field_pic_flag                         = h->picture_structure != PICT_FRAME;
 +    render->info.h264.bottom_field_flag                      = h->picture_structure == PICT_BOTTOM_FIELD;
 +    render->info.h264.num_ref_frames                         = h->sps.ref_frame_count;
 +    render->info.h264.mb_adaptive_frame_field_flag           = h->sps.mb_aff && !render->info.h264.field_pic_flag;
 +    render->info.h264.constrained_intra_pred_flag            = h->pps.constrained_intra_pred;
 +    render->info.h264.weighted_pred_flag                     = h->pps.weighted_pred;
 +    render->info.h264.weighted_bipred_idc                    = h->pps.weighted_bipred_idc;
 +    render->info.h264.frame_mbs_only_flag                    = h->sps.frame_mbs_only_flag;
 +    render->info.h264.transform_8x8_mode_flag                = h->pps.transform_8x8_mode;
 +    render->info.h264.chroma_qp_index_offset                 = h->pps.chroma_qp_index_offset[0];
 +    render->info.h264.second_chroma_qp_index_offset          = h->pps.chroma_qp_index_offset[1];
 +    render->info.h264.pic_init_qp_minus26                    = h->pps.init_qp - 26;
 +    render->info.h264.num_ref_idx_l0_active_minus1           = h->pps.ref_count[0] - 1;
 +    render->info.h264.num_ref_idx_l1_active_minus1           = h->pps.ref_count[1] - 1;
 +    render->info.h264.log2_max_frame_num_minus4              = h->sps.log2_max_frame_num - 4;
 +    render->info.h264.pic_order_cnt_type                     = h->sps.poc_type;
 +    render->info.h264.log2_max_pic_order_cnt_lsb_minus4      = h->sps.poc_type ? 0 : h->sps.log2_max_poc_lsb - 4;
 +    render->info.h264.delta_pic_order_always_zero_flag       = h->sps.delta_pic_order_always_zero_flag;
 +    render->info.h264.direct_8x8_inference_flag              = h->sps.direct_8x8_inference_flag;
 +    render->info.h264.entropy_coding_mode_flag               = h->pps.cabac;
 +    render->info.h264.pic_order_present_flag                 = h->pps.pic_order_present;
 +    render->info.h264.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present;
 +    render->info.h264.redundant_pic_cnt_present_flag         = h->pps.redundant_pic_cnt_present;
 +    memcpy(render->info.h264.scaling_lists_4x4, h->pps.scaling_matrix4, sizeof(render->info.h264.scaling_lists_4x4));
 +    memcpy(render->info.h264.scaling_lists_8x8[0], h->pps.scaling_matrix8[0], sizeof(render->info.h264.scaling_lists_8x8[0]));
 +    memcpy(render->info.h264.scaling_lists_8x8[1], h->pps.scaling_matrix8[3], sizeof(render->info.h264.scaling_lists_8x8[0]));
 +
 +    ff_h264_draw_horiz_band(h, &h->slice_ctx[0], 0, h->avctx->height);
 +    render->bitstream_buffers_used = 0;
 +}
 +#endif /* CONFIG_H264_VDPAU_DECODER */
 +
 +#if CONFIG_MPEG_VDPAU_DECODER || CONFIG_MPEG1_VDPAU_DECODER
 +void ff_vdpau_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf,
 +                                    int buf_size, int slice_count)
 +{
 +    struct vdpau_render_state *render, *last, *next;
 +    int i;
 +
 +    if (!s->current_picture_ptr) return;
 +
 +    render = (struct vdpau_render_state *)s->current_picture_ptr->f->data[0];
 +    assert(render);
 +
 +    /* fill VdpPictureInfoMPEG1Or2 struct */
 +    render->info.mpeg.picture_structure          = s->picture_structure;
 +    render->info.mpeg.picture_coding_type        = s->pict_type;
 +    render->info.mpeg.intra_dc_precision         = s->intra_dc_precision;
 +    render->info.mpeg.frame_pred_frame_dct       = s->frame_pred_frame_dct;
 +    render->info.mpeg.concealment_motion_vectors = s->concealment_motion_vectors;
 +    render->info.mpeg.intra_vlc_format           = s->intra_vlc_format;
 +    render->info.mpeg.alternate_scan             = s->alternate_scan;
 +    render->info.mpeg.q_scale_type               = s->q_scale_type;
 +    render->info.mpeg.top_field_first            = s->top_field_first;
 +    render->info.mpeg.full_pel_forward_vector    = s->full_pel[0]; // MPEG-1 only.  Set 0 for MPEG-2
 +    render->info.mpeg.full_pel_backward_vector   = s->full_pel[1]; // MPEG-1 only.  Set 0 for MPEG-2
 +    render->info.mpeg.f_code[0][0]               = s->mpeg_f_code[0][0]; // For MPEG-1 fill both horiz. & vert.
 +    render->info.mpeg.f_code[0][1]               = s->mpeg_f_code[0][1];
 +    render->info.mpeg.f_code[1][0]               = s->mpeg_f_code[1][0];
 +    render->info.mpeg.f_code[1][1]               = s->mpeg_f_code[1][1];
 +    for (i = 0; i < 64; ++i) {
 +        render->info.mpeg.intra_quantizer_matrix[i]     = s->intra_matrix[i];
 +        render->info.mpeg.non_intra_quantizer_matrix[i] = s->inter_matrix[i];
 +    }
 +
 +    render->info.mpeg.forward_reference          = VDP_INVALID_HANDLE;
 +    render->info.mpeg.backward_reference         = VDP_INVALID_HANDLE;
 +
 +    switch(s->pict_type){
 +    case  AV_PICTURE_TYPE_B:
 +        next = (struct vdpau_render_state *)s->next_picture.f->data[0];
 +        assert(next);
 +        render->info.mpeg.backward_reference     = next->surface;
 +        // no return here, going to set forward prediction
 +    case  AV_PICTURE_TYPE_P:
 +        last = (struct vdpau_render_state *)s->last_picture.f->data[0];
 +        if (!last) // FIXME: Does this test make sense?
 +            last = render; // predict second field from the first
 +        render->info.mpeg.forward_reference      = last->surface;
 +    }
 +
 +    ff_vdpau_add_data_chunk(s->current_picture_ptr->f->data[0], buf, buf_size);
 +
 +    render->info.mpeg.slice_count                = slice_count;
 +
 +    if (slice_count)
 +        ff_mpeg_draw_horiz_band(s, 0, s->avctx->height);
 +    render->bitstream_buffers_used               = 0;
 +}
 +#endif /* CONFIG_MPEG_VDPAU_DECODER || CONFIG_MPEG1_VDPAU_DECODER */
 +
 +#if CONFIG_VC1_VDPAU_DECODER
 +void ff_vdpau_vc1_decode_picture(MpegEncContext *s, const uint8_t *buf,
 +                                 int buf_size)
 +{
 +    VC1Context *v = s->avctx->priv_data;
 +    struct vdpau_render_state *render, *last, *next;
 +
 +    render = (struct vdpau_render_state *)s->current_picture.f->data[0];
 +    assert(render);
 +
 +    /*  fill LvPictureInfoVC1 struct */
 +    render->info.vc1.frame_coding_mode  = v->fcm ? v->fcm + 1 : 0;
 +    render->info.vc1.postprocflag       = v->postprocflag;
 +    render->info.vc1.pulldown           = v->broadcast;
 +    render->info.vc1.interlace          = v->interlace;
 +    render->info.vc1.tfcntrflag         = v->tfcntrflag;
 +    render->info.vc1.finterpflag        = v->finterpflag;
 +    render->info.vc1.psf                = v->psf;
 +    render->info.vc1.dquant             = v->dquant;
 +    render->info.vc1.panscan_flag       = v->panscanflag;
 +    render->info.vc1.refdist_flag       = v->refdist_flag;
 +    render->info.vc1.quantizer          = v->quantizer_mode;
 +    render->info.vc1.extended_mv        = v->extended_mv;
 +    render->info.vc1.extended_dmv       = v->extended_dmv;
 +    render->info.vc1.overlap            = v->overlap;
 +    render->info.vc1.vstransform        = v->vstransform;
 +    render->info.vc1.loopfilter         = v->s.loop_filter;
 +    render->info.vc1.fastuvmc           = v->fastuvmc;
 +    render->info.vc1.range_mapy_flag    = v->range_mapy_flag;
 +    render->info.vc1.range_mapy         = v->range_mapy;
 +    render->info.vc1.range_mapuv_flag   = v->range_mapuv_flag;
 +    render->info.vc1.range_mapuv        = v->range_mapuv;
 +    /* Specific to simple/main profile only */
 +    render->info.vc1.multires           = v->multires;
 +    render->info.vc1.syncmarker         = v->resync_marker;
 +    render->info.vc1.rangered           = v->rangered | (v->rangeredfrm << 1);
 +    render->info.vc1.maxbframes         = v->s.max_b_frames;
 +
 +    render->info.vc1.deblockEnable      = v->postprocflag & 1;
 +    render->info.vc1.pquant             = v->pq;
 +
 +    render->info.vc1.forward_reference  = VDP_INVALID_HANDLE;
 +    render->info.vc1.backward_reference = VDP_INVALID_HANDLE;
 +
 +    if (v->bi_type)
 +        render->info.vc1.picture_type = 4;
 +    else
 +        render->info.vc1.picture_type = s->pict_type - 1 + s->pict_type / 3;
 +
 +    switch(s->pict_type){
 +    case  AV_PICTURE_TYPE_B:
 +        next = (struct vdpau_render_state *)s->next_picture.f->data[0];
 +        assert(next);
 +        render->info.vc1.backward_reference = next->surface;
 +        // no break here, going to set forward prediction
 +    case  AV_PICTURE_TYPE_P:
 +        last = (struct vdpau_render_state *)s->last_picture.f->data[0];
 +        if (!last) // FIXME: Does this test make sense?
 +            last = render; // predict second field from the first
 +        render->info.vc1.forward_reference = last->surface;
 +    }
 +
 +    ff_vdpau_add_data_chunk(s->current_picture_ptr->f->data[0], buf, buf_size);
 +
 +    render->info.vc1.slice_count          = 1;
 +
 +    ff_mpeg_draw_horiz_band(s, 0, s->avctx->height);
 +    render->bitstream_buffers_used        = 0;
 +}
 +#endif /* (CONFIG_VC1_VDPAU_DECODER */
 +
 +#if CONFIG_MPEG4_VDPAU_DECODER
 +void ff_vdpau_mpeg4_decode_picture(Mpeg4DecContext *ctx, const uint8_t *buf,
 +                                   int buf_size)
 +{
 +    MpegEncContext *s = &ctx->m;
 +    struct vdpau_render_state *render, *last, *next;
 +    int i;
 +
 +    if (!s->current_picture_ptr) return;
 +
 +    render = (struct vdpau_render_state *)s->current_picture_ptr->f->data[0];
 +    assert(render);
 +
 +    /* fill VdpPictureInfoMPEG4Part2 struct */
 +    render->info.mpeg4.trd[0]                            = s->pp_time;
 +    render->info.mpeg4.trb[0]                            = s->pb_time;
 +    render->info.mpeg4.trd[1]                            = s->pp_field_time >> 1;
 +    render->info.mpeg4.trb[1]                            = s->pb_field_time >> 1;
 +    render->info.mpeg4.vop_time_increment_resolution     = s->avctx->time_base.den;
 +    render->info.mpeg4.vop_coding_type                   = 0;
 +    render->info.mpeg4.vop_fcode_forward                 = s->f_code;
 +    render->info.mpeg4.vop_fcode_backward                = s->b_code;
 +    render->info.mpeg4.resync_marker_disable             = !ctx->resync_marker;
 +    render->info.mpeg4.interlaced                        = !s->progressive_sequence;
 +    render->info.mpeg4.quant_type                        = s->mpeg_quant;
 +    render->info.mpeg4.quarter_sample                    = s->quarter_sample;
 +    render->info.mpeg4.short_video_header                = s->avctx->codec->id == AV_CODEC_ID_H263;
 +    render->info.mpeg4.rounding_control                  = s->no_rounding;
 +    render->info.mpeg4.alternate_vertical_scan_flag      = s->alternate_scan;
 +    render->info.mpeg4.top_field_first                   = s->top_field_first;
 +    for (i = 0; i < 64; ++i) {
 +        render->info.mpeg4.intra_quantizer_matrix[i]     = s->intra_matrix[i];
 +        render->info.mpeg4.non_intra_quantizer_matrix[i] = s->inter_matrix[i];
 +    }
 +    render->info.mpeg4.forward_reference                 = VDP_INVALID_HANDLE;
 +    render->info.mpeg4.backward_reference                = VDP_INVALID_HANDLE;
 +
 +    switch (s->pict_type) {
 +    case AV_PICTURE_TYPE_B:
 +        next = (struct vdpau_render_state *)s->next_picture.f->data[0];
 +        assert(next);
 +        render->info.mpeg4.backward_reference     = next->surface;
 +        render->info.mpeg4.vop_coding_type        = 2;
 +        // no break here, going to set forward prediction
 +    case AV_PICTURE_TYPE_P:
 +        last = (struct vdpau_render_state *)s->last_picture.f->data[0];
 +        assert(last);
 +        render->info.mpeg4.forward_reference      = last->surface;
 +    }
 +
 +    ff_vdpau_add_data_chunk(s->current_picture_ptr->f->data[0], buf, buf_size);
 +
 +    ff_mpeg_draw_horiz_band(s, 0, s->avctx->height);
 +    render->bitstream_buffers_used = 0;
 +}
 +#endif /* CONFIG_MPEG4_VDPAU_DECODER */
 +
  int av_vdpau_get_profile(AVCodecContext *avctx, VdpDecoderProfile *profile)
  {
  #define PROFILE(prof)                      \
Simple merge