mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 09:10:36 +00:00
v4l2codecs: h264: Add API checks
Check that the V4L2 H264 controls' sizes match our expectation. If not, then probably there's an API mismatch which will cause errors or decoding corruption. Also, print a warning if the kernel version is too old. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1624>
This commit is contained in:
parent
7d6b06ca1b
commit
010565eb7f
3 changed files with 110 additions and 0 deletions
|
@ -26,6 +26,12 @@
|
|||
#include "gstv4l2codecpool.h"
|
||||
#include "linux/v4l2-controls.h"
|
||||
|
||||
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
|
||||
|
||||
#define V4L2_MIN_KERNEL_VER_MAJOR 5
|
||||
#define V4L2_MIN_KERNEL_VER_MINOR 11
|
||||
#define V4L2_MIN_KERNEL_VERSION KERNEL_VERSION(V4L2_MIN_KERNEL_VER_MAJOR, V4L2_MIN_KERNEL_VER_MINOR, 0)
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (v4l2_h264dec_debug);
|
||||
#define GST_CAT_DEFAULT v4l2_h264dec_debug
|
||||
|
||||
|
@ -109,10 +115,62 @@ needs_start_codes (GstV4l2CodecH264Dec * self)
|
|||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
gst_v4l2_decoder_h264_api_check (GstV4l2CodecH264Dec * self)
|
||||
{
|
||||
guint i, ret_size;
|
||||
/* *INDENT-OFF* */
|
||||
struct
|
||||
{
|
||||
unsigned int id;
|
||||
unsigned int size;
|
||||
} controls[] = {
|
||||
{
|
||||
.id = V4L2_CID_MPEG_VIDEO_H264_SPS,
|
||||
.size = sizeof(struct v4l2_ctrl_h264_sps),
|
||||
}, {
|
||||
.id = V4L2_CID_MPEG_VIDEO_H264_PPS,
|
||||
.size = sizeof(struct v4l2_ctrl_h264_pps),
|
||||
}, {
|
||||
.id = V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX,
|
||||
.size = sizeof(struct v4l2_ctrl_h264_scaling_matrix),
|
||||
}, {
|
||||
.id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS,
|
||||
.size = sizeof(struct v4l2_ctrl_h264_decode_params),
|
||||
}, {
|
||||
.id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS,
|
||||
.size = sizeof(struct v4l2_ctrl_h264_slice_params),
|
||||
}, {
|
||||
.id = V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS,
|
||||
.size = sizeof(struct v4l2_ctrl_h264_pred_weights),
|
||||
}
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
* Compatibility check: make sure the pointer controls are
|
||||
* 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));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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[] = {
|
||||
{
|
||||
|
@ -131,6 +189,20 @@ 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,
|
||||
|
|
|
@ -74,6 +74,7 @@ struct _GstV4l2Decoder
|
|||
gint video_fd;
|
||||
GstQueueArray *request_pool;
|
||||
GstQueueArray *pending_requests;
|
||||
guint version;
|
||||
|
||||
enum v4l2_buf_type src_buf_type;
|
||||
enum v4l2_buf_type sink_buf_type;
|
||||
|
@ -148,6 +149,12 @@ gst_v4l2_decoder_new (GstV4l2CodecDevice * device)
|
|||
return gst_object_ref_sink (decoder);
|
||||
}
|
||||
|
||||
guint
|
||||
gst_v4l2_decoder_get_version (GstV4l2Decoder * self)
|
||||
{
|
||||
return self->version;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_v4l2_decoder_open (GstV4l2Decoder * self)
|
||||
{
|
||||
|
@ -176,6 +183,8 @@ gst_v4l2_decoder_open (GstV4l2Decoder * self)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
self->version = querycap.version;
|
||||
|
||||
if (querycap.capabilities & V4L2_CAP_DEVICE_CAPS)
|
||||
capabilities = querycap.device_caps;
|
||||
else
|
||||
|
@ -717,6 +726,29 @@ gst_v4l2_decoder_get_controls (GstV4l2Decoder * self,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_v4l2_decoder_query_control_size (GstV4l2Decoder * self,
|
||||
unsigned int control_id, unsigned int *control_size)
|
||||
{
|
||||
gint ret;
|
||||
struct v4l2_query_ext_ctrl control = {
|
||||
.id = control_id,
|
||||
};
|
||||
|
||||
*control_size = 0;
|
||||
|
||||
ret = ioctl (self->video_fd, VIDIOC_QUERY_EXT_CTRL, &control);
|
||||
if (ret < 0)
|
||||
/*
|
||||
* It's not an error if a control is not supported by this driver.
|
||||
* Return false but don't print any error.
|
||||
*/
|
||||
return FALSE;
|
||||
|
||||
*control_size = control.elem_size;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gst_v4l2_decoder_install_properties (GObjectClass * gobject_class,
|
||||
gint prop_offset, GstV4l2CodecDevice * device)
|
||||
|
|
|
@ -35,6 +35,8 @@ typedef struct _GstV4l2Request GstV4l2Request;
|
|||
|
||||
GstV4l2Decoder * gst_v4l2_decoder_new (GstV4l2CodecDevice * device);
|
||||
|
||||
guint gst_v4l2_decoder_get_version (GstV4l2Decoder * self);
|
||||
|
||||
gboolean gst_v4l2_decoder_open (GstV4l2Decoder * decoder);
|
||||
|
||||
gboolean gst_v4l2_decoder_close (GstV4l2Decoder * decoder);
|
||||
|
@ -81,6 +83,10 @@ gboolean gst_v4l2_decoder_get_controls (GstV4l2Decoder * self,
|
|||
struct v4l2_ext_control * control,
|
||||
guint count);
|
||||
|
||||
gboolean gst_v4l2_decoder_query_control_size (GstV4l2Decoder * self,
|
||||
unsigned int control_id,
|
||||
unsigned int *control_size);
|
||||
|
||||
void gst_v4l2_decoder_install_properties (GObjectClass * gobject_class,
|
||||
gint prop_offset,
|
||||
GstV4l2CodecDevice * device);
|
||||
|
|
Loading…
Reference in a new issue