v4l2codecs: h264: Improve ABI check

This moves the ABI check to the registration, so we don't expose
decoders with the wrong ABI or that are just broken somehow. It
also makes few enhancement:

- Handle missing, but required controls
- Prints the controls macro name instead of id

This should fix RK3399 support with a currently release minor
regression in the Hantro driver that cause errors.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1599>
This commit is contained in:
Nicolas Dufresne 2022-01-28 14:39:35 -05:00 committed by GStreamer Marge Bot
parent 4254920b72
commit 47bfa71530

View file

@ -118,37 +118,42 @@ needs_start_codes (GstV4l2CodecH264Dec * self)
return self->start_code == V4L2_STATELESS_H264_START_CODE_ANNEX_B;
}
static gboolean
gst_v4l2_decoder_h264_api_check (GstV4l2CodecH264Dec * self)
gst_v4l2_decoder_h264_api_check (GstV4l2Decoder * decoder)
{
guint i, ret_size;
/* *INDENT-OFF* */
#define SET_ID(cid) .id = (cid), .name = #cid
struct
{
const gchar *name;
unsigned int id;
unsigned int size;
gboolean optional;
} controls[] = {
{
.id = V4L2_CID_STATELESS_H264_SPS,
SET_ID (V4L2_CID_STATELESS_H264_SPS),
.size = sizeof(struct v4l2_ctrl_h264_sps),
}, {
.id = V4L2_CID_STATELESS_H264_PPS,
SET_ID (V4L2_CID_STATELESS_H264_PPS),
.size = sizeof(struct v4l2_ctrl_h264_pps),
}, {
.id = V4L2_CID_STATELESS_H264_SCALING_MATRIX,
SET_ID (V4L2_CID_STATELESS_H264_SCALING_MATRIX),
.size = sizeof(struct v4l2_ctrl_h264_scaling_matrix),
}, {
.id = V4L2_CID_STATELESS_H264_DECODE_PARAMS,
SET_ID (V4L2_CID_STATELESS_H264_DECODE_PARAMS),
.size = sizeof(struct v4l2_ctrl_h264_decode_params),
}, {
.id = V4L2_CID_STATELESS_H264_SLICE_PARAMS,
SET_ID (V4L2_CID_STATELESS_H264_SLICE_PARAMS),
.size = sizeof(struct v4l2_ctrl_h264_slice_params),
.optional = TRUE,
}, {
.id = V4L2_CID_STATELESS_H264_PRED_WEIGHTS,
SET_ID (V4L2_CID_STATELESS_H264_PRED_WEIGHTS),
.size = sizeof(struct v4l2_ctrl_h264_pred_weights),
.optional = TRUE,
}
};
#undef SET_ID
/* *INDENT-ON* */
/*
@ -156,12 +161,19 @@ gst_v4l2_decoder_h264_api_check (GstV4l2CodecH264Dec * self)
* the right size.
*/
for (i = 0; i < G_N_ELEMENTS (controls); i++) {
if (gst_v4l2_decoder_query_control_size (self->decoder, controls[i].id,
&ret_size) && ret_size != controls[i].size) {
GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ_WRITE,
("H264 API mismatch!"),
("%d control size mismatch: got %d bytes but %d expected.",
controls[i].id, ret_size, controls[i].size));
gboolean control_found;
control_found = gst_v4l2_decoder_query_control_size (decoder,
controls[i].id, &ret_size);
if (!controls[i].optional && !control_found) {
GST_WARNING ("Driver is missing %s support.", controls[i].name);
return FALSE;
}
if (control_found && ret_size != controls[i].size) {
GST_WARNING ("%s control size mismatch: got %d bytes but %d expected.",
controls[i].name, ret_size, controls[i].size);
return FALSE;
}
}
@ -173,7 +185,6 @@ static gboolean
gst_v4l2_codec_h264_dec_open (GstVideoDecoder * decoder)
{
GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
guint version;
/* *INDENT-OFF* */
struct v4l2_ext_control control[] = {
@ -193,20 +204,6 @@ gst_v4l2_codec_h264_dec_open (GstVideoDecoder * decoder)
return FALSE;
}
version = gst_v4l2_decoder_get_version (self->decoder);
if (version < V4L2_MIN_KERNEL_VERSION)
GST_WARNING_OBJECT (self,
"V4L2 API v%u.%u too old, at least v%u.%u required",
(version >> 16) & 0xff, (version >> 8) & 0xff,
V4L2_MIN_KERNEL_VER_MAJOR, V4L2_MIN_KERNEL_VER_MINOR);
if (!gst_v4l2_decoder_h264_api_check (self)) {
GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ_WRITE,
("Failed to open H264 decoder"),
("gst_v4l2_decoder_h264_api_check() failed"));
return FALSE;
}
if (!gst_v4l2_decoder_get_controls (self->decoder, control,
G_N_ELEMENTS (control))) {
GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ_WRITE,
@ -1520,6 +1517,7 @@ gst_v4l2_codec_h264_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
GstV4l2CodecDevice * device, guint rank)
{
GstCaps *src_caps;
guint version;
GST_DEBUG_CATEGORY_INIT (v4l2_h264dec_debug, "v4l2codecs-h264dec", 0,
"V4L2 stateless h264 decoder");
@ -1535,6 +1533,17 @@ gst_v4l2_codec_h264_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
goto done;
}
version = gst_v4l2_decoder_get_version (decoder);
if (version < V4L2_MIN_KERNEL_VERSION)
GST_WARNING ("V4L2 API v%u.%u too old, at least v%u.%u required",
(version >> 16) & 0xff, (version >> 8) & 0xff,
V4L2_MIN_KERNEL_VER_MAJOR, V4L2_MIN_KERNEL_VER_MINOR);
if (!gst_v4l2_decoder_h264_api_check (decoder)) {
GST_WARNING ("Not registering H264 decoder as it failed ABI check.");
goto done;
}
gst_v4l2_decoder_register (plugin,
GST_TYPE_V4L2_CODEC_H264_DEC,
(GClassInitFunc) gst_v4l2_codec_h264_dec_subclass_init,