v4l2codecs: h264: Implement optional scaling matrix

The new H.264 uAPI requires that all drivers support
scaling matrix only as an option, when a non-flat
scaling matrix is provided in the bitstream headers.

Take advantage of this and avoid passing the scaling
matrix if not needed.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1624>
This commit is contained in:
Ezequiel Garcia 2020-08-14 10:13:09 -03:00 committed by GStreamer Merge Bot
parent 78756ecba9
commit 1c082b79e1

View file

@ -76,6 +76,7 @@ struct _GstV4l2CodecH264Dec
gboolean need_negotiation; gboolean need_negotiation;
gboolean need_sequence; gboolean need_sequence;
gboolean copy_frames; gboolean copy_frames;
gboolean scaling_matrix_present;
struct v4l2_ctrl_h264_sps sps; struct v4l2_ctrl_h264_sps sps;
struct v4l2_ctrl_h264_pps pps; struct v4l2_ctrl_h264_pps pps;
@ -491,7 +492,7 @@ gst_v4l2_codec_h264_dec_fill_pps (GstV4l2CodecH264Dec * self, GstH264PPS * pps)
| (pps->constrained_intra_pred_flag ? V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED : 0) | (pps->constrained_intra_pred_flag ? V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED : 0)
| (pps->redundant_pic_cnt_present_flag ? V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT : 0) | (pps->redundant_pic_cnt_present_flag ? V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT : 0)
| (pps->transform_8x8_mode_flag ? V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE : 0) | (pps->transform_8x8_mode_flag ? V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE : 0)
| V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT, | (self->scaling_matrix_present ? V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT : 0),
}; };
/* *INDENT-ON* */ /* *INDENT-ON* */
} }
@ -865,8 +866,20 @@ gst_v4l2_codec_h264_dec_start_picture (GstH264Decoder * decoder,
if (!gst_v4l2_codec_h264_dec_ensure_bitstream (self)) if (!gst_v4l2_codec_h264_dec_ensure_bitstream (self))
return FALSE; return FALSE;
/*
* Scaling matrix is present if there's one provided
* by either the SPS or the PPS. This flag must be
* set to true or false, before filling the PPS V4L2 control.
*/
self->scaling_matrix_present =
slice->header.pps->sequence->scaling_matrix_present_flag ||
slice->header.pps->pic_scaling_matrix_present_flag;
gst_v4l2_codec_h264_dec_fill_pps (self, slice->header.pps); gst_v4l2_codec_h264_dec_fill_pps (self, slice->header.pps);
gst_v4l2_codec_h264_dec_fill_scaling_matrix (self, slice->header.pps);
if (self->scaling_matrix_present)
gst_v4l2_codec_h264_dec_fill_scaling_matrix (self, slice->header.pps);
gst_v4l2_codec_h264_dec_fill_decoder_params (self, &slice->header, picture, gst_v4l2_codec_h264_dec_fill_decoder_params (self, &slice->header, picture,
dpb); dpb);
@ -1023,11 +1036,6 @@ gst_v4l2_codec_h264_dec_submit_bitstream (GstV4l2CodecH264Dec * self,
.ptr = &self->pps, .ptr = &self->pps,
.size = sizeof (self->pps), .size = sizeof (self->pps),
}, },
{
.id = V4L2_CID_STATELESS_H264_SCALING_MATRIX,
.ptr = &self->scaling_matrix,
.size = sizeof (self->scaling_matrix),
},
{ {
.id = V4L2_CID_STATELESS_H264_DECODE_PARAMS, .id = V4L2_CID_STATELESS_H264_DECODE_PARAMS,
.ptr = &self->decode_params, .ptr = &self->decode_params,
@ -1036,6 +1044,7 @@ gst_v4l2_codec_h264_dec_submit_bitstream (GstV4l2CodecH264Dec * self,
{ }, { },
{ }, { },
{ }, { },
{ },
}; };
/* *INDENT-ON* */ /* *INDENT-ON* */
@ -1071,8 +1080,8 @@ gst_v4l2_codec_h264_dec_submit_bitstream (GstV4l2CodecH264Dec * self,
goto done; goto done;
} }
/* Always set PPS, SCALING_MATRIX and DECODE_PARAMS */ /* Always set PPS and DECODE_PARAMS */
count = 3; count = 2;
if (self->need_sequence) { if (self->need_sequence) {
control[count].id = V4L2_CID_STATELESS_H264_SPS; control[count].id = V4L2_CID_STATELESS_H264_SPS;
@ -1082,6 +1091,13 @@ gst_v4l2_codec_h264_dec_submit_bitstream (GstV4l2CodecH264Dec * self,
self->need_sequence = FALSE; self->need_sequence = FALSE;
} }
if (self->scaling_matrix_present) {
control[count].id = V4L2_CID_STATELESS_H264_SCALING_MATRIX;
control[count].ptr = &self->scaling_matrix;
control[count].size = sizeof (self->scaling_matrix);
count++;
}
/* If it's not slice-based then it doesn't support per-slice controls. */ /* If it's not slice-based then it doesn't support per-slice controls. */
if (is_slice_based (self)) { if (is_slice_based (self)) {
control[count].id = V4L2_CID_STATELESS_H264_SLICE_PARAMS; control[count].id = V4L2_CID_STATELESS_H264_SLICE_PARAMS;