v4l2: Add support for setting memory:DMABuf caps

This is the final step to allow negotiation of this caps features. Limiting the
features based on the io-mode shall come next.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7633>
This commit is contained in:
Nicolas Dufresne 2024-08-22 16:08:03 -04:00 committed by GStreamer Marge Bot
parent 58b196d62b
commit 77744c3d63
7 changed files with 306 additions and 178 deletions

View file

@ -449,7 +449,7 @@ gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
GstVideoInfo *info;
obj = pool->obj;
info = &obj->info;
info = &obj->info.vinfo;
switch (obj->mode) {
case GST_V4L2_IO_RW:
@ -622,8 +622,8 @@ gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
}
/* Always update the config to ensure the configured size matches */
gst_buffer_pool_config_set_params (config, caps, obj->info.size, min_buffers,
max_buffers);
gst_buffer_pool_config_set_params (config, caps, obj->info.vinfo.size,
min_buffers, max_buffers);
/* keep a GstVideoInfo with defaults for the when we need to copy */
gst_video_info_from_caps (&pool->caps_info, caps);
@ -1244,7 +1244,7 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer,
GstV4l2Object *obj = pool->obj;
GstClockTime timestamp;
GstV4l2MemoryGroup *group;
const GstVideoInfo *info = &obj->info;
const GstVideoInfo *info = &obj->info.vinfo;
gint i;
gint old_buffer_state;
@ -1797,7 +1797,7 @@ gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps)
gst_object_ref (obj->element);
config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
gst_buffer_pool_config_set_params (config, caps, obj->info.size, 0, 0);
gst_buffer_pool_config_set_params (config, caps, obj->info.vinfo.size, 0, 0);
/* This will simply set a default config, but will not configure the pool
* because min and max are not valid */
gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST (pool), config);
@ -1827,7 +1827,7 @@ gst_v4l2_do_read (GstV4l2BufferPool * pool, GstBuffer * buf)
GstMapInfo map;
gint toread;
toread = obj->info.size;
toread = obj->info.vinfo.size;
GST_LOG_OBJECT (pool, "reading %d bytes into buffer %p", toread, buf);

View file

