v4l2object: Add a method to try and import buffers
This method will check if a buffer, base on it's video meta, can be imported. It will also try and adapt the request stride in case this is the only that miss-match. https://bugzilla.gnome.org/show_bug.cgi?id=583890
This commit is contained in:
parent
d6d8187345
commit
1c729be537
@ -42,6 +42,7 @@
|
|||||||
#include "gst/gst-i18n-plugin.h"
|
#include "gst/gst-i18n-plugin.h"
|
||||||
|
|
||||||
#include <gst/video/video.h>
|
#include <gst/video/video.h>
|
||||||
|
#include <gst/allocators/gstdmabuf.h>
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
|
GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
|
||||||
#define GST_CAT_DEFAULT v4l2_debug
|
#define GST_CAT_DEFAULT v4l2_debug
|
||||||
@ -4601,3 +4602,154 @@ different_caps:
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_v4l2_object_try_import (GstV4l2Object * obj, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GstVideoMeta *vmeta;
|
||||||
|
guint n_mem = gst_buffer_n_memory (buffer);
|
||||||
|
|
||||||
|
/* only import if requested */
|
||||||
|
switch (obj->mode) {
|
||||||
|
case GST_V4L2_IO_USERPTR:
|
||||||
|
case GST_V4L2_IO_DMABUF_IMPORT:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GST_DEBUG_OBJECT (obj->dbg_obj,
|
||||||
|
"The io-mode does not enable importation");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
vmeta = gst_buffer_get_video_meta (buffer);
|
||||||
|
if (!vmeta && obj->need_video_meta) {
|
||||||
|
GST_DEBUG_OBJECT (obj->dbg_obj, "Downstream buffer uses standard "
|
||||||
|
"stride/offset while the driver does not.");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we need matching strides/offsets and size */
|
||||||
|
if (vmeta) {
|
||||||
|
guint p;
|
||||||
|
gboolean need_fmt_update = FALSE;
|
||||||
|
|
||||||
|
if (vmeta->n_planes != GST_VIDEO_INFO_N_PLANES (&obj->info)) {
|
||||||
|
GST_WARNING_OBJECT (obj->dbg_obj,
|
||||||
|
"Cannot import buffers with different number planes");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (p = 0; p < vmeta->n_planes; p++) {
|
||||||
|
if (vmeta->stride[p] < obj->info.stride[p]) {
|
||||||
|
GST_DEBUG_OBJECT (obj->dbg_obj,
|
||||||
|
"Not importing as remote stride %i is smaller then %i on plane %u",
|
||||||
|
vmeta->stride[p], obj->info.stride[p], p);
|
||||||
|
return FALSE;
|
||||||
|
} else if (vmeta->stride[p] > obj->info.stride[p]) {
|
||||||
|
need_fmt_update = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vmeta->offset[p] < obj->info.offset[p]) {
|
||||||
|
GST_DEBUG_OBJECT (obj->dbg_obj,
|
||||||
|
"Not importing as offset %" G_GSIZE_FORMAT
|
||||||
|
" is smaller then %" G_GSIZE_FORMAT " on plane %u",
|
||||||
|
vmeta->offset[p], obj->info.offset[p], p);
|
||||||
|
return FALSE;
|
||||||
|
} else if (vmeta->offset[p] > obj->info.offset[p]) {
|
||||||
|
need_fmt_update = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (need_fmt_update) {
|
||||||
|
struct v4l2_format format;
|
||||||
|
gint wanted_stride[GST_VIDEO_MAX_PLANES] = { 0, };
|
||||||
|
|
||||||
|
format = obj->format;
|
||||||
|
|
||||||
|
/* update the current format with the stride we want to import from */
|
||||||
|
if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) {
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (obj->dbg_obj, "Wanted strides:");
|
||||||
|
|
||||||
|
for (i = 0; i < obj->n_v4l2_planes; i++) {
|
||||||
|
gint stride = vmeta->stride[i];
|
||||||
|
|
||||||
|
if (GST_VIDEO_FORMAT_INFO_IS_TILED (obj->info.finfo))
|
||||||
|
stride = GST_VIDEO_TILE_X_TILES (stride) <<
|
||||||
|
GST_VIDEO_FORMAT_INFO_TILE_WS (obj->info.finfo);
|
||||||
|
|
||||||
|
format.fmt.pix_mp.plane_fmt[i].bytesperline = stride;
|
||||||
|
wanted_stride[i] = stride;
|
||||||
|
GST_DEBUG_OBJECT (obj->dbg_obj, " [%u] %i", i, wanted_stride[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gint stride = vmeta->stride[0];
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (obj->dbg_obj, "Wanted stride: %i", stride);
|
||||||
|
|
||||||
|
if (GST_VIDEO_FORMAT_INFO_IS_TILED (obj->info.finfo))
|
||||||
|
stride = GST_VIDEO_TILE_X_TILES (stride) <<
|
||||||
|
GST_VIDEO_FORMAT_INFO_TILE_WS (obj->info.finfo);
|
||||||
|
|
||||||
|
format.fmt.pix.bytesperline = stride;
|
||||||
|
wanted_stride[0] = stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj->ioctl (obj->video_fd, VIDIOC_S_FMT, &format) < 0) {
|
||||||
|
GST_WARNING_OBJECT (obj->dbg_obj,
|
||||||
|
"Something went wrong trying to update current format: %s",
|
||||||
|
g_strerror (errno));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_v4l2_object_save_format (obj, obj->fmtdesc, &format, &obj->info,
|
||||||
|
&obj->align);
|
||||||
|
|
||||||
|
if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) {
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < obj->n_v4l2_planes; i++) {
|
||||||
|
if (format.fmt.pix_mp.plane_fmt[i].bytesperline != wanted_stride[i]) {
|
||||||
|
GST_DEBUG_OBJECT (obj->dbg_obj,
|
||||||
|
"[%i] Driver did not accept the new stride (wants %i, got %i)",
|
||||||
|
i, format.fmt.pix_mp.plane_fmt[i].bytesperline,
|
||||||
|
wanted_stride[i]);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (format.fmt.pix.bytesperline != wanted_stride[0]) {
|
||||||
|
GST_DEBUG_OBJECT (obj->dbg_obj,
|
||||||
|
"Driver did not accept the new stride (wants %i, got %i)",
|
||||||
|
format.fmt.pix.bytesperline, wanted_stride[0]);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we can always import single memory buffer, but otherwise we need the same
|
||||||
|
* amount of memory object. */
|
||||||
|
if (n_mem != 1 && n_mem != obj->n_v4l2_planes) {
|
||||||
|
GST_DEBUG_OBJECT (obj->dbg_obj, "Can only import %i memory, "
|
||||||
|
"buffers contains %u memory", obj->n_v4l2_planes, n_mem);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For DMABuf importation we need DMABuf of course */
|
||||||
|
if (obj->mode == GST_V4L2_IO_DMABUF_IMPORT) {
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < n_mem; i++) {
|
||||||
|
GstMemory *mem = gst_buffer_peek_memory (buffer, i);
|
||||||
|
|
||||||
|
if (!gst_is_dmabuf_memory (mem)) {
|
||||||
|
GST_DEBUG_OBJECT (obj->dbg_obj, "Cannot import non-DMABuf memory.");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for the remaining, only the kernel driver can tell */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
@ -277,6 +277,7 @@ gint gst_v4l2_object_extrapolate_stride (const GstVideoFormatInfo * finf
|
|||||||
|
|
||||||
gboolean gst_v4l2_object_set_format (GstV4l2Object * v4l2object, GstCaps * caps, GstV4l2Error * error);
|
gboolean gst_v4l2_object_set_format (GstV4l2Object * v4l2object, GstCaps * caps, GstV4l2Error * error);
|
||||||
gboolean gst_v4l2_object_try_format (GstV4l2Object * v4l2object, GstCaps * caps, GstV4l2Error * error);
|
gboolean gst_v4l2_object_try_format (GstV4l2Object * v4l2object, GstCaps * caps, GstV4l2Error * error);
|
||||||
|
gboolean gst_v4l2_object_try_import (GstV4l2Object * v4l2object, GstBuffer * buffer);
|
||||||
|
|
||||||
gboolean gst_v4l2_object_caps_equal (GstV4l2Object * v4l2object, GstCaps * caps);
|
gboolean gst_v4l2_object_caps_equal (GstV4l2Object * v4l2object, GstCaps * caps);
|
||||||
gboolean gst_v4l2_object_caps_is_subset (GstV4l2Object * v4l2object, GstCaps * caps);
|
gboolean gst_v4l2_object_caps_is_subset (GstV4l2Object * v4l2object, GstCaps * caps);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user