---
Here's a go at MPEG-4 part 2.

This is not tested, because I don't have anything which supports it.  (I 
thought it worked on AMD with gallium/mesa, but the driver here does not 
declare support for it - I haven't pursued that further, maybe it's possible 
somehow.)

I'm also wondering whether it even works.  Does anyone know what hardware this 
was tested on, if any?

For example, we have (in the current code):

    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;

To me that looks wrong for any height which has multiple macroblock lines in 
each GOB but the last GOB has fewer lines.

For example: height = 720, mb_height = 45, GOB height = 2 (height is in 
(400,800]), so the GOB count should be ceil(45/2) = 23 but num_gobs_in_vop here 
is 22?

 libavcodec/vaapi_mpeg4.c | 215 +++++++++++++++++++++++++++++------------------
 1 file changed, 133 insertions(+), 82 deletions(-)

diff --git a/libavcodec/vaapi_mpeg4.c b/libavcodec/vaapi_mpeg4.c
index 6743e2a..4413cbf 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,82 +45,116 @@ 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;
-    struct vaapi_context * const vactx = avctx->hwaccel_context;
-    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;
-    VASliceParameterBufferMPEG4 *slice_param;
+    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
@@ -130,40 +164,57 @@ static int vaapi_mpeg4_decode_slice(AVCodecContext 
*avctx, const uint8_t *buffer
     if (avctx->codec->id == AV_CODEC_ID_H263)
         size = s->gb.buffer_end - buffer;

-    /* Fill in VASliceParameterBufferMPEG4 */
-    slice_param = (VASliceParameterBufferMPEG4 
*)ff_vaapi_alloc_slice(avctx->hwaccel_context, buffer, size);
-    if (!slice_param)
-        return -1;
-    slice_param->macroblock_offset      = get_bits_count(&s->gb) % 8;
-    slice_param->macroblock_number      = s->mb_y * s->mb_width + s->mb_x;
-    slice_param->quant_scale            = s->qscale;
+    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,
+    .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,
+    .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.8.1

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to