@ -1443,6 +1443,31 @@ gst_v4l2_object_get_desc_from_video_format (GstVideoFormat format,
return ret;
}
static const GstV4L2FormatDesc *
gst_v4l2_object_get_desc_from_drm_fourcc (guint32 drm_fourcc,
guint64 drm_modifier, const GstV4L2FormatDesc ** fallback)
{
const GstV4L2FormatDesc *ret = NULL;
gint i;
if (fallback)
*fallback = NULL;
for (i = 0; i < GST_V4L2_FORMAT_COUNT; i++) {
if (gst_v4l2_formats[i].drm_fourcc == drm_fourcc
&& gst_v4l2_formats[i].drm_modifier == drm_modifier) {
if (!ret)
ret = &gst_v4l2_formats[i];
else if (fallback && !*fallback)
*fallback = &gst_v4l2_formats[i];
else
break;
}
}
return ret;
}
static gboolean
gst_v4l2_object_v4l2fourcc_is_codec (guint32 fourcc)
{
@ -1642,7 +1667,8 @@ gst_v4l2_object_is_raw (GstV4l2Object * v4l2object)
{
gint i;
if (GST_VIDEO_INFO_FORMAT (&v4l2object->info) != GST_VIDEO_FORMAT_ENCODED)
if (GST_VIDEO_INFO_FORMAT (&v4l2object->info.vinfo) !=
GST_VIDEO_FORMAT_ENCODED)
return TRUE;
for (i = 0; i < GST_V4L2_FORMAT_COUNT; i++) {
@ -1876,6 +1902,8 @@ gst_v4l2_object_probe_template_caps (const gchar * device, gint video_fd,
}
/* collect data for the given caps
* @v4l2object: the associated GstV4l2Object
* @info: the format information as GstVideoInfoDmaDrm
* @caps: given input caps
* @format: location for the v4l format
* @w/@h: location for width and height
@ -1884,7 +1912,7 @@ gst_v4l2_object_probe_template_caps (const gchar * device, gint video_fd,
*/
static gboolean
gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
struct v4l2_fmtdesc **format, GstVideoInfo * info)
struct v4l2_fmtdesc **format, GstVideoInfoDmaDrm * info)
{
GstStructure *structure;
guint32 fourcc = 0, fourcc_nc = 0;
@ -1895,13 +1923,27 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
mimetype = gst_structure_get_name (structure);
if (!gst_video_info_from_caps (info, caps))
if (!gst_video_info_dma_drm_from_caps (info, caps) &&
!gst_video_info_from_caps (&info->vinfo, caps))
goto invalid_format;
if (g_str_equal (mimetype, "video/x-raw")) {
const GstV4L2FormatDesc *desc, *fallback_desc;
GstVideoFormat format = GST_VIDEO_INFO_FORMAT (info);
desc = gst_v4l2_object_get_desc_from_video_format (format, &fallback_desc);
const GstV4L2FormatDesc *desc, *fallback_desc = NULL;
GstVideoFormat format = GST_VIDEO_INFO_FORMAT (&info->vinfo);
if (format == GST_VIDEO_FORMAT_DMA_DRM) {
const GstStructure *s = gst_caps_get_structure (caps, 0);
guint64 drm_modifier;
guint32 drm_fourcc =
gst_video_dma_drm_fourcc_from_string (gst_structure_get_string (s,
"drm-format"), &drm_modifier);
/* we can't support single plane fallback with opaque DRM fourcc since we
* don't know how to extrapolate the missing strides and offsets. */
desc = gst_v4l2_object_get_desc_from_drm_fourcc (drm_fourcc, drm_modifier,
NULL);
} else {
desc =
gst_v4l2_object_get_desc_from_video_format (format, &fallback_desc);
}
if (desc)
fourcc_nc = desc->v4l2_format;
if (fallback_desc)
@ -3149,11 +3191,12 @@ default_frame_sizes:
if (!v4l2object->skip_try_fmt_probes) {
gint probed_w, probed_h;
if (v4l2object->info.width >= min_w && v4l2object->info.width <= max_w &&
v4l2object->info.height >= min_h
&& v4l2object->info.height <= max_h) {
probed_w = v4l2object->info.width;
probed_h = v4l2object->info.height;
if (v4l2object->info.vinfo.width >= min_w &&
v4l2object->info.vinfo.width <= max_w &&
v4l2object->info.vinfo.height >= min_h
&& v4l2object->info.vinfo.height <= max_h) {
probed_w = v4l2object->info.vinfo.width;
probed_h = v4l2object->info.vinfo.height;
} else {
probed_w = max_w;
probed_h = max_h;
@ -3430,15 +3473,15 @@ gst_v4l2_object_extrapolate_info (GstV4l2Object * v4l2object,
static void
gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
struct v4l2_fmtdesc *fmtdesc, struct v4l2_format *format,
GstVideoInfo * info, GstVideoAlignment * align)
GstVideoInfoDmaDrm * info, GstVideoAlignment * align)
{
const GstVideoFormatInfo *finfo = info->finfo;
const GstVideoFormatInfo *finfo = info->vinfo.finfo;
gboolean standard_stride = TRUE;
gint stride, pstride, padded_width, padded_height, i;
if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_ENCODED) {
if (GST_VIDEO_INFO_FORMAT (&info->vinfo) == GST_VIDEO_FORMAT_ENCODED) {
v4l2object->n_v4l2_planes = 1;
info->size = format->fmt.pix.sizeimage;
info->vinfo.size = format->fmt.pix.sizeimage;
goto store_info;
}
@ -3455,7 +3498,7 @@ gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
/* pstride can be 0 for complex formats */
GST_WARNING_OBJECT (v4l2object->dbg_obj,
"format %s has a pstride of 0, cannot compute padded with",
gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (info)));
gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&info->vinfo)));
padded_width = format->fmt.pix.width;
}
@ -3464,7 +3507,7 @@ gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
"Driver bug detected, stride (%d) is too small for the width (%d)",
padded_width, format->fmt.pix.width);
align->padding_right = padded_width - info->width - align->padding_left;
align->padding_right = padded_width - info->vinfo.width - align->padding_left;
/* adjust bottom padding */
padded_height = format->fmt.pix.height;
@ -3477,8 +3520,8 @@ gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
(padded_height + tile_height - 1) / tile_height * tile_height;
}
align->padding_bottom =
padded_height - GST_VIDEO_INFO_FIELD_HEIGHT (info) - align->padding_top;
align->padding_bottom = padded_height -
GST_VIDEO_INFO_FIELD_HEIGHT (&info->vinfo) - align->padding_top;
/* setup the strides and offset */
if (V4L2_TYPE_IS_MULTIPLANAR (v4l2object->type)) {
@ -3486,33 +3529,40 @@ gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
/* figure out the frame layout */
v4l2object->n_v4l2_planes = MAX (1, pix_mp->num_planes);
info->size = 0;
info->vinfo.size = 0;
for (i = 0; i < v4l2object->n_v4l2_planes; i++) {
stride = pix_mp->plane_fmt[i].bytesperline;
if (info->stride[i] != stride)
if (info->vinfo.stride[i] != stride)
standard_stride = FALSE;
gst_v4l2_object_set_stride (info, align, i, stride);
info->offset[i] = info->size;
info->size += pix_mp->plane_fmt[i].sizeimage;
gst_v4l2_object_set_stride (&info->vinfo, align, i, stride);
info->vinfo.offset[i] = info->vinfo.size;
info->vinfo.size += pix_mp->plane_fmt[i].sizeimage;
}
/* Extrapolate stride if planar format are being set in 1 v4l2 plane */
if (v4l2object->n_v4l2_planes < finfo->n_planes) {
/* We should never negotiate single plane variant of formats unless the
* formats is mapped into libgstvideo, otherwise we don't know how to
* guess the missing strides and offsets. If you hit this assertion,
* please remove the mapping from V4L2 to DRM formats. */
g_assert (GST_VIDEO_INFO_FORMAT (&info->vinfo) !=
GST_VIDEO_FORMAT_UNKNOWN);
stride = format->fmt.pix_mp.plane_fmt[0].bytesperline;
gst_v4l2_object_extrapolate_info (v4l2object, info, align, stride);
gst_v4l2_object_extrapolate_info (v4l2object, &info->vinfo, align,
stride);
}
} else {
/* only one plane in non-MPLANE mode */
v4l2object->n_v4l2_planes = 1;
info->size = format->fmt.pix.sizeimage;
info->vinfo.size = format->fmt.pix.sizeimage;
stride = format->fmt.pix.bytesperline;
if (info->stride[0] != stride)
if (info->vinfo.stride[0] != stride)
standard_stride = FALSE;
gst_v4l2_object_extrapolate_info (v4l2object, info, align, stride);
gst_v4l2_object_extrapolate_info (v4l2object, &info->vinfo, align, stride);
}
/* adjust the offset to take into account left and top */
@ -3522,14 +3572,15 @@ gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
"Left and top padding is not permitted for tiled formats");
memset (v4l2object->plane_size, 0, sizeof (v4l2object->plane_size));
} else {
if (!gst_video_info_align_full (info, align, v4l2object->plane_size)) {
if (!gst_video_info_align_full (&info->vinfo, align,
v4l2object->plane_size)) {
GST_WARNING_OBJECT (v4l2object->dbg_obj, "Failed to align video info");
}
}
store_info:
GST_DEBUG_OBJECT (v4l2object->dbg_obj, "Got sizeimage %" G_GSIZE_FORMAT,
info->size);
info->vinfo.size);
/* to avoid copies we need video meta if there is padding */
v4l2object->need_video_meta =
@ -3550,10 +3601,10 @@ store_info:
v4l2object->fmtdesc = fmtdesc;
/* if we have a framerate pre-calculate duration */
if (info->fps_n > 0 && info->fps_d > 0) {
v4l2object->duration = gst_util_uint64_scale_int (GST_SECOND, info->fps_d,
info->fps_n);
if (GST_VIDEO_INFO_INTERLACE_MODE (info) ==
if (info->vinfo.fps_n > 0 && info->vinfo.fps_d > 0) {
v4l2object->duration = gst_util_uint64_scale_int (GST_SECOND,
info->vinfo.fps_d, info->vinfo.fps_n);
if (GST_VIDEO_INFO_INTERLACE_MODE (&info->vinfo) ==
GST_VIDEO_INTERLACE_MODE_ALTERNATE)
v4l2object->duration /= 2;
} else {
@ -3696,7 +3747,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
enum v4l2_field field;
guint32 pixelformat;
struct v4l2_fmtdesc *fmtdesc;
GstVideoInfo info;
GstVideoInfoDmaDrm info;
GstVideoAlignment align;
gint width, height, fps_n, fps_d;
guint pixel_bitdepth = 8;
@ -3720,7 +3771,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
is_mplane = V4L2_TYPE_IS_MULTIPLANAR (v4l2object->type);
gst_video_info_init (&info);
gst_video_info_dma_drm_init (&info);
gst_video_alignment_reset (&align);
v4l2object->transfer = GST_VIDEO_TRANSFER_UNKNOWN;
v4l2object->matrix = GST_VIDEO_COLOR_MATRIX_UNKNOWN;
@ -3729,35 +3780,43 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
goto invalid_caps;
pixelformat = fmtdesc->pixelformat;
width = GST_VIDEO_INFO_WIDTH (&info);
height = GST_VIDEO_INFO_FIELD_HEIGHT (&info);
width = GST_VIDEO_INFO_WIDTH (&info.vinfo);
height = GST_VIDEO_INFO_FIELD_HEIGHT (&info.vinfo);
/* if caps has no width and height info, use default value */
if (V4L2_TYPE_IS_OUTPUT (v4l2object->type) && width == 0 && height == 0) {
width = GST_V4L2_DEFAULT_WIDTH;
height = GST_V4L2_DEFAULT_HEIGHT;
}
fps_n = GST_VIDEO_INFO_FPS_N (&info);
fps_d = GST_VIDEO_INFO_FPS_D (&info);
fps_n = GST_VIDEO_INFO_FPS_N (&info.vinfo);
fps_d = GST_VIDEO_INFO_FPS_D (&info.vinfo);
/* if encoded format (GST_VIDEO_INFO_N_PLANES return 0)
* or if contiguous is preferred */
n_v4l_planes = GST_VIDEO_INFO_N_PLANES (&info);
if (!n_v4l_planes || !v4l2object->prefered_non_contiguous)
n_v4l_planes = GST_VIDEO_INFO_N_PLANES (&info.vinfo);
if (!n_v4l_planes) {
/* For opaque DRM format we let the driver tell us how many planes
* otherwise its an encoded format and we will have 1 plane */
if (GST_VIDEO_INFO_FORMAT (&info.vinfo) == GST_VIDEO_FORMAT_DMA_DRM)
n_v4l_planes = GST_VIDEO_MAX_PLANES;
else
n_v4l_planes = 1;
}
/* If our preference is single plane, then set te number of plane to 1 */
if (!v4l2object->prefered_non_contiguous)
n_v4l_planes = 1;
field = get_v4l2_field_for_info (&info);
field = get_v4l2_field_for_info (&info.vinfo);
if (field != V4L2_FIELD_NONE)
GST_DEBUG_OBJECT (v4l2object->dbg_obj, "interlaced video");
else
GST_DEBUG_OBJECT (v4l2object->dbg_obj, "progressive video");
/* We first pick the main colorspace from the primaries */
switch (info.colorimetry.primaries) {
switch (info.vinfo.colorimetry.primaries) {
case GST_VIDEO_COLOR_PRIMARIES_BT709:
/* There is three colorspaces using these primaries, use the range
* and format type to differentiate them */
if (info.colorimetry.range == GST_VIDEO_COLOR_RANGE_16_235) {
if (GST_VIDEO_INFO_IS_RGB (&info))
if (info.vinfo.colorimetry.range == GST_VIDEO_COLOR_RANGE_16_235) {
if (GST_VIDEO_INFO_IS_RGB (&info.vinfo))
colorspace = V4L2_COLORSPACE_SRGB;
else
colorspace = V4L2_COLORSPACE_REC709;
@ -3788,11 +3847,11 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
default:
GST_WARNING_OBJECT (v4l2object->dbg_obj,
"Unknown colorimetry primaries %d", info.colorimetry.primaries);
"Unknown colorimetry primaries %d", info.vinfo.colorimetry.primaries);
break;
}
switch (info.colorimetry.range) {
switch (info.vinfo.colorimetry.range) {
case GST_VIDEO_COLOR_RANGE_0_255:
range = V4L2_QUANTIZATION_FULL_RANGE;
break;
@ -3804,11 +3863,11 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
break;
default:
GST_WARNING_OBJECT (v4l2object->dbg_obj,
"Unknown colorimetry range %d", info.colorimetry.range);
"Unknown colorimetry range %d", info.vinfo.colorimetry.range);
break;
}
switch (info.colorimetry.matrix) {
switch (info.vinfo.colorimetry.matrix) {
case GST_VIDEO_COLOR_MATRIX_RGB:
/* save the matrix so we can restore it on get() call from default */
v4l2object->matrix = GST_VIDEO_COLOR_MATRIX_RGB;
@ -3833,11 +3892,11 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
break;
default:
GST_WARNING_OBJECT (v4l2object->dbg_obj,
"Unknown colorimetry matrix %d", info.colorimetry.matrix);
"Unknown colorimetry matrix %d", info.vinfo.colorimetry.matrix);
break;
}
switch (info.colorimetry.transfer) {
switch (info.vinfo.colorimetry.transfer) {
case GST_VIDEO_TRANSFER_GAMMA18:
case GST_VIDEO_TRANSFER_GAMMA20:
case GST_VIDEO_TRANSFER_GAMMA22:
@ -3855,7 +3914,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
case GST_VIDEO_TRANSFER_BT2020_12:
case GST_VIDEO_TRANSFER_BT2020_10:
case GST_VIDEO_TRANSFER_BT709:
v4l2object->transfer = info.colorimetry.transfer;
v4l2object->transfer = info.vinfo.colorimetry.transfer;
transfer = V4L2_XFER_FUNC_709;
break;
case GST_VIDEO_TRANSFER_SMPTE240M:
@ -3875,13 +3934,13 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
break;
default:
GST_WARNING_OBJECT (v4l2object->dbg_obj,
"Unknown colorimetry transfer %d", info.colorimetry.transfer);
"Unknown colorimetry transfer %d", info.vinfo.colorimetry.transfer);
break;
}
if (colorspace == 0) {
/* Try to guess colorspace according to pixelformat and size */
if (GST_VIDEO_INFO_IS_YUV (&info)) {
if (GST_VIDEO_INFO_IS_YUV (&info.vinfo)) {
if (range == V4L2_QUANTIZATION_FULL_RANGE
&& matrix == V4L2_YCBCR_ENC_601 && transfer == 0) {
/* Full range BT.601 YCbCr encoding with unknown primaries and transfer
@ -3890,12 +3949,12 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
transfer = V4L2_XFER_FUNC_SRGB;
} else {
/* SD streams likely use SMPTE170M and HD streams REC709 */
if (width <= 720 && GST_VIDEO_INFO_HEIGHT (&info) <= 576)
if (width <= 720 && GST_VIDEO_INFO_HEIGHT (&info.vinfo) <= 576)
colorspace = V4L2_COLORSPACE_SMPTE170M;
else
colorspace = V4L2_COLORSPACE_REC709;
}
} else if (GST_VIDEO_INFO_IS_RGB (&info)) {
} else if (GST_VIDEO_INFO_IS_RGB (&info.vinfo)) {
colorspace = V4L2_COLORSPACE_SRGB;
transfer = V4L2_XFER_FUNC_NONE;
}
@ -3903,7 +3962,8 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
GST_DEBUG_OBJECT (v4l2object->dbg_obj, "Desired format %dx%d, format "
"%" GST_FOURCC_FORMAT " stride: %d", width, height,
GST_FOURCC_ARGS (pixelformat), GST_VIDEO_INFO_PLANE_STRIDE (&info, 0));
GST_FOURCC_ARGS (pixelformat),
GST_VIDEO_INFO_PLANE_STRIDE (&info.vinfo, 0));
s = gst_caps_get_structure (caps, 0);
@ -3927,20 +3987,20 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
/* try to ask our preferred stride but it's not a failure if not
* accepted */
for (i = 0; i < n_v4l_planes; i++) {
gint stride = GST_VIDEO_INFO_PLANE_STRIDE (&info, i);
gint stride = GST_VIDEO_INFO_PLANE_STRIDE (&info.vinfo, i);
if (GST_VIDEO_FORMAT_INFO_IS_TILED (info.finfo))
if (GST_VIDEO_FORMAT_INFO_IS_TILED (info.vinfo.finfo))
stride = GST_VIDEO_TILE_X_TILES (stride) *
GST_VIDEO_FORMAT_INFO_TILE_STRIDE (info.finfo, i);
GST_VIDEO_FORMAT_INFO_TILE_STRIDE (info.vinfo.finfo, i);
format.fmt.pix_mp.plane_fmt[i].bytesperline = stride;
}
if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_ENCODED)
if (GST_VIDEO_INFO_FORMAT (&info.vinfo) == GST_VIDEO_FORMAT_ENCODED)
format.fmt.pix_mp.plane_fmt[0].sizeimage =
calculate_max_sizeimage (v4l2object, pixel_bitdepth);
} else {
gint stride = GST_VIDEO_INFO_PLANE_STRIDE (&info, 0);
gint stride = GST_VIDEO_INFO_PLANE_STRIDE (&info.vinfo, 0);
format.type = v4l2object->type;
@ -3949,14 +4009,14 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
format.fmt.pix.pixelformat = pixelformat;
format.fmt.pix.field = field;
if (GST_VIDEO_FORMAT_INFO_IS_TILED (info.finfo))
if (GST_VIDEO_FORMAT_INFO_IS_TILED (info.vinfo.finfo))
stride = GST_VIDEO_TILE_X_TILES (stride) *
GST_VIDEO_FORMAT_INFO_TILE_STRIDE (info.finfo, i);
GST_VIDEO_FORMAT_INFO_TILE_STRIDE (info.vinfo.finfo, i);
/* try to ask our preferred stride */
format.fmt.pix.bytesperline = stride;
if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_ENCODED)
if (GST_VIDEO_INFO_FORMAT (&info.vinfo) == GST_VIDEO_FORMAT_ENCODED)
format.fmt.pix.sizeimage =
calculate_max_sizeimage (v4l2object, pixel_bitdepth);
}
@ -4139,7 +4199,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
* For some codecs the dimensions are *not* in the bitstream, IIRC VC1
* in ASF mode for example, there is also not reason for a driver to
* change the size. */
if (info.finfo->format != GST_VIDEO_FORMAT_ENCODED) {
if (GST_VIDEO_INFO_FORMAT (&info.vinfo) != GST_VIDEO_FORMAT_ENCODED) {
/* We can crop larger images */
if (format.fmt.pix.width < width || format.fmt.pix.height < height)
goto invalid_dimensions;
@ -4156,7 +4216,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
/* used to check colorimetry and interlace mode fields presence */
if (gst_v4l2_object_get_interlace_mode (format.fmt.pix.field,
&info.interlace_mode)) {
&info.vinfo.interlace_mode)) {
if (gst_structure_has_field (s, "interlace-mode")) {
if (format.fmt.pix.field != field)
goto invalid_field;
@ -4169,9 +4229,10 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
gst_structure_remove_field (s, "interlace-mode");
}
if (gst_v4l2_object_get_colorspace (v4l2object, &format, &info.colorimetry)) {
if (gst_v4l2_object_get_colorspace (v4l2object, &format,
&info.vinfo.colorimetry)) {
if (gst_structure_has_field (s, "colorimetry")) {
if (!gst_v4l2_video_colorimetry_matches (&info.colorimetry, caps))
if (!gst_v4l2_video_colorimetry_matches (&info.vinfo.colorimetry, caps))
goto invalid_colorimetry;
}
} else {
@ -4187,10 +4248,10 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
if (v4l2object->skip_try_fmt_probes) {
if (!disable_interlacing && !gst_structure_has_field (s, "interlace-mode")) {
gst_structure_set (s, "interlace-mode", G_TYPE_STRING,
gst_video_interlace_mode_to_string (info.interlace_mode), NULL);
gst_video_interlace_mode_to_string (info.vinfo.interlace_mode), NULL);
}
if (!disable_colorimetry && !gst_structure_has_field (s, "colorimetry")) {
gchar *str = gst_video_colorimetry_to_string (&info.colorimetry);
gchar *str = gst_video_colorimetry_to_string (&info.vinfo.colorimetry);
gst_structure_set (s, "colorimetry", G_TYPE_STRING, str, NULL);
g_free (str);
}
@ -4281,7 +4342,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
if (try_only) /* good enough for trying only */
return TRUE;
if (GST_VIDEO_INFO_HAS_ALPHA (&info)) {
if (GST_VIDEO_INFO_HAS_ALPHA (&info.vinfo)) {
struct v4l2_control ctl = { 0, };
ctl.id = V4L2_CID_ALPHA_COMPONENT;
ctl.value = 0xff;
@ -4303,9 +4364,9 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
if (v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE
|| v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
GST_VIDEO_INFO_FPS_N (&info) =
GST_VIDEO_INFO_FPS_N (&info.vinfo) =
streamparm.parm.capture.timeperframe.denominator;
GST_VIDEO_INFO_FPS_D (&info) =
GST_VIDEO_INFO_FPS_D (&info.vinfo) =
streamparm.parm.capture.timeperframe.numerator;
GST_DEBUG_OBJECT (v4l2object->dbg_obj, "Got capture framerate: %u/%u",
@ -4374,13 +4435,13 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
"Reuse caps framerate %u/%u - fix v4l2 capture driver", fps_n, fps_d);
}
GST_VIDEO_INFO_FPS_N (&info) = fps_n;
GST_VIDEO_INFO_FPS_D (&info) = fps_d;
GST_VIDEO_INFO_FPS_N (&info.vinfo) = fps_n;
GST_VIDEO_INFO_FPS_D (&info.vinfo) = fps_d;
} else if (v4l2object->type == V4L2_BUF_TYPE_VIDEO_OUTPUT
|| v4l2object->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
GST_VIDEO_INFO_FPS_N (&info) =
GST_VIDEO_INFO_FPS_N (&info.vinfo) =
streamparm.parm.output.timeperframe.denominator;
GST_VIDEO_INFO_FPS_D (&info) =
GST_VIDEO_INFO_FPS_D (&info.vinfo) =
streamparm.parm.output.timeperframe.numerator;
GST_DEBUG_OBJECT (v4l2object->dbg_obj, "Got output framerate: %u/%u",
@ -4426,8 +4487,8 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
"Reuse caps framerate %u/%u - fix v4l2 output driver", fps_n, fps_d);
}
GST_VIDEO_INFO_FPS_N (&info) = fps_n;
GST_VIDEO_INFO_FPS_D (&info) = fps_d;
GST_VIDEO_INFO_FPS_N (&info.vinfo) = fps_n;
GST_VIDEO_INFO_FPS_D (&info.vinfo) = fps_d;
}
done:
@ -4544,7 +4605,8 @@ invalid_colorimetry:
{
gchar *wanted_colorimetry;
wanted_colorimetry = gst_video_colorimetry_to_string (&info.colorimetry);
wanted_colorimetry =
gst_video_colorimetry_to_string (&info.vinfo.colorimetry);
GST_V4L2_ERROR (error, RESOURCE, SETTINGS,
(_("Device '%s' does not support %s colorimetry"),
@ -4607,7 +4669,8 @@ gst_v4l2_object_try_format (GstV4l2Object * v4l2object, GstCaps * caps,
* Returns: %TRUE on success, %FALSE on failure.
*/
gboolean
gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info)
gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object,
GstVideoInfoDmaDrm * info)
{
struct v4l2_fmtdesc *fmtdesc;
struct v4l2_format fmt;
@ -4618,8 +4681,9 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info)
guint width, height;
GstVideoAlignment align;
GstVideoInterlaceMode interlace_mode;
const GstV4L2FormatDesc *desc;
gst_video_info_init (info);
gst_video_info_dma_drm_init (info);
gst_video_alignment_reset (&align);
v4l2object->transfer = GST_VIDEO_TRANSFER_UNKNOWN;
v4l2object->matrix = GST_VIDEO_COLOR_MATRIX_UNKNOWN;
@ -4635,12 +4699,18 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info)
goto unsupported_format;
/* No need to care about mplane, the four first params are the same */
format = gst_v4l2_object_v4l2fourcc_to_video_format (fmt.fmt.pix.pixelformat);
/* fails if we do no translate the fmt.pix.pixelformat to GstVideoFormat */
if (format == GST_VIDEO_FORMAT_UNKNOWN)
desc = gst_v4l2_object_get_desc_from_v4l2fourcc (fmt.fmt.pix.pixelformat);
if (!desc)
goto unsupported_format;
if (desc->gst_format == GST_VIDEO_FORMAT_UNKNOWN) {
if (!desc->drm_fourcc)
goto unsupported_format;
format = GST_VIDEO_FORMAT_DMA_DRM;
} else {
format = desc->gst_format;
}
if (fmt.fmt.pix.width == 0 || fmt.fmt.pix.height == 0)
goto invalid_dimensions;
@ -4686,19 +4756,22 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info)
goto unsupported_field;
}
if (!gst_video_info_set_interlaced_format (info, format, interlace_mode,
width, height))
info->drm_fourcc = desc->drm_fourcc;
info->drm_modifier = desc->drm_modifier;
if (!gst_video_info_set_interlaced_format (&info->vinfo, format,
interlace_mode, width, height))
goto invalid_dimensions;
gst_v4l2_object_get_colorspace (v4l2object, &fmt, &info->colorimetry);
gst_v4l2_object_get_streamparm (v4l2object, info);
if ((info->fps_n == 0 && v4l2object->info.fps_d != 0)
gst_v4l2_object_get_colorspace (v4l2object, &fmt, &info->vinfo.colorimetry);
gst_v4l2_object_get_streamparm (v4l2object, &info->vinfo);
if ((info->vinfo.fps_n == 0 && GST_V4L2_FPS_D (v4l2object) != 0)
&& (v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE
|| v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) {
info->fps_d = v4l2object->info.fps_d;
info->fps_n = v4l2object->info.fps_n;
info->vinfo.fps_d = GST_V4L2_FPS_D (v4l2object);
info->vinfo.fps_n = GST_V4L2_FPS_N (v4l2object);
GST_DEBUG_OBJECT (v4l2object->dbg_obj, "Set capture fps to %d/%d",
info->fps_n, info->fps_d);
info->vinfo.fps_n, info->vinfo.fps_d);
}
gst_v4l2_object_save_format (v4l2object, fmtdesc, &fmt, info, &align);
@ -4886,8 +4959,8 @@ gst_v4l2_object_setup_padding (GstV4l2Object * obj)
rect.left = align->padding_left;
rect.top = align->padding_top;
rect.width = obj->info.width;
rect.height = GST_VIDEO_INFO_FIELD_HEIGHT (&obj->info);
rect.width = GST_V4L2_WIDTH (obj);
rect.height = GST_V4L2_FIELD_HEIGHT (obj);
if (V4L2_TYPE_IS_OUTPUT (obj->type)) {
return gst_v4l2_object_set_crop (obj, &rect);
@ -5309,39 +5382,40 @@ gst_v4l2_object_match_buffer_layout (GstV4l2Object * obj, guint n_planes,
gsize offset[GST_VIDEO_MAX_PLANES], gint stride[GST_VIDEO_MAX_PLANES],
gsize buffer_size, guint padded_height)
{
guint p;
gboolean need_fmt_update = FALSE;
GstVideoInfo *info = &obj->info.vinfo;
guint p;
if (n_planes != GST_VIDEO_INFO_N_PLANES (&obj->info)) {
if (n_planes != GST_V4L2_N_PLANES (obj)) {
GST_WARNING_OBJECT (obj->dbg_obj,
"Cannot match buffers with different number planes");
return FALSE;
}
for (p = 0; p < n_planes; p++) {
if (stride[p] < obj->info.stride[p]) {
if (stride[p] < info->stride[p]) {
GST_DEBUG_OBJECT (obj->dbg_obj,
"Not matching as remote stride %i is smaller than %i on plane %u",
stride[p], obj->info.stride[p], p);
stride[p], info->stride[p], p);
return FALSE;
} else if (stride[p] > obj->info.stride[p]) {
} else if (stride[p] > info->stride[p]) {
GST_LOG_OBJECT (obj->dbg_obj,
"Remote stride %i is higher than %i on plane %u",
stride[p], obj->info.stride[p], p);
stride[p], info->stride[p], p);
need_fmt_update = TRUE;
}
if (offset[p] < obj->info.offset[p]) {
if (offset[p] < info->offset[p]) {
GST_DEBUG_OBJECT (obj->dbg_obj,
"Not matching as offset %" G_GSIZE_FORMAT
" is smaller than %" G_GSIZE_FORMAT " on plane %u",
offset[p], obj->info.offset[p], p);
offset[p], info->offset[p], p);
return FALSE;
} else if (offset[p] > obj->info.offset[p]) {
} else if (offset[p] > info->offset[p]) {
GST_LOG_OBJECT (obj->dbg_obj,
"Remote offset %" G_GSIZE_FORMAT
" is higher than %" G_GSIZE_FORMAT " on plane %u",
offset[p], obj->info.offset[p], p);
offset[p], info->offset[p], p);
need_fmt_update = TRUE;
}
}
@ -5372,7 +5446,7 @@ gst_v4l2_object_match_buffer_layout (GstV4l2Object * obj, guint n_planes,
GST_DEBUG_OBJECT (obj->dbg_obj, "Padded height %u", padded_height);
obj->align.padding_bottom =
padded_height - GST_VIDEO_INFO_FIELD_HEIGHT (&obj->info);
padded_height - GST_VIDEO_INFO_FIELD_HEIGHT (info);
} else {
GST_WARNING_OBJECT (obj->dbg_obj,
"Failed to compute padded height; keep the default one");
@ -5388,9 +5462,9 @@ gst_v4l2_object_match_buffer_layout (GstV4l2Object * obj, guint n_planes,
for (i = 0; i < obj->n_v4l2_planes; i++) {
gint plane_stride = stride[i];
if (GST_VIDEO_FORMAT_INFO_IS_TILED (obj->info.finfo))
if (GST_VIDEO_FORMAT_INFO_IS_TILED (info->finfo))
plane_stride = GST_VIDEO_TILE_X_TILES (plane_stride) *
GST_VIDEO_FORMAT_INFO_TILE_STRIDE (obj->info.finfo, i);
GST_VIDEO_FORMAT_INFO_TILE_STRIDE (info->finfo, i);
format.fmt.pix_mp.plane_fmt[i].bytesperline = plane_stride;
wanted_stride[i] = plane_stride;
@ -5403,9 +5477,9 @@ gst_v4l2_object_match_buffer_layout (GstV4l2Object * obj, guint n_planes,
GST_DEBUG_OBJECT (obj->dbg_obj, "Wanted stride: %i", plane_stride);
if (GST_VIDEO_FORMAT_INFO_IS_TILED (obj->info.finfo))
if (GST_VIDEO_FORMAT_INFO_IS_TILED (info->finfo))
plane_stride = GST_VIDEO_TILE_X_TILES (plane_stride) *
GST_VIDEO_FORMAT_INFO_TILE_STRIDE (obj->info.finfo, 0);
GST_VIDEO_FORMAT_INFO_TILE_STRIDE (info->finfo, 0);
format.fmt.pix.bytesperline = plane_stride;
format.fmt.pix.height = padded_height;
@ -5620,13 +5694,13 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
/* use the bigest size, when we use our own pool we can't really do any
* other size than what the hardware gives us but for downstream pools
* we can try */
size = MAX (size, obj->info.size);
size = MAX (size, GST_V4L2_SIZE (obj));
} else if (can_share_own_pool) {
/* no downstream pool, use our own then */
GST_DEBUG_OBJECT (obj->dbg_obj,
"read/write mode: no downstream pool, using our own");
pool = gst_object_ref (obj_pool);
size = obj->info.size;
size = GST_V4L2_SIZE (obj);
pushing_from_our_pool = TRUE;
}
break;
@ -5642,7 +5716,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
other_pool = pool;
gst_object_unref (pool);
pool = gst_object_ref (obj_pool);
size = obj->info.size;
size = GST_V4L2_SIZE (obj);
break;
case GST_V4L2_IO_MMAP:
@ -5653,7 +5727,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
if (pool)
gst_object_unref (pool);
pool = gst_object_ref (obj_pool);
size = obj->info.size;
size = GST_V4L2_SIZE (obj);
GST_DEBUG_OBJECT (obj->dbg_obj,
"streaming mode: using our own pool %" GST_PTR_FORMAT, pool);
pushing_from_our_pool = TRUE;
@ -5664,7 +5738,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
} else {
GST_DEBUG_OBJECT (obj->dbg_obj,
"streaming mode: no usable pool, copying to generic pool");
size = MAX (size, obj->info.size);
size = MAX (size, GST_V4L2_SIZE (obj));
}
break;
case GST_V4L2_IO_AUTO:
@ -5851,7 +5925,7 @@ gst_v4l2_object_propose_allocation (GstV4l2Object * obj, GstQuery * query)
GstStructure *allocation_meta = NULL;
/* Set defaults allocation parameters */
size = obj->info.size;
size = GST_V4L2_SIZE (obj);
min = GST_V4L2_MIN_BUFFERS (obj);
max = VIDEO_MAX_FRAME;

View file

@ -44,7 +44,7 @@ typedef struct _GstV4l2ObjectClassHelper GstV4l2ObjectClassHelper;
/* size of v4l2 buffer pool in streaming case, obj->info needs to be valid */
#define GST_V4L2_MIN_BUFFERS(obj) \
((GST_VIDEO_INFO_INTERLACE_MODE (&obj->info) == \
((GST_VIDEO_INFO_INTERLACE_MODE (&obj->info.vinfo) == \
GST_VIDEO_INTERLACE_MODE_ALTERNATE) ? \
/* 2x buffers needed with each field in its own buffer */ \
4 : 2)
@ -82,11 +82,14 @@ typedef int ioctl_req_t;
typedef gulong ioctl_req_t;
#endif
#define GST_V4L2_WIDTH(o) (GST_VIDEO_INFO_WIDTH (&(o)->info))
#define GST_V4L2_HEIGHT(o) (GST_VIDEO_INFO_HEIGHT (&(o)->info))
#define GST_V4L2_WIDTH(o) (GST_VIDEO_INFO_WIDTH (&(o)->info.vinfo))
#define GST_V4L2_HEIGHT(o) (GST_VIDEO_INFO_HEIGHT (&(o)->info.vinfo))
#define GST_V4L2_FIELD_HEIGHT(o) (GST_VIDEO_INFO_FIELD_HEIGHT (&(o)->info.vinfo))
#define GST_V4L2_PIXELFORMAT(o) ((o)->fmtdesc->pixelformat)
#define GST_V4L2_FPS_N(o) (GST_VIDEO_INFO_FPS_N (&(o)->info))
#define GST_V4L2_FPS_D(o) (GST_VIDEO_INFO_FPS_D (&(o)->info))
#define GST_V4L2_FPS_N(o) (GST_VIDEO_INFO_FPS_N (&(o)->info.vinfo))
#define GST_V4L2_FPS_D(o) (GST_VIDEO_INFO_FPS_D (&(o)->info.vinfo))
#define GST_V4L2_SIZE(o) (GST_VIDEO_INFO_SIZE (&(o)->info.vinfo))
#define GST_V4L2_N_PLANES(o) (GST_VIDEO_INFO_N_PLANES (&(o)->info.vinfo))
/* simple check whether the device is open */
#define GST_V4L2_IS_OPEN(o) ((o)->video_fd > 0)
@ -145,7 +148,7 @@ struct _GstV4l2Object {
/* the current format */
struct v4l2_fmtdesc *fmtdesc;
struct v4l2_format format;
GstVideoInfo info;
GstVideoInfoDmaDrm info;
GstVideoAlignment align;
GstVideoTransferFunction transfer;
gsize plane_size[GST_VIDEO_MAX_PLANES];
@ -229,7 +232,7 @@ struct _GstV4l2Object {
* on slow USB firmwares. When this is set, gst_v4l2_set_format() will modify
* the caps to reflect what was negotiated during fixation */
gboolean skip_try_fmt_probes;
guint max_width;
guint max_height;
};
@ -315,7 +318,7 @@ gboolean gst_v4l2_object_stop (GstV4l2Object * v4l2object);
GstCaps * gst_v4l2_object_probe_caps (GstV4l2Object * v4l2object, GstCaps * filter);
GstCaps * gst_v4l2_object_get_caps (GstV4l2Object * v4l2object, GstCaps * filter);
gboolean gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info);
gboolean gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfoDmaDrm * info);
gboolean gst_v4l2_object_setup_padding (GstV4l2Object * obj);

View file

@ -922,10 +922,10 @@ gst_v4l2src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
if (gst_query_get_n_allocation_pools (query))
gst_query_set_nth_allocation_pool (query, 0, pool,
src->v4l2object->info.size, 1, 0);
src->v4l2object->info.vinfo.size, 1, 0);
else
gst_query_add_allocation_pool (query, pool, src->v4l2object->info.size, 1,
0);
gst_query_add_allocation_pool (query, pool,
src->v4l2object->info.vinfo.size, 1, 0);
if (pool)
gst_object_unref (pool);
@ -998,7 +998,7 @@ gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query)
/* min latency is the time to capture one frame/field */
min_latency = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
if (GST_VIDEO_INFO_INTERLACE_MODE (&obj->info) ==
if (GST_VIDEO_INFO_INTERLACE_MODE (&obj->info.vinfo) ==
GST_VIDEO_INTERLACE_MODE_ALTERNATE)
min_latency /= 2;
@ -1160,7 +1160,7 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
do {
ret = GST_BASE_SRC_CLASS (parent_class)->alloc (GST_BASE_SRC (src), 0,
obj->info.size, buf);
obj->info.vinfo.size, buf);
if (G_UNLIKELY (ret != GST_FLOW_OK)) {
if (ret == GST_V4L2_FLOW_RESOLUTION_CHANGE) {

View file

@ -29,6 +29,8 @@
#include <unistd.h>
#include <string.h>
#include <gst/allocators/allocators.h>
#include "gstv4l2object.h"
#include "gstv4l2transform.h"
@ -373,23 +375,45 @@ gst_v4l2_transform_caps_remove_format_info (GstCaps * caps)
n = gst_caps_get_size (caps);
for (i = 0; i < n; i++) {
st = gst_caps_get_structure (caps, i);
GstCapsFeatures *alt_f = NULL;
st = gst_structure_copy (gst_caps_get_structure (caps, i));
f = gst_caps_get_features (caps, i);
alt_f = gst_caps_features_copy (f);
/* remove all the features we support, if anything is left it means we
* cannot convert */
if (!gst_caps_features_is_any (f)) {
gst_caps_features_remove (alt_f, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
gst_caps_features_remove (alt_f, GST_CAPS_FEATURE_MEMORY_DMABUF);
gst_caps_features_remove (alt_f, GST_CAPS_FEATURE_FORMAT_INTERLACED);
}
/* Only remove format info for the cases when we can actually convert */
if (!gst_caps_features_is_any (f)
&& (gst_caps_features_get_size (alt_f) == 0)) {
gst_structure_remove_fields (st, "format", "drm-format", "colorimetry",
"chroma-site", "width", "height", "pixel-aspect-ratio", NULL);
/* create an alternate feature, so that we allow converting between system
* memory and dmabuf */
if (gst_caps_features_contains (f, GST_CAPS_FEATURE_FORMAT_INTERLACED))
gst_caps_features_add (alt_f, GST_CAPS_FEATURE_FORMAT_INTERLACED);
if (!gst_caps_features_contains (f, GST_CAPS_FEATURE_MEMORY_DMABUF))
gst_caps_features_add (alt_f, GST_CAPS_FEATURE_MEMORY_DMABUF);
}
/* If this is already expressed by the existing caps
* skip this structure */
if (i > 0 && gst_caps_is_subset_structure_full (res, st, f))
continue;
if (!gst_caps_is_subset_structure_full (res, st, f))
gst_caps_append_structure_full (res, gst_structure_copy (st),
gst_caps_features_copy (f));
if (!gst_caps_is_subset_structure_full (res, st, alt_f))
gst_caps_append_structure_full (res, gst_structure_copy (st),
gst_caps_features_copy (alt_f));
st = gst_structure_copy (st);
/* Only remove format info for the cases when we can actually convert */
if (!gst_caps_features_is_any (f)
&& gst_caps_features_is_equal (f,
GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY))
gst_structure_remove_fields (st, "format", "colorimetry", "chroma-site",
"width", "height", "pixel-aspect-ratio", NULL);
gst_caps_append_structure_full (res, st, gst_caps_features_copy (f));
gst_structure_free (st);
gst_caps_features_free (alt_f);
}
return res;
@ -920,7 +944,7 @@ gst_v4l2_transform_prepare_output_buffer (GstBaseTransform * trans,
}
gst_buffer_pool_config_set_params (config, self->incaps,
self->v4l2output->info.size, min, min);
self->v4l2output->info.vinfo.size, min, min);
/* There is no reason to refuse this config */
if (!gst_buffer_pool_set_config (pool, config))

View file

@ -364,7 +364,7 @@ gst_v4l2_video_remove_padding (GstCapsFeatures * features,
{
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (user_data);
GstVideoAlignment *align = &self->v4l2capture->align;
GstVideoInfo *info = &self->v4l2capture->info;
GstVideoInfo *info = &self->v4l2capture->info.vinfo;
int width, height;
if (!gst_structure_get_int (structure, "width", &width))
@ -397,13 +397,14 @@ gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
{
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
GstV4l2Error error = GST_V4L2_ERROR_INIT;
GstVideoInfo info;
GstVideoInfoDmaDrm info;
GstVideoCodecState *output_state;
GstCaps *acquired_caps, *fixation_caps, *available_caps, *caps, *filter;
GstStructure *st;
GstCaps *acquired_caps, *acquired_drm_caps;
GstCaps *fixation_caps, *available_caps, *caps, *filter;
gboolean active;
GstBufferPool *cpool;
gboolean ret;
gint i;
/* We don't allow renegotiation without careful disabling the pool */
cpool = gst_v4l2_object_get_buffer_pool (self->v4l2capture);
@ -415,8 +416,8 @@ gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
}
/* init capture fps according to output */
self->v4l2capture->info.fps_d = self->v4l2output->info.fps_d;
self->v4l2capture->info.fps_n = self->v4l2output->info.fps_n;
GST_V4L2_FPS_D (self->v4l2capture) = GST_V4L2_FPS_D (self->v4l2output);
GST_V4L2_FPS_N (self->v4l2capture) = GST_V4L2_FPS_N (self->v4l2output);
/* For decoders G_FMT returns coded size, G_SELECTION returns visible size
* in the compose rectangle. gst_v4l2_object_acquire_format() checks both
@ -426,19 +427,34 @@ gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
goto not_negotiated;
/* gst_v4l2_object_acquire_format() does not set fps, copy from sink */
info.fps_n = self->v4l2output->info.fps_n;
info.fps_d = self->v4l2output->info.fps_d;
info.vinfo.fps_n = GST_V4L2_FPS_N (self->v4l2output);
info.vinfo.fps_d = GST_V4L2_FPS_D (self->v4l2output);
gst_caps_replace (&self->probed_srccaps, NULL);
self->probed_srccaps = gst_v4l2_object_probe_caps (self->v4l2capture,
gst_v4l2_object_get_raw_caps ());
/* Create caps from the acquired format, remove the format field */
acquired_caps = gst_video_info_to_caps (&info);
GST_DEBUG_OBJECT (self, "Acquired caps: %" GST_PTR_FORMAT, acquired_caps);
fixation_caps = gst_caps_copy (acquired_caps);
st = gst_caps_get_structure (fixation_caps, 0);
gst_structure_remove_fields (st, "format", "colorimetry", "chroma-site",
NULL);
/* Create caps from the acquired format, removing the format fields */
fixation_caps = gst_caps_new_empty ();
acquired_drm_caps = gst_video_info_dma_drm_to_caps (&info);
if (acquired_drm_caps) {
GST_DEBUG_OBJECT (self, "Acquired DRM caps: %" GST_PTR_FORMAT,
acquired_drm_caps);
gst_caps_append (fixation_caps, gst_caps_copy (acquired_drm_caps));
}
acquired_caps = gst_video_info_to_caps (&info.vinfo);
if (acquired_caps) {
GST_DEBUG_OBJECT (self, "Acquired caps: %" GST_PTR_FORMAT, acquired_caps);
gst_caps_append (fixation_caps, gst_caps_copy (acquired_drm_caps));
}
for (i = 0; i < gst_caps_get_size (fixation_caps); i++) {
GstStructure *st = gst_caps_get_structure (fixation_caps, i);
gst_structure_remove_fields (st, "format", "drm-format", "colorimetry",
"chroma-site", NULL);
}
/* Probe currently available pixel formats */
available_caps = gst_caps_copy (self->probed_srccaps);
@ -465,6 +481,16 @@ gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
/* Prefer the acquired caps over anything suggested downstream, this ensure
* that we preserves the bit depth, as we don't have any fancy fixation
* process */
if (acquired_drm_caps) {
if (gst_caps_is_subset (acquired_drm_caps, caps)) {
gst_caps_replace (&acquired_caps, acquired_drm_caps);
acquired_drm_caps = NULL;
goto use_acquired_caps;
}
gst_clear_caps (&acquired_drm_caps);
}
if (gst_caps_is_subset (acquired_caps, caps))
goto use_acquired_caps;
@ -475,12 +501,11 @@ gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
/* Try to set negotiated format, on success replace acquired format */
if (gst_v4l2_object_set_format (self->v4l2capture, caps, &error))
gst_video_info_from_caps (&info, caps);
info = self->v4l2capture->info;
else
gst_v4l2_clear_error (&error);
use_acquired_caps:
gst_caps_unref (acquired_caps);
gst_caps_unref (caps);
/* catch possible bogus driver that don't enumerate the format it actually
@ -488,12 +513,13 @@ use_acquired_caps:
if (!self->v4l2capture->fmtdesc)
goto not_negotiated;
output_state = gst_video_decoder_set_output_state (decoder,
info.finfo->format, info.width, info.height, self->input_state);
output_state = gst_video_decoder_set_interlaced_output_state (decoder,
info.vinfo.finfo->format, info.vinfo.interlace_mode, info.vinfo.width,
info.vinfo.height, self->input_state);
/* Copy the rest of the information, there might be more in the future */
output_state->info.interlace_mode = info.interlace_mode;
output_state->info.colorimetry = info.colorimetry;
output_state->info.colorimetry = info.vinfo.colorimetry;
output_state->caps = acquired_caps;
gst_video_codec_state_unref (output_state);
ret = GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
@ -945,14 +971,15 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
/* Ensure input internal pool is active */
gst_buffer_pool_config_set_params (config, self->input_state->caps,
self->v4l2output->info.size, min, max);
self->v4l2output->info.vinfo.size, min, max);
/* There is no reason to refuse this config */
if (!gst_buffer_pool_set_config (pool, config)) {
config = gst_buffer_pool_get_config (pool);
if (!gst_buffer_pool_config_validate_params (config,
self->input_state->caps, self->v4l2output->info.size, min, max)) {
self->input_state->caps,
self->v4l2output->info.vinfo.size, min, max)) {
gst_structure_free (config);
goto activate_failed;
}

View file

@ -779,14 +779,14 @@ gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
GST_V4L2_MIN_BUFFERS (self->v4l2output));
gst_buffer_pool_config_set_params (config, self->input_state->caps,
self->v4l2output->info.size, min, min);
self->v4l2output->info.vinfo.size, min, min);
/* There is no reason to refuse this config */
if (!gst_buffer_pool_set_config (opool, config)) {
config = gst_buffer_pool_get_config (opool);
if (gst_buffer_pool_config_validate_params (config,
self->input_state->caps, self->v4l2output->info.size, min,
self->input_state->caps, self->v4l2output->info.vinfo.size, min,
min)) {
gst_structure_free (config);
if (opool)