mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 03:31:05 +00:00
va: refactor buffer import
This patch removes the code duplication of input buffer importation, in all the va elements that import video frames. It defines a synthetic object whose members are required to create a new input buffer and do the importation of the upstream buffer. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5257>
This commit is contained in:
parent
94593735d3
commit
89b0a6fa23
7 changed files with 297 additions and 480 deletions
190
subprojects/gst-plugins-bad/sys/va/gstvabase.c
Normal file
190
subprojects/gst-plugins-bad/sys/va/gstvabase.c
Normal file
|
@ -0,0 +1,190 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2023 Igalia, S.L.
|
||||
* Author: Víctor Jáquez <vjaquez@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstvabase.h"
|
||||
|
||||
#include <gst/video/video.h>
|
||||
|
||||
#include <gst/va/vasurfaceimage.h>
|
||||
|
||||
#define GST_CAT_DEFAULT (importer->debug_category)
|
||||
|
||||
/* big bad mutex to exclusive access to shared stream buffers, such as
|
||||
* DMABuf after a tee */
|
||||
static GRecMutex GST_VA_SHARED_LOCK = { 0, };
|
||||
|
||||
static gboolean
|
||||
_try_import_dmabuf_unlocked (GstVaBufferImporter * importer, GstBuffer * inbuf)
|
||||
{
|
||||
GstVideoMeta *meta;
|
||||
GstVideoInfo in_info = *importer->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];
|
||||
gsize plane_size[GST_VIDEO_MAX_PLANES];
|
||||
GstVideoAlignment align = { 0, };
|
||||
|
||||
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 importerd 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];
|
||||
}
|
||||
}
|
||||
|
||||
if (!gst_video_info_align_full (&in_info, &align, plane_size))
|
||||
return FALSE;
|
||||
|
||||
/* Find and validate all memories */
|
||||
for (i = 0; i < n_planes; i++) {
|
||||
guint length;
|
||||
guint mem_idx;
|
||||
gsize mem_skip;
|
||||
|
||||
if (!gst_buffer_find_memory (inbuf,
|
||||
GST_VIDEO_INFO_PLANE_OFFSET (&in_info, i), plane_size[i], &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 (importer->display,
|
||||
importer->entrypoint, GST_PAD_SINK, TRUE);
|
||||
|
||||
/* Now create a VASurfaceID for the buffer */
|
||||
return gst_va_dmabuf_memories_setup (importer->display, &in_info, n_planes,
|
||||
mems, fd, offset, usage_hint);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_try_import_buffer (GstVaBufferImporter * importer, GstBuffer * inbuf)
|
||||
{
|
||||
VASurfaceID surface;
|
||||
gboolean ret;
|
||||
|
||||
surface = gst_va_buffer_get_surface (inbuf);
|
||||
if (surface != VA_INVALID_ID &&
|
||||
(gst_va_buffer_peek_display (inbuf) == importer->display))
|
||||
return TRUE;
|
||||
|
||||
g_rec_mutex_lock (&GST_VA_SHARED_LOCK);
|
||||
ret = _try_import_dmabuf_unlocked (importer, inbuf);
|
||||
g_rec_mutex_unlock (&GST_VA_SHARED_LOCK);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
GstFlowReturn
|
||||
gst_va_buffer_importer_import (GstVaBufferImporter * importer,
|
||||
GstBuffer * inbuf, GstBuffer ** outbuf)
|
||||
{
|
||||
GstBuffer *buffer = NULL;
|
||||
GstBufferPool *pool;
|
||||
GstFlowReturn ret;
|
||||
GstVideoFrame in_frame, out_frame;
|
||||
gboolean imported, copied;
|
||||
|
||||
imported = _try_import_buffer (importer, inbuf);
|
||||
if (imported) {
|
||||
*outbuf = gst_buffer_ref (inbuf);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
/* input buffer doesn't come from a vapool, thus it is required to
|
||||
* have a pool, grab from it a new buffer and copy the input
|
||||
* buffer to the new one */
|
||||
if (!(pool = importer->get_sinkpad_pool (importer->element,
|
||||
importer->pool_data)))
|
||||
return GST_FLOW_ERROR;
|
||||
|
||||
ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);
|
||||
if (ret != GST_FLOW_OK)
|
||||
return ret;
|
||||
|
||||
GST_LOG_OBJECT (importer->element, "copying input frame");
|
||||
|
||||
if (!gst_video_frame_map (&in_frame, importer->in_info, inbuf, GST_MAP_READ))
|
||||
goto invalid_buffer;
|
||||
|
||||
if (!gst_video_frame_map (&out_frame, importer->sinkpad_info, buffer,
|
||||
GST_MAP_WRITE)) {
|
||||
gst_video_frame_unmap (&in_frame);
|
||||
goto invalid_buffer;
|
||||
}
|
||||
|
||||
copied = gst_video_frame_copy (&out_frame, &in_frame);
|
||||
|
||||
gst_video_frame_unmap (&out_frame);
|
||||
gst_video_frame_unmap (&in_frame);
|
||||
|
||||
if (!copied)
|
||||
goto invalid_buffer;
|
||||
|
||||
if (!gst_buffer_copy_into (buffer, inbuf, GST_BUFFER_COPY_FLAGS |
|
||||
GST_BUFFER_COPY_TIMESTAMPS, 0, -1)) {
|
||||
GST_WARNING_OBJECT (importer->element,
|
||||
"Couldn't import buffer flags and timestamps");
|
||||
}
|
||||
|
||||
*outbuf = buffer;
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
invalid_buffer:
|
||||
{
|
||||
GST_ELEMENT_WARNING (importer->element, STREAM, FORMAT, (NULL),
|
||||
("invalid video buffer received"));
|
||||
if (buffer)
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
48
subprojects/gst-plugins-bad/sys/va/gstvabase.h
Normal file
48
subprojects/gst-plugins-bad/sys/va/gstvabase.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2021 Igalia, S.L.
|
||||
* Author: Víctor Jáquez <vjaquez@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include <gst/va/gstva.h>
|
||||
|
||||
typedef struct _GstVaBufferImporter GstVaBufferImporter;
|
||||
|
||||
typedef GstBufferPool *(*GstVaBufferImporterGetSinkPool) (GstElement * element, gpointer data);
|
||||
|
||||
struct _GstVaBufferImporter
|
||||
{
|
||||
GstElement *element;
|
||||
GstDebugCategory *debug_category;
|
||||
|
||||
GstVaDisplay *display;
|
||||
VAEntrypoint entrypoint;
|
||||
|
||||
GstVideoInfo *in_info;
|
||||
GstVideoInfo *sinkpad_info;
|
||||
|
||||
gpointer pool_data;
|
||||
GstVaBufferImporterGetSinkPool get_sinkpad_pool;
|
||||
};
|
||||
|
||||
GstFlowReturn gst_va_buffer_importer_import (GstVaBufferImporter * base,
|
||||
GstBuffer * inbuf,
|
||||
GstBuffer ** outbuf);
|
|
@ -25,6 +25,7 @@
|
|||
#include <gst/va/gstvavideoformat.h>
|
||||
|
||||
#include "vacompat.h"
|
||||
#include "gstvabase.h"
|
||||
#include "gstvacaps.h"
|
||||
#include "gstvapluginutils.h"
|
||||
|
||||
|
@ -195,8 +196,9 @@ gst_va_base_enc_get_caps (GstVideoEncoder * venc, GstCaps * filter)
|
|||
}
|
||||
|
||||
static GstBufferPool *
|
||||
_get_sinkpad_pool (GstVaBaseEnc * base)
|
||||
_get_sinkpad_pool (GstElement * element, gpointer data)
|
||||
{
|
||||
GstVaBaseEnc *base = GST_VA_BASE_ENC (element);
|
||||
GstAllocator *allocator;
|
||||
GstAllocationParams params = { 0, };
|
||||
guint size, usage_hint;
|
||||
|
@ -273,170 +275,25 @@ _get_sinkpad_pool (GstVaBaseEnc * base)
|
|||
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
|
||||
_try_import_buffer (GstVaBaseEnc * base, GstBuffer * inbuf)
|
||||
{
|
||||
VASurfaceID surface;
|
||||
gboolean ret;
|
||||
|
||||
/* The VA buffer. */
|
||||
surface = gst_va_buffer_get_surface (inbuf);
|
||||
if (surface != VA_INVALID_ID &&
|
||||
(gst_va_buffer_peek_display (inbuf) == base->display))
|
||||
return TRUE;
|
||||
|
||||
g_rec_mutex_lock (&GST_VA_SHARED_LOCK);
|
||||
ret = _try_import_dmabuf_unlocked (base, inbuf);
|
||||
g_rec_mutex_unlock (&GST_VA_SHARED_LOCK);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_va_base_enc_import_input_buffer (GstVaBaseEnc * base,
|
||||
GstBuffer * inbuf, GstBuffer ** buf)
|
||||
{
|
||||
GstBuffer *buffer = NULL;
|
||||
GstBufferPool *pool;
|
||||
GstFlowReturn ret;
|
||||
GstVideoFrame in_frame, out_frame;
|
||||
gboolean imported, copied;
|
||||
GstVaBufferImporter importer = {
|
||||
.element = GST_ELEMENT_CAST (base),
|
||||
#ifndef GST_DISABLE_GST_DEBUG
|
||||
.debug_category = GST_CAT_DEFAULT,
|
||||
#endif
|
||||
.display = base->display,
|
||||
.entrypoint = GST_VA_BASE_ENC_ENTRYPOINT (base),
|
||||
.in_info = &base->input_state->info,
|
||||
.sinkpad_info = &base->priv->sinkpad_info,
|
||||
.get_sinkpad_pool = _get_sinkpad_pool,
|
||||
};
|
||||
|
||||
imported = _try_import_buffer (base, inbuf);
|
||||
if (imported) {
|
||||
*buf = gst_buffer_ref (inbuf);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
g_return_val_if_fail (GST_IS_VA_BASE_ENC (base), GST_FLOW_ERROR);
|
||||
|
||||
/* input buffer doesn't come from a vapool, thus it is required to
|
||||
* have a pool, grab from it a new buffer and copy the input
|
||||
* buffer to the new one */
|
||||
if (!(pool = _get_sinkpad_pool (base)))
|
||||
return GST_FLOW_ERROR;
|
||||
|
||||
ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);
|
||||
if (ret != GST_FLOW_OK)
|
||||
return ret;
|
||||
|
||||
GST_LOG_OBJECT (base, "copying input frame");
|
||||
|
||||
if (!gst_video_frame_map (&in_frame, &base->input_state->info,
|
||||
inbuf, GST_MAP_READ))
|
||||
goto invalid_buffer;
|
||||
if (!gst_video_frame_map (&out_frame, &base->priv->sinkpad_info, buffer,
|
||||
GST_MAP_WRITE)) {
|
||||
gst_video_frame_unmap (&in_frame);
|
||||
goto invalid_buffer;
|
||||
}
|
||||
|
||||
copied = gst_video_frame_copy (&out_frame, &in_frame);
|
||||
|
||||
gst_video_frame_unmap (&out_frame);
|
||||
gst_video_frame_unmap (&in_frame);
|
||||
|
||||
if (!copied)
|
||||
goto invalid_buffer;
|
||||
|
||||
/* strictly speaking this is not needed but let's play safe */
|
||||
if (!gst_buffer_copy_into (buffer, inbuf, GST_BUFFER_COPY_FLAGS |
|
||||
GST_BUFFER_COPY_TIMESTAMPS, 0, -1))
|
||||
return GST_FLOW_ERROR;
|
||||
|
||||
*buf = buffer;
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
invalid_buffer:
|
||||
{
|
||||
GST_ELEMENT_WARNING (base, CORE, NOT_IMPLEMENTED, (NULL),
|
||||
("invalid video buffer received"));
|
||||
if (buffer)
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
return gst_va_buffer_importer_import (&importer, inbuf, buf);
|
||||
}
|
||||
|
||||
static GstBuffer *
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <gst/va/gstvavideoformat.h>
|
||||
#include <gst/va/vasurfaceimage.h>
|
||||
|
||||
#include "gstvabase.h"
|
||||
#include "gstvacaps.h"
|
||||
#include "gstvapluginutils.h"
|
||||
|
||||
|
@ -80,8 +81,6 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstVaBaseTransform, gst_va_base_transform,
|
|||
"vabasetransform", 0, "vabasetransform element");
|
||||
);
|
||||
|
||||
extern GRecMutex GST_VA_SHARED_LOCK;
|
||||
|
||||
static void
|
||||
gst_va_base_transform_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
|
@ -700,90 +699,6 @@ gst_va_base_transform_allocator_from_caps (GstVaBaseTransform * self,
|
|||
return allocator;
|
||||
}
|
||||
|
||||
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 (GstVaBaseTransform * self, GstBuffer * inbuf)
|
||||
{
|
||||
GstVaBaseTransform *btrans = GST_VA_BASE_TRANSFORM (self);
|
||||
GstVideoMeta *meta;
|
||||
GstVideoInfo in_info = btrans->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 (self->display,
|
||||
VAEntrypointVideoProc, GST_PAD_SINK, TRUE);
|
||||
|
||||
/* Now create a VASurfaceID for the buffer */
|
||||
return gst_va_dmabuf_memories_setup (btrans->display, &in_info, n_planes,
|
||||
mems, fd, offset, usage_hint);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_check_uncropped_size (GstVaBaseTransform * self, GstBuffer * inbuf)
|
||||
{
|
||||
|
@ -831,21 +746,15 @@ _check_uncropped_size (GstVaBaseTransform * self, GstBuffer * inbuf)
|
|||
}
|
||||
|
||||
static GstBufferPool *
|
||||
_get_sinkpad_pool (GstVaBaseTransform * self, GstBuffer * inbuf)
|
||||
_get_sinkpad_pool (GstElement * element, gpointer data)
|
||||
{
|
||||
GstVaBaseTransform *self = GST_VA_BASE_TRANSFORM (element);
|
||||
GstAllocator *allocator;
|
||||
GstAllocationParams params = { 0, };
|
||||
GstCaps *caps;
|
||||
GstVideoInfo in_info;
|
||||
guint size, usage_hint;
|
||||
|
||||
if (_check_uncropped_size (self, inbuf)) {
|
||||
if (self->priv->sinkpad_pool)
|
||||
gst_buffer_pool_set_active (self->priv->sinkpad_pool, FALSE);
|
||||
|
||||
gst_clear_object (&self->priv->sinkpad_pool);
|
||||
}
|
||||
|
||||
if (self->priv->sinkpad_pool)
|
||||
return self->priv->sinkpad_pool;
|
||||
|
||||
|
@ -933,24 +842,6 @@ _get_sinkpad_pool (GstVaBaseTransform * self, GstBuffer * inbuf)
|
|||
return self->priv->sinkpad_pool;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_try_import_buffer (GstVaBaseTransform * self, GstBuffer * inbuf)
|
||||
{
|
||||
VASurfaceID surface;
|
||||
gboolean ret;
|
||||
|
||||
surface = gst_va_buffer_get_surface (inbuf);
|
||||
if (surface != VA_INVALID_ID &&
|
||||
(gst_va_buffer_peek_display (inbuf) == self->display))
|
||||
return TRUE;
|
||||
|
||||
g_rec_mutex_lock (&GST_VA_SHARED_LOCK);
|
||||
ret = _try_import_dmabuf_unlocked (self, inbuf);
|
||||
g_rec_mutex_unlock (&GST_VA_SHARED_LOCK);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstVaBaseTransform *self;
|
||||
|
@ -992,70 +883,43 @@ GstFlowReturn
|
|||
gst_va_base_transform_import_buffer (GstVaBaseTransform * self,
|
||||
GstBuffer * inbuf, GstBuffer ** buf)
|
||||
{
|
||||
GstBuffer *buffer = NULL;
|
||||
GstBufferPool *pool;
|
||||
GstVaBufferImporter importer = {
|
||||
.element = GST_ELEMENT_CAST (self),
|
||||
#ifndef GST_DISABLE_GST_DEBUG
|
||||
.debug_category = GST_CAT_DEFAULT,
|
||||
#endif
|
||||
.display = self->display,
|
||||
.entrypoint = VAEntrypointVideoProc,
|
||||
.in_info = &self->in_info,
|
||||
.sinkpad_info = &self->priv->sinkpad_info,
|
||||
.get_sinkpad_pool = _get_sinkpad_pool,
|
||||
};
|
||||
GstFlowReturn ret;
|
||||
GstVideoFrame in_frame, out_frame;
|
||||
gboolean imported, copied;
|
||||
CopyMetaData data;
|
||||
|
||||
g_return_val_if_fail (GST_IS_VA_BASE_TRANSFORM (self), GST_FLOW_ERROR);
|
||||
|
||||
imported = _try_import_buffer (self, inbuf);
|
||||
if (imported) {
|
||||
*buf = gst_buffer_ref (inbuf);
|
||||
return GST_FLOW_OK;
|
||||
if (_check_uncropped_size (self, inbuf)) {
|
||||
if (self->priv->sinkpad_pool)
|
||||
gst_buffer_pool_set_active (self->priv->sinkpad_pool, FALSE);
|
||||
|
||||
gst_clear_object (&self->priv->sinkpad_pool);
|
||||
}
|
||||
|
||||
/* input buffer doesn't come from a vapool, thus it is required to
|
||||
* have a pool, grab from it a new buffer and copy the input
|
||||
* buffer to the new one */
|
||||
if (!(pool = _get_sinkpad_pool (self, inbuf)))
|
||||
return GST_FLOW_ERROR;
|
||||
|
||||
ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);
|
||||
ret = gst_va_buffer_importer_import (&importer, inbuf, buf);
|
||||
if (ret != GST_FLOW_OK)
|
||||
return ret;
|
||||
goto bail;
|
||||
|
||||
GST_LOG_OBJECT (self, "copying input frame");
|
||||
|
||||
if (!gst_video_frame_map (&in_frame, &self->in_info, inbuf, GST_MAP_READ))
|
||||
goto invalid_buffer;
|
||||
|
||||
if (!gst_video_frame_map (&out_frame, &self->priv->sinkpad_info, buffer,
|
||||
GST_MAP_WRITE)) {
|
||||
gst_video_frame_unmap (&in_frame);
|
||||
goto invalid_buffer;
|
||||
}
|
||||
|
||||
copied = gst_video_frame_copy (&out_frame, &in_frame);
|
||||
|
||||
gst_video_frame_unmap (&out_frame);
|
||||
gst_video_frame_unmap (&in_frame);
|
||||
|
||||
if (!copied)
|
||||
goto invalid_buffer;
|
||||
|
||||
gst_buffer_copy_into (buffer, inbuf,
|
||||
GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
|
||||
if (*buf == inbuf)
|
||||
goto bail;
|
||||
|
||||
data.self = self;
|
||||
data.outbuf = buffer;
|
||||
data.outbuf = *buf;
|
||||
|
||||
gst_buffer_foreach_meta (inbuf, foreach_metadata, &data);
|
||||
|
||||
*buf = buffer;
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
invalid_buffer:
|
||||
{
|
||||
GST_ELEMENT_WARNING (self, STREAM, FORMAT, (NULL),
|
||||
("invalid video buffer received"));
|
||||
if (buffer)
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
bail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
GstCaps *
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include <gst/video/video.h>
|
||||
#include <va/va_drmcommon.h>
|
||||
|
||||
#include "gstvabase.h"
|
||||
#include "gstvacaps.h"
|
||||
#include "gstvadisplay_priv.h"
|
||||
#include "gstvafilter.h"
|
||||
|
@ -794,8 +795,10 @@ gst_va_compositor_decide_allocation (GstAggregator * agg, GstQuery * query)
|
|||
}
|
||||
|
||||
static GstBufferPool *
|
||||
_get_sinkpad_pool (GstVaCompositor * self, GstVaCompositorPad * pad)
|
||||
_get_sinkpad_pool (GstElement * element, gpointer data)
|
||||
{
|
||||
GstVaCompositor *self = GST_VA_COMPOSITOR (element);
|
||||
GstVaCompositorPad *pad = GST_VA_COMPOSITOR_PAD (data);
|
||||
GstAllocator *allocator;
|
||||
GstAllocationParams params = { 0, };
|
||||
GstCaps *caps;
|
||||
|
@ -851,121 +854,22 @@ _get_sinkpad_pool (GstVaCompositor * self, GstVaCompositorPad * pad)
|
|||
return pad->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 (GstVaCompositor * self, GstVideoInfo * info,
|
||||
GstBuffer * inbuf)
|
||||
{
|
||||
GstVideoMeta *meta;
|
||||
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 (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 (info) = meta->width;
|
||||
GST_VIDEO_INFO_HEIGHT (info) = meta->height;
|
||||
|
||||
for (i = 0; i < meta->n_planes; i++) {
|
||||
GST_VIDEO_INFO_PLANE_OFFSET (info, i) = meta->offset[i];
|
||||
GST_VIDEO_INFO_PLANE_STRIDE (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 (info, i);
|
||||
|
||||
if (!gst_buffer_find_memory (inbuf, 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 (self->display,
|
||||
VAEntrypointVideoProc, GST_PAD_SINK, TRUE);
|
||||
|
||||
/* Now create a VASurfaceID for the buffer */
|
||||
return gst_va_dmabuf_memories_setup (self->display, info, n_planes,
|
||||
mems, fd, offset, usage_hint);
|
||||
}
|
||||
|
||||
extern GRecMutex GST_VA_SHARED_LOCK;
|
||||
|
||||
static gboolean
|
||||
_try_import_buffer (GstVaCompositor * self, GstVideoInfo * info,
|
||||
GstBuffer * inbuf)
|
||||
{
|
||||
VASurfaceID surface;
|
||||
gboolean ret;
|
||||
|
||||
surface = gst_va_buffer_get_surface (inbuf);
|
||||
if (surface != VA_INVALID_ID &&
|
||||
(gst_va_buffer_peek_display (inbuf) == self->display))
|
||||
return TRUE;
|
||||
|
||||
g_rec_mutex_lock (&GST_VA_SHARED_LOCK);
|
||||
ret = _try_import_dmabuf_unlocked (self, info, inbuf);
|
||||
g_rec_mutex_unlock (&GST_VA_SHARED_LOCK);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_va_compositor_import_buffer (GstVaCompositor * self,
|
||||
GstVaCompositorPad * pad, GstBuffer * inbuf, GstBuffer ** buf)
|
||||
{
|
||||
GstBuffer *buffer = NULL;
|
||||
GstBufferPool *pool;
|
||||
GstFlowReturn ret;
|
||||
GstVaBufferImporter importer = {
|
||||
.element = GST_ELEMENT_CAST (self),
|
||||
#ifndef GST_DISABLE_GST_DEBUG
|
||||
.debug_category = GST_CAT_DEFAULT,
|
||||
#endif
|
||||
.display = self->display,
|
||||
.entrypoint = VAEntrypointVideoProc,
|
||||
.get_sinkpad_pool = _get_sinkpad_pool,
|
||||
.pool_data = pad,
|
||||
};
|
||||
GstCaps *caps;
|
||||
GstVideoInfo info;
|
||||
GstVideoFrame in_frame, out_frame;
|
||||
gboolean imported, copied;
|
||||
|
||||
caps = gst_pad_get_current_caps (GST_PAD (pad));
|
||||
if (!caps)
|
||||
|
@ -977,52 +881,9 @@ gst_va_compositor_import_buffer (GstVaCompositor * self,
|
|||
}
|
||||
gst_caps_unref (caps);
|
||||
|
||||
imported = _try_import_buffer (self, &info, inbuf);
|
||||
if (imported) {
|
||||
*buf = gst_buffer_ref (inbuf);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
importer.in_info = importer.sinkpad_info = &info;
|
||||
|
||||
GST_LOG_OBJECT (self, "copying input frame");
|
||||
|
||||
/* input buffer doesn't come from a vapool, thus it is required to
|
||||
* have a pool, grab from it a new buffer and copy the input
|
||||
* buffer to the new one */
|
||||
if (!(pool = _get_sinkpad_pool (self, pad)))
|
||||
return GST_FLOW_ERROR;
|
||||
|
||||
ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);
|
||||
if (ret != GST_FLOW_OK)
|
||||
return ret;
|
||||
|
||||
if (!gst_video_frame_map (&in_frame, &info, inbuf, GST_MAP_READ))
|
||||
goto invalid_buffer;
|
||||
|
||||
if (!gst_video_frame_map (&out_frame, &info, buffer, GST_MAP_WRITE)) {
|
||||
gst_video_frame_unmap (&in_frame);
|
||||
goto invalid_buffer;
|
||||
}
|
||||
|
||||
copied = gst_video_frame_copy (&out_frame, &in_frame);
|
||||
|
||||
gst_video_frame_unmap (&out_frame);
|
||||
gst_video_frame_unmap (&in_frame);
|
||||
|
||||
if (!copied)
|
||||
goto invalid_buffer;
|
||||
|
||||
*buf = buffer;
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
invalid_buffer:
|
||||
{
|
||||
GST_ELEMENT_WARNING (self, CORE, NOT_IMPLEMENTED, (NULL),
|
||||
("invalid video buffer received"));
|
||||
if (buffer)
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
return gst_va_buffer_importer_import (&importer, inbuf, buf);
|
||||
}
|
||||
|
||||
typedef struct _GstVaCompositorSampleGenerator GstVaCompositorSampleGenerator;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
va_sources = [
|
||||
'plugin.c',
|
||||
'gstjpegdecoder.c',
|
||||
'gstvabase.c',
|
||||
'gstvabasedec.c',
|
||||
'gstvabasetransform.c',
|
||||
'gstvabaseenc.c',
|
||||
|
|
|
@ -47,10 +47,6 @@
|
|||
#define GST_CAT_DEFAULT gstva_debug
|
||||
GST_DEBUG_CATEGORY (gstva_debug);
|
||||
|
||||
/* big bad mutex to exclusive access to shared stream buffers, such as
|
||||
* DMABuf after a tee */
|
||||
GRecMutex GST_VA_SHARED_LOCK = { 0, };
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
/* Windows support is still experimental */
|
||||
#define GST_VA_RANK_PRIMARY GST_RANK_NONE
|
||||
|
|
Loading…
Reference in a new issue