mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 03:31:05 +00:00
va: baseenc: Add the DMA buffer input support
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5189>
This commit is contained in:
parent
5e6c91579f
commit
e81a40cb72
1 changed files with 120 additions and 2 deletions
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include <gst/va/gstva.h>
|
#include <gst/va/gstva.h>
|
||||||
#include <gst/va/vasurfaceimage.h>
|
#include <gst/va/vasurfaceimage.h>
|
||||||
|
#include <gst/va/gstvavideoformat.h>
|
||||||
|
|
||||||
#include "vacompat.h"
|
#include "vacompat.h"
|
||||||
#include "gstvacaps.h"
|
#include "gstvacaps.h"
|
||||||
|
@ -59,6 +60,8 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstVaBaseEnc, gst_va_base_enc,
|
||||||
"vabaseenc", 0, "vabaseenc element"););
|
"vabaseenc", 0, "vabaseenc element"););
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
extern GRecMutex GST_VA_SHARED_LOCK;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_va_base_enc_reset_state_default (GstVaBaseEnc * base)
|
gst_va_base_enc_reset_state_default (GstVaBaseEnc * base)
|
||||||
{
|
{
|
||||||
|
@ -205,6 +208,35 @@ _get_sinkpad_pool (GstVaBaseEnc * base)
|
||||||
|
|
||||||
g_assert (base->input_state);
|
g_assert (base->input_state);
|
||||||
caps = gst_caps_copy (base->input_state->caps);
|
caps = gst_caps_copy (base->input_state->caps);
|
||||||
|
g_assert (gst_caps_is_fixed (caps));
|
||||||
|
/* For DMA buffer, we can only import linear buffers.
|
||||||
|
Replace the drm-format into format field. */
|
||||||
|
if (gst_video_is_dma_drm_caps (caps)) {
|
||||||
|
GstVideoInfoDmaDrm dma_info;
|
||||||
|
GstVideoInfo info;
|
||||||
|
|
||||||
|
if (!gst_video_info_dma_drm_from_caps (&dma_info, caps)) {
|
||||||
|
GST_ERROR_OBJECT (base, "Cannot parse caps %" GST_PTR_FORMAT, caps);
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dma_info.drm_modifier != DRM_FORMAT_MOD_LINEAR) {
|
||||||
|
GST_ERROR_OBJECT (base, "Cannot import non-linear DMA buffer");
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gst_va_dma_drm_info_to_video_info (&dma_info, &info)) {
|
||||||
|
GST_ERROR_OBJECT (base, "Cannot get va video info");
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_caps_set_simple (caps, "format", G_TYPE_STRING,
|
||||||
|
gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&info)), NULL);
|
||||||
|
gst_structure_remove_field (gst_caps_get_structure (caps, 0), "drm-format");
|
||||||
|
}
|
||||||
gst_caps_set_features_simple (caps,
|
gst_caps_set_features_simple (caps,
|
||||||
gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_VA));
|
gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_VA));
|
||||||
|
|
||||||
|
@ -241,10 +273,94 @@ _get_sinkpad_pool (GstVaBaseEnc * base)
|
||||||
return base->priv->raw_pool;
|
return base->priv->raw_pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline gsize
|
||||||
|
_get_plane_data_size (GstVideoInfo * info, guint plane)
|
||||||
|
{
|
||||||
|
gint comp[GST_VIDEO_MAX_COMPONENTS];
|
||||||
|
gint height, padded_height;
|
||||||
|
|
||||||
|
gst_video_format_info_component (info->finfo, plane, comp);
|
||||||
|
|
||||||
|
height = GST_VIDEO_INFO_HEIGHT (info);
|
||||||
|
padded_height =
|
||||||
|
GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info->finfo, comp[0], height);
|
||||||
|
|
||||||
|
return GST_VIDEO_INFO_PLANE_STRIDE (info, plane) * padded_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_try_import_dmabuf_unlocked (GstVaBaseEnc * base, GstBuffer * inbuf)
|
||||||
|
{
|
||||||
|
GstVideoMeta *meta;
|
||||||
|
GstVideoInfo in_info = base->in_info;
|
||||||
|
GstMemory *mems[GST_VIDEO_MAX_PLANES];
|
||||||
|
guint i, n_mem, n_planes, usage_hint;
|
||||||
|
gsize offset[GST_VIDEO_MAX_PLANES];
|
||||||
|
uintptr_t fd[GST_VIDEO_MAX_PLANES];
|
||||||
|
|
||||||
|
n_planes = GST_VIDEO_INFO_N_PLANES (&in_info);
|
||||||
|
n_mem = gst_buffer_n_memory (inbuf);
|
||||||
|
meta = gst_buffer_get_video_meta (inbuf);
|
||||||
|
|
||||||
|
/* This will eliminate most non-dmabuf out there */
|
||||||
|
if (!gst_is_dmabuf_memory (gst_buffer_peek_memory (inbuf, 0)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* We cannot have multiple dmabuf per plane */
|
||||||
|
if (n_mem > n_planes)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Update video info based on video meta */
|
||||||
|
if (meta) {
|
||||||
|
GST_VIDEO_INFO_WIDTH (&in_info) = meta->width;
|
||||||
|
GST_VIDEO_INFO_HEIGHT (&in_info) = meta->height;
|
||||||
|
|
||||||
|
for (i = 0; i < meta->n_planes; i++) {
|
||||||
|
GST_VIDEO_INFO_PLANE_OFFSET (&in_info, i) = meta->offset[i];
|
||||||
|
GST_VIDEO_INFO_PLANE_STRIDE (&in_info, i) = meta->stride[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find and validate all memories */
|
||||||
|
for (i = 0; i < n_planes; i++) {
|
||||||
|
guint plane_size;
|
||||||
|
guint length;
|
||||||
|
guint mem_idx;
|
||||||
|
gsize mem_skip;
|
||||||
|
|
||||||
|
plane_size = _get_plane_data_size (&in_info, i);
|
||||||
|
|
||||||
|
if (!gst_buffer_find_memory (inbuf, in_info.offset[i], plane_size,
|
||||||
|
&mem_idx, &length, &mem_skip))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* We can't have more then one dmabuf per plane */
|
||||||
|
if (length != 1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
mems[i] = gst_buffer_peek_memory (inbuf, mem_idx);
|
||||||
|
|
||||||
|
/* And all memory found must be dmabuf */
|
||||||
|
if (!gst_is_dmabuf_memory (mems[i]))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
offset[i] = mems[i]->offset + mem_skip;
|
||||||
|
fd[i] = gst_dmabuf_memory_get_fd (mems[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
usage_hint = va_get_surface_usage_hint (base->display,
|
||||||
|
VAEntrypointEncSlice, GST_PAD_SINK, TRUE);
|
||||||
|
|
||||||
|
/* Now create a VASurfaceID for the buffer */
|
||||||
|
return gst_va_dmabuf_memories_setup (base->display, &in_info, n_planes,
|
||||||
|
mems, fd, offset, usage_hint);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_try_import_buffer (GstVaBaseEnc * base, GstBuffer * inbuf)
|
_try_import_buffer (GstVaBaseEnc * base, GstBuffer * inbuf)
|
||||||
{
|
{
|
||||||
VASurfaceID surface;
|
VASurfaceID surface;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
/* The VA buffer. */
|
/* The VA buffer. */
|
||||||
surface = gst_va_buffer_get_surface (inbuf);
|
surface = gst_va_buffer_get_surface (inbuf);
|
||||||
|
@ -252,9 +368,11 @@ _try_import_buffer (GstVaBaseEnc * base, GstBuffer * inbuf)
|
||||||
(gst_va_buffer_peek_display (inbuf) == base->display))
|
(gst_va_buffer_peek_display (inbuf) == base->display))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* TODO: DMA buffer. */
|
g_rec_mutex_lock (&GST_VA_SHARED_LOCK);
|
||||||
|
ret = _try_import_dmabuf_unlocked (base, inbuf);
|
||||||
|
g_rec_mutex_unlock (&GST_VA_SHARED_LOCK);
|
||||||
|
|
||||||
return FALSE;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
|
|
Loading…
Reference in a new issue