[FFmpeg-devel] [PATCH 09/16] vaapi_mpeg4: Convert to use the new VAAPI hwaccel code

Mark Thompson sw at jkqxz.net
Sun Jan 8 20:12:30 EET 2017


(cherry picked from commit ccd0316f7cab760a93052206e8150f6b178c1e39)
---
 libavcodec/vaapi_mpeg4.c | 235 +++++++++++++++++++++++++++++------------------
 1 file changed, 145 insertions(+), 90 deletions(-)

diff --git a/libavcodec/vaapi_mpeg4.c b/libavcodec/vaapi_mpeg4.c
index 725f00b0a6..462233ce8c 100644
--- a/libavcodec/vaapi_mpeg4.c
+++ b/libavcodec/vaapi_mpeg4.c
@@ -20,11 +20,11 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "vaapi_internal.h"
-#include "internal.h"
 #include "h263.h"
+#include "internal.h"
 #include "mpeg4video.h"
 #include "mpegvideo.h"
+#include "vaapi_decode.h"
 
 /** Reconstruct bitstream intra_dc_vlc_thr */
 static int mpeg4_get_intra_dc_vlc_thr(Mpeg4DecContext *s)
@@ -45,121 +45,176 @@ static int mpeg4_get_intra_dc_vlc_thr(Mpeg4DecContext *s)
 static int vaapi_mpeg4_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size)
 {
     Mpeg4DecContext *ctx = avctx->priv_data;
-    MpegEncContext * const s = &ctx->m;
-    FFVAContext * const vactx = ff_vaapi_get_context(avctx);
-    VAPictureParameterBufferMPEG4 *pic_param;
-    VAIQMatrixBufferMPEG4 *iq_matrix;
-    int i;
-
-    vactx->slice_param_size = sizeof(VASliceParameterBufferMPEG4);
-
-    /* Fill in VAPictureParameterBufferMPEG4 */
-    pic_param = ff_vaapi_alloc_pic_param(vactx, sizeof(VAPictureParameterBufferMPEG4));
-    if (!pic_param)
-        return -1;
-    pic_param->vop_width                                = s->width;
-    pic_param->vop_height                               = s->height;
-    pic_param->forward_reference_picture                = VA_INVALID_ID;
-    pic_param->backward_reference_picture               = VA_INVALID_ID;
-    pic_param->vol_fields.value                         = 0; /* reset all bits */
-    pic_param->vol_fields.bits.short_video_header       = avctx->codec->id == AV_CODEC_ID_H263;
-    pic_param->vol_fields.bits.chroma_format            = CHROMA_420;
-    pic_param->vol_fields.bits.interlaced               = !s->progressive_sequence;
-    pic_param->vol_fields.bits.obmc_disable             = 1;
-    pic_param->vol_fields.bits.sprite_enable            = ctx->vol_sprite_usage;
-    pic_param->vol_fields.bits.sprite_warping_accuracy  = s->sprite_warping_accuracy;
-    pic_param->vol_fields.bits.quant_type               = s->mpeg_quant;
-    pic_param->vol_fields.bits.quarter_sample           = s->quarter_sample;
-    pic_param->vol_fields.bits.data_partitioned         = s->data_partitioning;
-    pic_param->vol_fields.bits.reversible_vlc           = ctx->rvlc;
-    pic_param->vol_fields.bits.resync_marker_disable    = !ctx->resync_marker;
-    pic_param->no_of_sprite_warping_points              = ctx->num_sprite_warping_points;
+    MpegEncContext *s = &ctx->m;
+    VAAPIDecodePicture *pic = s->current_picture_ptr->hwaccel_picture_private;
+    VAPictureParameterBufferMPEG4 pic_param;
+    int i, err;
+
+    pic->output_surface = ff_vaapi_get_surface_id(s->current_picture_ptr->f);
+
+    pic_param = (VAPictureParameterBufferMPEG4) {
+        .vop_width                        = s->width,
+        .vop_height                       = s->height,
+        .forward_reference_picture        = VA_INVALID_ID,
+        .backward_reference_picture       = VA_INVALID_ID,
+        .vol_fields.bits = {
+            .short_video_header           = avctx->codec->id == AV_CODEC_ID_H263,
+            .chroma_format                = CHROMA_420,
+            .interlaced                   = !s->progressive_sequence,
+            .obmc_disable                 = 1,
+            .sprite_enable                = ctx->vol_sprite_usage,
+            .sprite_warping_accuracy      = s->sprite_warping_accuracy,
+            .quant_type                   = s->mpeg_quant,
+            .quarter_sample               = s->quarter_sample,
+            .data_partitioned             = s->data_partitioning,
+            .reversible_vlc               = ctx->rvlc,
+            .resync_marker_disable        = !ctx->resync_marker,
+        },
+        .no_of_sprite_warping_points      = ctx->num_sprite_warping_points,
+        .quant_precision                  = s->quant_precision,
+        .vop_fields.bits = {
+            .vop_coding_type              = s->pict_type - AV_PICTURE_TYPE_I,
+            .backward_reference_vop_coding_type =
+                s->pict_type == AV_PICTURE_TYPE_B ? s->next_picture.f->pict_type - AV_PICTURE_TYPE_I : 0,
+            .vop_rounding_type            = s->no_rounding,
+            .intra_dc_vlc_thr             = mpeg4_get_intra_dc_vlc_thr(ctx),
+            .top_field_first              = s->top_field_first,
+            .alternate_vertical_scan_flag = s->alternate_scan,
+        },
+        .vop_fcode_forward                = s->f_code,
+        .vop_fcode_backward               = s->b_code,
+        .vop_time_increment_resolution    = avctx->framerate.num,
+        .num_macroblocks_in_gob           = s->mb_width * H263_GOB_HEIGHT(s->height),
+        .num_gobs_in_vop                  =
+            (s->mb_width * s->mb_height) / (s->mb_width * H263_GOB_HEIGHT(s->height)),
+        .TRB                              = s->pb_time,
+        .TRD                              = s->pp_time,
+    };
+
     for (i = 0; i < ctx->num_sprite_warping_points && i < 3; i++) {
-        pic_param->sprite_trajectory_du[i]              = ctx->sprite_traj[i][0];
-        pic_param->sprite_trajectory_dv[i]              = ctx->sprite_traj[i][1];
+        pic_param.sprite_trajectory_du[i]              = ctx->sprite_traj[i][0];
+        pic_param.sprite_trajectory_dv[i]              = ctx->sprite_traj[i][1];
     }
-    pic_param->quant_precision                          = s->quant_precision;
-    pic_param->vop_fields.value                         = 0; /* reset all bits */
-    pic_param->vop_fields.bits.vop_coding_type          = s->pict_type - AV_PICTURE_TYPE_I;
-    pic_param->vop_fields.bits.backward_reference_vop_coding_type = s->pict_type == AV_PICTURE_TYPE_B ? s->next_picture.f->pict_type - AV_PICTURE_TYPE_I : 0;
-    pic_param->vop_fields.bits.vop_rounding_type        = s->no_rounding;
-    pic_param->vop_fields.bits.intra_dc_vlc_thr         = mpeg4_get_intra_dc_vlc_thr(ctx);
-    pic_param->vop_fields.bits.top_field_first          = s->top_field_first;
-    pic_param->vop_fields.bits.alternate_vertical_scan_flag = s->alternate_scan;
-    pic_param->vop_fcode_forward                        = s->f_code;
-    pic_param->vop_fcode_backward                       = s->b_code;
-    pic_param->vop_time_increment_resolution            = avctx->framerate.num;
-    pic_param->num_macroblocks_in_gob                   = s->mb_width * H263_GOB_HEIGHT(s->height);
-    pic_param->num_gobs_in_vop                          = (s->mb_width * s->mb_height) / pic_param->num_macroblocks_in_gob;
-    pic_param->TRB                                      = s->pb_time;
-    pic_param->TRD                                      = s->pp_time;
 
     if (s->pict_type == AV_PICTURE_TYPE_B)
-        pic_param->backward_reference_picture = ff_vaapi_get_surface_id(s->next_picture.f);
+        pic_param.backward_reference_picture = ff_vaapi_get_surface_id(s->next_picture.f);
     if (s->pict_type != AV_PICTURE_TYPE_I)
-        pic_param->forward_reference_picture  = ff_vaapi_get_surface_id(s->last_picture.f);
+        pic_param.forward_reference_picture  = ff_vaapi_get_surface_id(s->last_picture.f);
+
+    err = ff_vaapi_decode_make_param_buffer(avctx, pic,
+                                            VAPictureParameterBufferType,
+                                            &pic_param, sizeof(pic_param));
+    if (err < 0)
+        goto fail;
 
-    /* Fill in VAIQMatrixBufferMPEG4 */
     /* Only the first inverse quantisation method uses the weighting matrices */
-    if (pic_param->vol_fields.bits.quant_type) {
-        iq_matrix = ff_vaapi_alloc_iq_matrix(vactx, sizeof(VAIQMatrixBufferMPEG4));
-        if (!iq_matrix)
-            return -1;
-        iq_matrix->load_intra_quant_mat         = 1;
-        iq_matrix->load_non_intra_quant_mat     = 1;
+    if (pic_param.vol_fields.bits.quant_type) {
+        VAIQMatrixBufferMPEG4 iq_matrix;
+
+        iq_matrix.load_intra_quant_mat     = 1;
+        iq_matrix.load_non_intra_quant_mat = 1;
 
         for (i = 0; i < 64; i++) {
             int n = s->idsp.idct_permutation[ff_zigzag_direct[i]];
-            iq_matrix->intra_quant_mat[i]       = s->intra_matrix[n];
-            iq_matrix->non_intra_quant_mat[i]   = s->inter_matrix[n];
+            iq_matrix.intra_quant_mat[i]     = s->intra_matrix[n];
+            iq_matrix.non_intra_quant_mat[i] = s->inter_matrix[n];
         }
+
+        err = ff_vaapi_decode_make_param_buffer(avctx, pic,
+                                                VAIQMatrixBufferType,
+                                                &iq_matrix, sizeof(iq_matrix));
+        if (err < 0)
+            goto fail;
     }
     return 0;
+
+fail:
+    ff_vaapi_decode_cancel(avctx, pic);
+    return err;
+}
+
+static int vaapi_mpeg4_end_frame(AVCodecContext *avctx)
+{
+    MpegEncContext *s = avctx->priv_data;
+    VAAPIDecodePicture *pic = s->current_picture_ptr->hwaccel_picture_private;
+    int ret;
+
+    ret = ff_vaapi_decode_issue(avctx, pic);
+    if (ret < 0)
+        goto fail;
+
+    ff_mpeg_draw_horiz_band(s, 0, s->avctx->height);
+
+fail:
+    return ret;
 }
 
 static int vaapi_mpeg4_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
 {
-    MpegEncContext * const s = avctx->priv_data;
-    FFVAContext * const vactx = ff_vaapi_get_context(avctx);
-    VASliceParameterBufferMPEG4 *slice_param;
-
-    /* Fill in VASliceParameterBufferMPEG4 */
-    slice_param = (VASliceParameterBufferMPEG4 *)ff_vaapi_alloc_slice(vactx, buffer, size);
-    if (!slice_param)
-        return -1;
-    slice_param->macroblock_offset      = get_bits_count(&s->gb) % 8;
-    slice_param->macroblock_number      = 0;
-    slice_param->quant_scale            = s->qscale;
+    MpegEncContext *s = avctx->priv_data;
+    VAAPIDecodePicture *pic = s->current_picture_ptr->hwaccel_picture_private;
+    VASliceParameterBufferMPEG4 slice_param;
+    int err;
+
+    /* video_plane_with_short_video_header() contains all GOBs
+     * in-order, and this is what VA API (Intel backend) expects: only
+     * a single slice param. So fake macroblock_number for Libav so
+     * that we don't call vaapi_mpeg4_decode_slice() again
+     */
+    if (avctx->codec->id == AV_CODEC_ID_H263)
+        size = s->gb.buffer_end - buffer;
+
+    slice_param = (VASliceParameterBufferMPEG4) {
+        .slice_data_size   = size,
+        .slice_data_offset = 0,
+        .slice_data_flag   = VA_SLICE_DATA_FLAG_ALL,
+        .macroblock_offset = get_bits_count(&s->gb) % 8,
+        .macroblock_number = s->mb_y * s->mb_width + s->mb_x,
+        .quant_scale       = s->qscale,
+    };
+
+    if (avctx->codec->id == AV_CODEC_ID_H263)
+        s->mb_y = s->mb_height;
+
+    err = ff_vaapi_decode_make_slice_buffer(avctx, pic,
+                                            &slice_param, sizeof(slice_param),
+                                            buffer, size);
+    if (err < 0) {
+        ff_vaapi_decode_cancel(avctx, pic);
+        return err;
+    }
 
     return 0;
 }
 
 #if CONFIG_MPEG4_VAAPI_HWACCEL
 AVHWAccel ff_mpeg4_vaapi_hwaccel = {
-    .name           = "mpeg4_vaapi",
-    .type           = AVMEDIA_TYPE_VIDEO,
-    .id             = AV_CODEC_ID_MPEG4,
-    .pix_fmt        = AV_PIX_FMT_VAAPI,
-    .start_frame    = vaapi_mpeg4_start_frame,
-    .end_frame      = ff_vaapi_mpeg_end_frame,
-    .decode_slice   = vaapi_mpeg4_decode_slice,
-    .init           = ff_vaapi_context_init,
-    .uninit         = ff_vaapi_context_fini,
-    .priv_data_size = sizeof(FFVAContext),
+    .name                 = "mpeg4_vaapi",
+    .type                 = AVMEDIA_TYPE_VIDEO,
+    .id                   = AV_CODEC_ID_MPEG4,
+    .pix_fmt              = AV_PIX_FMT_VAAPI,
+    .start_frame          = &vaapi_mpeg4_start_frame,
+    .end_frame            = &vaapi_mpeg4_end_frame,
+    .decode_slice         = &vaapi_mpeg4_decode_slice,
+    .frame_priv_data_size = sizeof(VAAPIDecodePicture),
+    .init                 = &ff_vaapi_decode_init,
+    .uninit               = &ff_vaapi_decode_uninit,
+    .priv_data_size       = sizeof(VAAPIDecodeContext),
 };
 #endif
 
 #if CONFIG_H263_VAAPI_HWACCEL
 AVHWAccel ff_h263_vaapi_hwaccel = {
-    .name           = "h263_vaapi",
-    .type           = AVMEDIA_TYPE_VIDEO,
-    .id             = AV_CODEC_ID_H263,
-    .pix_fmt        = AV_PIX_FMT_VAAPI,
-    .start_frame    = vaapi_mpeg4_start_frame,
-    .end_frame      = ff_vaapi_mpeg_end_frame,
-    .decode_slice   = vaapi_mpeg4_decode_slice,
-    .init           = ff_vaapi_context_init,
-    .uninit         = ff_vaapi_context_fini,
-    .priv_data_size = sizeof(FFVAContext),
+    .name                 = "h263_vaapi",
+    .type                 = AVMEDIA_TYPE_VIDEO,
+    .id                   = AV_CODEC_ID_H263,
+    .pix_fmt              = AV_PIX_FMT_VAAPI,
+    .start_frame          = &vaapi_mpeg4_start_frame,
+    .end_frame            = &vaapi_mpeg4_end_frame,
+    .decode_slice         = &vaapi_mpeg4_decode_slice,
+    .frame_priv_data_size = sizeof(VAAPIDecodePicture),
+    .init                 = &ff_vaapi_decode_init,
+    .uninit               = &ff_vaapi_decode_uninit,
+    .priv_data_size       = sizeof(VAAPIDecodeContext),
 };
 #endif
-- 
2.11.0


More information about the ffmpeg-devel mailing list