From d7d8fc744b5893dc631c474600e41b285cf7d05f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 11 Jul 2018 16:18:18 +0200 Subject: [PATCH] Abstract away MPEG2 support Signed-off-by: Maxime Ripard Signed-off-by: Paul Kocialkowski --- src/mpeg2.c | 78 +++++++++++++++++-------------------- src/mpeg2.h | 9 +---- src/picture.c | 106 ++++++++++++++++++++++++++++---------------------- src/surface.c | 2 +- src/surface.h | 7 +++- 5 files changed, 104 insertions(+), 98 deletions(-) diff --git a/src/mpeg2.c b/src/mpeg2.c index acb200d..06481ea 100644 --- a/src/mpeg2.c +++ b/src/mpeg2.c @@ -34,63 +34,55 @@ #include -int mpeg2_fill_picture_parameters(struct sunxi_cedrus_driver_data *driver_data, - struct object_context *context_object, - struct object_surface *surface_object, - VAPictureParameterBufferMPEG2 *parameters) +#include "v4l2.h" + +int mpeg2_set_controls(struct sunxi_cedrus_driver_data *driver_data, + struct object_surface *surface_object) { - struct v4l2_ctrl_mpeg2_slice_params *slice_params = &surface_object->mpeg2_slice_params; + VAPictureParameterBufferMPEG2 *parameters = &surface_object->params.mpeg2.picture; + struct v4l2_ctrl_mpeg2_slice_params slice_params; struct object_surface *forward_reference_surface; struct object_surface *backward_reference_surface; + int rc; - slice_params->width = context_object->picture_width; - slice_params->height = context_object->picture_height; + memset(&slice_params, 0, sizeof(slice_params)); - slice_params->slice_type = parameters->picture_coding_type; - slice_params->f_code[0][0] = (parameters->f_code >> 12) & 0x0f; - slice_params->f_code[0][1] = (parameters->f_code >> 8) & 0x0f; - slice_params->f_code[1][0] = (parameters->f_code >> 4) & 0x0f; - slice_params->f_code[1][1] = (parameters->f_code >> 0) & 0x0f; + slice_params.width = surface_object->width; + slice_params.height = surface_object->height; - slice_params->intra_dc_precision = parameters->picture_coding_extension.bits.intra_dc_precision; - slice_params->picture_structure = parameters->picture_coding_extension.bits.picture_structure; - slice_params->top_field_first = parameters->picture_coding_extension.bits.top_field_first; - slice_params->frame_pred_frame_dct = parameters->picture_coding_extension.bits.frame_pred_frame_dct; - slice_params->concealment_motion_vectors = parameters->picture_coding_extension.bits.concealment_motion_vectors; - slice_params->q_scale_type = parameters->picture_coding_extension.bits.q_scale_type; - slice_params->intra_vlc_format = parameters->picture_coding_extension.bits.intra_vlc_format; - slice_params->alternate_scan = parameters->picture_coding_extension.bits.alternate_scan; + slice_params.slice_pos = 0; + slice_params.slice_len = surface_object->slices_size * 8; + + slice_params.slice_type = parameters->picture_coding_type; + slice_params.f_code[0][0] = (parameters->f_code >> 12) & 0x0f; + slice_params.f_code[0][1] = (parameters->f_code >> 8) & 0x0f; + slice_params.f_code[1][0] = (parameters->f_code >> 4) & 0x0f; + slice_params.f_code[1][1] = (parameters->f_code >> 0) & 0x0f; + + slice_params.intra_dc_precision = parameters->picture_coding_extension.bits.intra_dc_precision; + slice_params.picture_structure = parameters->picture_coding_extension.bits.picture_structure; + slice_params.top_field_first = parameters->picture_coding_extension.bits.top_field_first; + slice_params.frame_pred_frame_dct = parameters->picture_coding_extension.bits.frame_pred_frame_dct; + slice_params.concealment_motion_vectors = parameters->picture_coding_extension.bits.concealment_motion_vectors; + slice_params.q_scale_type = parameters->picture_coding_extension.bits.q_scale_type; + slice_params.intra_vlc_format = parameters->picture_coding_extension.bits.intra_vlc_format; + slice_params.alternate_scan = parameters->picture_coding_extension.bits.alternate_scan; forward_reference_surface = SURFACE(parameters->forward_reference_picture); if (forward_reference_surface != NULL) - slice_params->forward_ref_index = forward_reference_surface->destination_index; + slice_params.forward_ref_index = forward_reference_surface->destination_index; else - slice_params->forward_ref_index = surface_object->destination_index; + slice_params.forward_ref_index = surface_object->destination_index; backward_reference_surface = SURFACE(parameters->backward_reference_picture); if (backward_reference_surface != NULL) - slice_params->backward_ref_index = backward_reference_surface->destination_index; + slice_params.backward_ref_index = backward_reference_surface->destination_index; else - slice_params->backward_ref_index = surface_object->destination_index; - - return 0; -} - -int mpeg2_fill_slice_data(struct sunxi_cedrus_driver_data *driver_data, - struct object_context *context_object, - struct object_surface *surface_object, void *data, unsigned int size) -{ - unsigned char *p = (unsigned char *) surface_object->source_data + - surface_object->slices_size; - - /* - * Since there is no guarantee that the allocation order is the same as - * the submission order (via RenderPicture), we can't use a V4L2 buffer - * directly and have to copy from a regular buffer. - * */ - memcpy(p, data, size); - - surface_object->slices_size += size; + slice_params.backward_ref_index = surface_object->destination_index; + + rc = v4l2_set_control(driver_data->video_fd, surface_object->request_fd, V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS, &slice_params, sizeof(slice_params)); + if (rc < 0) + return VA_STATUS_ERROR_OPERATION_FAILED; return 0; } diff --git a/src/mpeg2.h b/src/mpeg2.h index eb149fe..e665cf5 100644 --- a/src/mpeg2.h +++ b/src/mpeg2.h @@ -33,12 +33,7 @@ #include "surface.h" -int mpeg2_fill_picture_parameters(struct sunxi_cedrus_driver_data *driver_data, - struct object_context *context_object, - struct object_surface *surface_object, - VAPictureParameterBufferMPEG2 *parameters); -int mpeg2_fill_slice_data(struct sunxi_cedrus_driver_data *driver_data, - struct object_context *context_object, - struct object_surface *surface_object, void *data, unsigned int size); +int mpeg2_set_controls(struct sunxi_cedrus_driver_data *driver_data, + struct object_surface *surface_object); #endif diff --git a/src/picture.c b/src/picture.c index 51ca8e8..37131bb 100644 --- a/src/picture.c +++ b/src/picture.c @@ -45,6 +45,60 @@ #include "media.h" #include "utils.h" +static VAStatus codec_store_buffer(struct sunxi_cedrus_driver_data *driver_data, + VAProfile profile, struct object_surface *surface_object, + struct object_buffer *buffer_object) +{ + switch (buffer_object->type) { + case VASliceDataBufferType: + /* + * Since there is no guarantee that the allocation + * order is the same as the submission order (via + * RenderPicture), we can't use a V4L2 buffer directly + * and have to copy from a regular buffer. + */ + memcpy(surface_object->source_data + surface_object->slices_size, buffer_object->data, buffer_object->size * buffer_object->count); + surface_object->slices_size += buffer_object->size * buffer_object->count; + break; + + case VAPictureParameterBufferType: + switch (profile) { + case VAProfileMPEG2Simple: + case VAProfileMPEG2Main: + memcpy(&surface_object->params.mpeg2.picture, buffer_object->data, sizeof(surface_object->params.mpeg2.picture)); + break; + default: + break; + } + break; + + default: + break; + } + + return VA_STATUS_SUCCESS; +} + +static VAStatus codec_set_controls(struct sunxi_cedrus_driver_data *driver_data, + VAProfile profile, struct object_surface *surface_object) +{ + int rc; + + switch (profile) { + case VAProfileMPEG2Simple: + case VAProfileMPEG2Main: + rc = mpeg2_set_controls(driver_data, surface_object); + if (rc < 0) + return VA_STATUS_ERROR_OPERATION_FAILED; + break; + + default: + return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; + } + + return VA_STATUS_SUCCESS; +} + VAStatus SunxiCedrusBeginPicture(VADriverContextP context, VAContextID context_id, VASurfaceID surface_id) { @@ -79,9 +133,6 @@ VAStatus SunxiCedrusRenderPicture(VADriverContextP context, struct object_config *config_object; struct object_surface *surface_object; struct object_buffer *buffer_object; - VAPictureParameterBufferMPEG2 *mpeg2_parameters; - void *data; - unsigned int size; int rc; int i; @@ -102,28 +153,9 @@ VAStatus SunxiCedrusRenderPicture(VADriverContextP context, if (buffer_object == NULL) return VA_STATUS_ERROR_INVALID_BUFFER; - switch (config_object->profile) { - case VAProfileMPEG2Simple: - case VAProfileMPEG2Main: - if (buffer_object->type == VASliceDataBufferType) { - data = buffer_object->data; - size = buffer_object->size * buffer_object->count; - - rc = mpeg2_fill_slice_data(driver_data, context_object, surface_object, data, size); - if (rc < 0) - return VA_STATUS_ERROR_OPERATION_FAILED; - } else if (buffer_object->type == VAPictureParameterBufferType) { - mpeg2_parameters = (VAPictureParameterBufferMPEG2 *) buffer_object->data; - - rc = mpeg2_fill_picture_parameters(driver_data, context_object, surface_object, mpeg2_parameters); - if (rc < 0) - return VA_STATUS_ERROR_OPERATION_FAILED; - } - break; - - default: - break; - } + rc = codec_store_buffer(driver_data, config_object->profile, surface_object, buffer_object); + if (rc != VA_STATUS_SUCCESS) + return rc; } return VA_STATUS_SUCCESS; @@ -137,9 +169,6 @@ VAStatus SunxiCedrusEndPicture(VADriverContextP context, struct object_context *context_object; struct object_config *config_object; struct object_surface *surface_object; - void *control_data; - unsigned int control_size; - unsigned int control_id; int request_fd; VAStatus status; int rc; @@ -165,24 +194,9 @@ VAStatus SunxiCedrusEndPicture(VADriverContextP context, surface_object->request_fd = request_fd; } - switch (config_object->profile) { - case VAProfileMPEG2Simple: - case VAProfileMPEG2Main: - surface_object->mpeg2_slice_params.slice_pos = 0; - surface_object->mpeg2_slice_params.slice_len = surface_object->slices_size * 8; - - control_id = V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS; - control_data = &surface_object->mpeg2_slice_params; - control_size = sizeof(surface_object->mpeg2_slice_params); - break; - - default: - return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; - } - - rc = v4l2_set_control(driver_data->video_fd, request_fd, control_id, control_data, control_size); - if (rc < 0) - return VA_STATUS_ERROR_OPERATION_FAILED; + rc = codec_set_controls(driver_data, config_object->profile, surface_object); + if (rc != VA_STATUS_SUCCESS) + return rc; rc = v4l2_queue_buffer(driver_data->video_fd, -1, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, surface_object->destination_index, 0, surface_object->destination_buffers_count); if (rc < 0) diff --git a/src/surface.c b/src/surface.c index c28b75f..3fd383d 100644 --- a/src/surface.c +++ b/src/surface.c @@ -129,7 +129,7 @@ VAStatus SunxiCedrusCreateSurfaces(VADriverContextP context, int width, surface_object->destination_planes_count = destination_planes_count; surface_object->destination_buffers_count = video_format->v4l2_buffers_count; - memset(&surface_object->mpeg2_slice_params, 0, sizeof(surface_object->mpeg2_slice_params)); + memset(&surface_object->params, 0, sizeof(surface_object->params)); surface_object->slices_size = 0; surface_object->request_fd = -1; diff --git a/src/surface.h b/src/surface.h index b749c58..d4765d2 100644 --- a/src/surface.h +++ b/src/surface.h @@ -57,9 +57,14 @@ struct object_surface { unsigned int destination_planes_count; unsigned int destination_buffers_count; - struct v4l2_ctrl_mpeg2_slice_params mpeg2_slice_params; unsigned int slices_size; + union { + struct { + VAPictureParameterBufferMPEG2 picture; + } mpeg2; + } params; + int request_fd; };