h264: Fix prediction weight table

The current code sets the prediction weight table by doing a memcpy of the
libva structure to the v4l2's structure.

However, for the offset and weight parameters, libva's structure uses
16-bits integer, while v4l2 uses 8-bits, which obviously doesn't work well
with memcpy.

Create a function to copy those arrays and matrices instead that follows
the algorithm defined in the H264 spec, and use it so that it works
properly.

Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
This commit is contained in:
Maxime Ripard
2018-07-17 14:42:13 +02:00
parent e7c09a336f
commit 1fca951c05
+37 -20
View File
@@ -294,14 +294,34 @@ static void h264_va_matrix_to_v4l2(struct cedrus_data *driver_data,
sizeof(v4l2_matrix->scaling_list_8x8[3])); sizeof(v4l2_matrix->scaling_list_8x8[3]));
} }
static void h264_copy_pred_table(struct v4l2_h264_weight_factors *factors,
unsigned int num_refs,
int16_t luma_weight[32],
int16_t luma_offset[32],
int16_t chroma_weight[32][2],
int16_t chroma_offset[32][2])
{
unsigned int i;
for (i = 0; i < num_refs; i++) {
unsigned int j;
factors->luma_weight[i] = luma_weight[i];
factors->luma_offset[i] = luma_offset[i];
for (j = 0; j < 2; j++) {
factors->chroma_weight[i][j] = chroma_weight[i][j];
factors->chroma_offset[i][j] = chroma_offset[i][j];
}
}
}
static void h264_va_slice_to_v4l2(struct cedrus_data *driver_data, static void h264_va_slice_to_v4l2(struct cedrus_data *driver_data,
struct object_context *context, struct object_context *context,
VASliceParameterBufferH264 *VASlice, VASliceParameterBufferH264 *VASlice,
VAPictureParameterBufferH264 *VAPicture, VAPictureParameterBufferH264 *VAPicture,
struct v4l2_ctrl_h264_slice_param *slice) struct v4l2_ctrl_h264_slice_param *slice)
{ {
struct v4l2_h264_weight_factors *factors;
slice->size = VASlice->slice_data_size; slice->size = VASlice->slice_data_size;
slice->header_bit_size = VASlice->slice_data_bit_offset; slice->header_bit_size = VASlice->slice_data_bit_offset;
slice->first_mb_in_slice = VASlice->first_mb_in_slice; slice->first_mb_in_slice = VASlice->first_mb_in_slice;
@@ -360,25 +380,22 @@ static void h264_va_slice_to_v4l2(struct cedrus_data *driver_data,
slice->pred_weight_table.luma_log2_weight_denom = slice->pred_weight_table.luma_log2_weight_denom =
VASlice->luma_log2_weight_denom; VASlice->luma_log2_weight_denom;
factors = &slice->pred_weight_table.weight_factors[0]; if (((VASlice->slice_type % 5) == H264_SLICE_P) ||
memcpy(&factors->chroma_weight, &VASlice->chroma_weight_l0, ((VASlice->slice_type % 5) == H264_SLICE_B))
sizeof(factors->chroma_weight)); h264_copy_pred_table(&slice->pred_weight_table.weight_factors[0],
memcpy(&factors->chroma_offset, &VASlice->chroma_offset_l0, slice->num_ref_idx_l0_active_minus1 + 1,
sizeof(factors->chroma_offset)); VASlice->luma_weight_l0,
memcpy(&factors->luma_weight, &VASlice->luma_weight_l0, VASlice->luma_offset_l0,
sizeof(factors->luma_weight)); VASlice->chroma_weight_l0,
memcpy(&factors->luma_offset, &VASlice->luma_offset_l0, VASlice->chroma_offset_l0);
sizeof(factors->luma_offset));
factors = &slice->pred_weight_table.weight_factors[1]; if ((VASlice->slice_type % 5) == H264_SLICE_B)
memcpy(&factors->chroma_weight, &VASlice->chroma_weight_l1, h264_copy_pred_table(&slice->pred_weight_table.weight_factors[1],
sizeof(factors->chroma_weight)); slice->num_ref_idx_l1_active_minus1 + 1,
memcpy(&factors->chroma_offset, &VASlice->chroma_offset_l1, VASlice->luma_weight_l1,
sizeof(factors->chroma_offset)); VASlice->luma_offset_l1,
memcpy(&factors->luma_weight, &VASlice->luma_weight_l1, VASlice->chroma_weight_l1,
sizeof(factors->luma_weight)); VASlice->chroma_offset_l1);
memcpy(&factors->luma_offset, &VASlice->luma_offset_l1,
sizeof(factors->luma_offset));
} }
int h264_set_controls(struct cedrus_data *driver_data, int h264_set_controls(struct cedrus_data *driver_data,