vdpau: don't assume Picture and H264Picture are the same
[ffmpeg.git] / libavcodec / vdpau_h264.c
index 09b7ad5..c71d6b8 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "avcodec.h"
 #include "h264.h"
+#include "mpegutils.h"
 #include "vdpau.h"
 #include "vdpau_internal.h"
 
@@ -46,16 +47,16 @@ static void vdpau_h264_clear_rf(VdpReferenceFrameH264 *rf)
     rf->frame_idx           = 0;
 }
 
-static void vdpau_h264_set_rf(VdpReferenceFrameH264 *rf, Picture *pic,
+static void vdpau_h264_set_rf(VdpReferenceFrameH264 *rf, H264Picture *pic,
                               int pic_structure)
 {
     VdpVideoSurface surface = ff_vdpau_get_surface_id(pic);
 
     if (pic_structure == 0)
-        pic_structure = pic->f.reference;
+        pic_structure = pic->reference;
 
     rf->surface             = surface;
-    rf->is_long_term        = pic->f.reference && pic->long_ref;
+    rf->is_long_term        = pic->reference && pic->long_ref;
     rf->top_is_reference    = (pic_structure & PICT_TOP_FIELD)    != 0;
     rf->bottom_is_reference = (pic_structure & PICT_BOTTOM_FIELD) != 0;
     rf->field_order_cnt[0]  = h264_foc(pic->field_poc[0]);
@@ -66,24 +67,24 @@ static void vdpau_h264_set_rf(VdpReferenceFrameH264 *rf, Picture *pic,
 static void vdpau_h264_set_reference_frames(AVCodecContext *avctx)
 {
     H264Context * const h = avctx->priv_data;
-    AVVDPAUContext *hwctx = avctx->hwaccel_context;
-    VdpPictureInfoH264 *info = &hwctx->info.h264;
+    struct vdpau_picture_context *pic_ctx = h->cur_pic_ptr->hwaccel_picture_private;
+    VdpPictureInfoH264 *info = &pic_ctx->info.h264;
     int list;
 
     VdpReferenceFrameH264 *rf = &info->referenceFrames[0];
 #define H264_RF_COUNT FF_ARRAY_ELEMS(info->referenceFrames)
 
     for (list = 0; list < 2; ++list) {
-        Picture **lp = list ? h->long_ref : h->short_ref;
+        H264Picture **lp = list ? h->long_ref : h->short_ref;
         int i, ls    = list ? 16          : h->short_ref_count;
 
         for (i = 0; i < ls; ++i) {
-            Picture *pic = lp[i];
+            H264Picture *pic = lp[i];
             VdpReferenceFrameH264 *rf2;
             VdpVideoSurface surface_ref;
             int pic_frame_idx;
 
-            if (!pic || !pic->f.reference)
+            if (!pic || !pic->reference)
                 continue;
             pic_frame_idx = pic->long_ref ? pic->pic_id : pic->frame_num;
             surface_ref = ff_vdpau_get_surface_id(pic);
@@ -97,15 +98,15 @@ static void vdpau_h264_set_reference_frames(AVCodecContext *avctx)
                 ++rf2;
             }
             if (rf2 != rf) {
-                rf2->top_is_reference    |= (pic->f.reference & PICT_TOP_FIELD)    ? VDP_TRUE : VDP_FALSE;
-                rf2->bottom_is_reference |= (pic->f.reference & PICT_BOTTOM_FIELD) ? VDP_TRUE : VDP_FALSE;
+                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 >= &info->referenceFrames[H264_RF_COUNT])
                 continue;
 
-            vdpau_h264_set_rf(rf, pic, pic->f.reference);
+            vdpau_h264_set_rf(rf, pic, pic->reference);
             ++rf;
         }
     }
@@ -118,10 +119,9 @@ static int vdpau_h264_start_frame(AVCodecContext *avctx,
                                   const uint8_t *buffer, uint32_t size)
 {
     H264Context * const h = avctx->priv_data;
-    AVVDPAUContext *hwctx = avctx->hwaccel_context;
-    MpegEncContext * const s = &h->s;
-    VdpPictureInfoH264 *info = &hwctx->info.h264;
-    Picture *pic = s->current_picture_ptr;
+    H264Picture *pic = h->cur_pic_ptr;
+    struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private;
+    VdpPictureInfoH264 *info = &pic_ctx->info.h264;
 
     /* init VdpPictureInfoH264 */
     info->slice_count                            = 0;
@@ -129,8 +129,8 @@ static int vdpau_h264_start_frame(AVCodecContext *avctx,
     info->field_order_cnt[1]                     = h264_foc(pic->field_poc[1]);
     info->is_reference                           = h->nal_ref_idc != 0;
     info->frame_num                              = h->frame_num;
-    info->field_pic_flag                         = s->picture_structure != PICT_FRAME;
-    info->bottom_field_flag                      = s->picture_structure == PICT_BOTTOM_FIELD;
+    info->field_pic_flag                         = h->picture_structure != PICT_FRAME;
+    info->bottom_field_flag                      = h->picture_structure == PICT_BOTTOM_FIELD;
     info->num_ref_frames                         = h->sps.ref_frame_count;
     info->mb_adaptive_frame_field_flag           = h->sps.mb_aff && !info->field_pic_flag;
     info->constrained_intra_pred_flag            = h->pps.constrained_intra_pred;
@@ -162,7 +162,7 @@ static int vdpau_h264_start_frame(AVCodecContext *avctx,
 
     vdpau_h264_set_reference_frames(avctx);
 
-    return ff_vdpau_common_start_frame(avctx, buffer, size);
+    return ff_vdpau_common_start_frame(pic_ctx, buffer, size);
 }
 
 static const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 };
@@ -170,18 +170,37 @@ static const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 };
 static int vdpau_h264_decode_slice(AVCodecContext *avctx,
                                    const uint8_t *buffer, uint32_t size)
 {
-    AVVDPAUContext *hwctx = avctx->hwaccel_context;
+    H264Context *h = avctx->priv_data;
+    H264Picture *pic = h->cur_pic_ptr;
+    struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private;
     int val;
 
-    val = ff_vdpau_add_buffer(avctx, start_code_prefix, 3);
+    val = ff_vdpau_add_buffer(pic_ctx, start_code_prefix, 3);
     if (val)
         return val;
 
-    val = ff_vdpau_add_buffer(avctx, buffer, size);
+    val = ff_vdpau_add_buffer(pic_ctx, buffer, size);
     if (val)
         return val;
 
-    hwctx->info.h264.slice_count++;
+    pic_ctx->info.h264.slice_count++;
+    return 0;
+}
+
+static int vdpau_h264_end_frame(AVCodecContext *avctx)
+{
+    AVVDPAUContext *hwctx = avctx->hwaccel_context;
+    H264Context *h = avctx->priv_data;
+    H264Picture *pic = h->cur_pic_ptr;
+    struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private;
+    VdpVideoSurface surf = ff_vdpau_get_surface_id(pic);
+
+    hwctx->render(hwctx->decoder, surf, (void *)&pic_ctx->info,
+                  pic_ctx->bitstream_buffers_used, pic_ctx->bitstream_buffers);
+
+    ff_h264_draw_horiz_band(h, 0, h->avctx->height);
+    av_freep(&pic_ctx->bitstream_buffers);
+
     return 0;
 }
 
@@ -191,6 +210,7 @@ AVHWAccel ff_h264_vdpau_hwaccel = {
     .id             = AV_CODEC_ID_H264,
     .pix_fmt        = AV_PIX_FMT_VDPAU,
     .start_frame    = vdpau_h264_start_frame,
-    .end_frame      = ff_vdpau_common_end_frame,
+    .end_frame      = vdpau_h264_end_frame,
     .decode_slice   = vdpau_h264_decode_slice,
+    .priv_data_size = sizeof(struct vdpau_picture_context),
 };