Updating prebuilts and/or headers

44b0e909f18f7e2f457ba501fc47d80ecedd150b - nvbufsurface.h
9a172f748a2b8f4d6d15648ea353989ccc7aeba6 - gst-plugins-nv-video-sinks/Makefile
9825d8a113dbf7dd16f791ff1ca66f2de3047b22 - gst-plugins-nv-video-sinks/LICENSE.libgstnvvideosinks
7ef56486c9e6b3e354473a2959d274517dd709da - gst-plugins-nv-video-sinks/gstnvvideosinks.c
15221adcd6193b5e2c1b38cba595d48e2da6a43f - gst-plugins-nv-video-sinks/nv3dsink/gstnv3dsink.c
9b7125a2d7ebe2ea647c43d2eb43e8d04cd16c47 - gst-plugins-nv-video-sinks/nv3dsink/gstnv3dsink.h
835dc89a20f2a95bea9c4033e40bf6787148ab08 - gst-plugins-nv-video-sinks/common/window.c
a52c6765b04d69f754e5aeaa8c17f83747124150 - gst-plugins-nv-video-sinks/common/display.c
96b0b4d38692a0aecf70944749684ac938ff192f - gst-plugins-nv-video-sinks/common/display.h
718a740b0d05eeaf159bc13b6734485fd065da8e - gst-plugins-nv-video-sinks/common/renderer.c
6e77d54ffc5d1a49d5bad768cdf5cfadf458f1f7 - gst-plugins-nv-video-sinks/common/window.h
9509626b9f2d25a07ceb91b524c604089812cebb - gst-plugins-nv-video-sinks/common/context.c
9d31e8f421736ac5bd8e166db190965bf3a5e472 - gst-plugins-nv-video-sinks/common/renderer.h
d48e1dae85e3c6a0ba7623be7ee306b8e1ef6695 - gst-plugins-nv-video-sinks/common/gstnvvideofwd.h
bcce8e13c6a9efb1ee2d2a8ec24e8f7acc7c6581 - gst-plugins-nv-video-sinks/common/context.h
1e8544869e1b3720d712cc655b602f1a7559eff7 - gst-plugins-nv-video-sinks/common/renderer/renderer_gl.c
f528404a796de5a23dab281588feb72f42343e59 - gst-plugins-nv-video-sinks/common/renderer/renderer_gl.h
1e324349b3704719f411b2da8f201ffb30e89c88 - gst-plugins-nv-video-sinks/common/egl/context_egl.c
536a072a8ef84b3c91307777f88121fb88df2c4f - gst-plugins-nv-video-sinks/common/egl/context_egl.h
b3f1b67cae0b4643f6a676b362ceaa61abc9c40f - gst-plugins-nv-video-sinks/common/x11/display_x11.c
d692399c6d94dbc7814770b08baf9271ed97f8e0 - gst-plugins-nv-video-sinks/common/x11/display_x11.h
c98945083e215dff26507c1e10b0ebf62a2c6fb7 - gst-plugins-nv-video-sinks/common/x11/window_x11.c
638b0da4ea65d02818289e89bc1d635ddbcdaec5 - gst-plugins-nv-video-sinks/common/x11/window_x11.h

Change-Id: I21ac756443e936aef0b7fbb8c9513a28182af74c
This commit is contained in:
svcmobrel-release
2025-08-25 10:25:21 -07:00
parent c64ebd08a3
commit 43b7ad2992
26 changed files with 5970 additions and 0 deletions

25
commitFile.txt Normal file
View File

@@ -0,0 +1,25 @@
Updating prebuilts and/or headers
44b0e909f18f7e2f457ba501fc47d80ecedd150b - nvbufsurface.h
9a172f748a2b8f4d6d15648ea353989ccc7aeba6 - gst-plugins-nv-video-sinks/Makefile
9825d8a113dbf7dd16f791ff1ca66f2de3047b22 - gst-plugins-nv-video-sinks/LICENSE.libgstnvvideosinks
7ef56486c9e6b3e354473a2959d274517dd709da - gst-plugins-nv-video-sinks/gstnvvideosinks.c
15221adcd6193b5e2c1b38cba595d48e2da6a43f - gst-plugins-nv-video-sinks/nv3dsink/gstnv3dsink.c
9b7125a2d7ebe2ea647c43d2eb43e8d04cd16c47 - gst-plugins-nv-video-sinks/nv3dsink/gstnv3dsink.h
835dc89a20f2a95bea9c4033e40bf6787148ab08 - gst-plugins-nv-video-sinks/common/window.c
a52c6765b04d69f754e5aeaa8c17f83747124150 - gst-plugins-nv-video-sinks/common/display.c
96b0b4d38692a0aecf70944749684ac938ff192f - gst-plugins-nv-video-sinks/common/display.h
718a740b0d05eeaf159bc13b6734485fd065da8e - gst-plugins-nv-video-sinks/common/renderer.c
6e77d54ffc5d1a49d5bad768cdf5cfadf458f1f7 - gst-plugins-nv-video-sinks/common/window.h
9509626b9f2d25a07ceb91b524c604089812cebb - gst-plugins-nv-video-sinks/common/context.c
9d31e8f421736ac5bd8e166db190965bf3a5e472 - gst-plugins-nv-video-sinks/common/renderer.h
d48e1dae85e3c6a0ba7623be7ee306b8e1ef6695 - gst-plugins-nv-video-sinks/common/gstnvvideofwd.h
bcce8e13c6a9efb1ee2d2a8ec24e8f7acc7c6581 - gst-plugins-nv-video-sinks/common/context.h
1e8544869e1b3720d712cc655b602f1a7559eff7 - gst-plugins-nv-video-sinks/common/renderer/renderer_gl.c
f528404a796de5a23dab281588feb72f42343e59 - gst-plugins-nv-video-sinks/common/renderer/renderer_gl.h
1e324349b3704719f411b2da8f201ffb30e89c88 - gst-plugins-nv-video-sinks/common/egl/context_egl.c
536a072a8ef84b3c91307777f88121fb88df2c4f - gst-plugins-nv-video-sinks/common/egl/context_egl.h
b3f1b67cae0b4643f6a676b362ceaa61abc9c40f - gst-plugins-nv-video-sinks/common/x11/display_x11.c
d692399c6d94dbc7814770b08baf9271ed97f8e0 - gst-plugins-nv-video-sinks/common/x11/display_x11.h
c98945083e215dff26507c1e10b0ebf62a2c6fb7 - gst-plugins-nv-video-sinks/common/x11/window_x11.c
638b0da4ea65d02818289e89bc1d635ddbcdaec5 - gst-plugins-nv-video-sinks/common/x11/window_x11.h

View File

@@ -0,0 +1,23 @@
The software listed below is licensed under the terms of the LGPLv2.1
(see below). To obtain source code, contact oss-requests@nvidia.com.
libgstnvvideosinks (libgstnvvideosinks.so)
------------------------------------
/*
* Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/

View File

@@ -0,0 +1,78 @@
###############################################################################
#
# Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved.
#
# NVIDIA Corporation and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA Corporation is strictly prohibited.
#
###############################################################################
ifneq ($(MAKECMDGOALS),install)
ifeq ($(CUDA_VER),)
$(error "CUDA_VER is not set. Set it by running - "export CUDA_VER=<cuda-version>"")
endif
endif
SO_NAME := libgstnvvideosinks.so
DEST_DIR ?= /usr/lib/aarch64-linux-gnu/gstreamer-1.0
SRCS := common/context.c \
common/display.c \
common/egl/context_egl.c \
common/renderer.c \
common/renderer/renderer_gl.c \
common/window.c \
common/x11/display_x11.c \
common/x11/window_x11.c \
gstnvvideosinks.c \
nv3dsink/gstnv3dsink.c
INCLUDES += -I./common \
-I./common/egl \
-I./common/renderer \
-I./common/x11 \
-I/usr/local/include/gstreamer-1.0 \
-I/usr/local/cuda-$(CUDA_VER)/targets/aarch64-linux/include/ \
-I../
PKGS := glib-2.0 \
gstreamer-1.0 \
gstreamer-base-1.0 \
gstreamer-video-1.0
OBJS := $(SRCS:.c=.o)
CFLAGS := -fPIC \
-DNV_VIDEO_SINKS_HAS_EGL \
-DNV_VIDEO_SINKS_HAS_GL \
-DNV_VIDEO_SINKS_HAS_NV3DSINK \
-DNV_VIDEO_SINKS_HAS_X11
CFLAGS += `pkg-config --cflags $(PKGS)`
LDFLAGS = -Wl,--no-undefined -L/usr/lib/aarch64-linux-gnu/tegra -L/usr/local/cuda-$(CUDA_VER)/targets/aarch64-linux/lib/
LIBS = -lnvbufsurface -lGLESv2 -lEGL -lX11 -lm -lcuda -lcudart
LIBS += `pkg-config --libs $(PKGS)`
all: $(SO_NAME)
%.o: %.c
$(CC) -c $< $(CFLAGS) $(INCLUDES) -o $@
$(SO_NAME): $(OBJS)
$(CC) -shared -o $(SO_NAME) $(OBJS) $(LIBS) $(LDFLAGS)
.PHONY: install
$(DEST_DIR):
mkdir -p $(DEST_DIR)
install: $(SO_NAME) | $(DEST_DIR)
cp -vp $(SO_NAME) $(DEST_DIR)
.PHONY: clean
clean:
rm -rf $(OBJS) $(SO_NAME)

View File

@@ -0,0 +1,38 @@
###############################################################################
#
# Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved.
#
# NVIDIA Corporation and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA Corporation is strictly prohibited.
#
###############################################################################
Steps to compile the "gst-plugins-nv-video-sinks" sources:
1) Install gstreamer related packages using the command:
sudo apt-get install gstreamer1.0-tools gstreamer1.0-alsa \
gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \
gstreamer1.0-libav libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev libegl1-mesa-dev
2) Install CUDA Runtime 10.0+
3) Extract the package "libgstnvvideosinks_src.tbz2" as follow:
tar xvjf libgstnvvideosinks_src.tbz2`
4) cd "gst-plugins-nv-video-sinks"
5) Export the appropriate CUDA_VER using - "export CUDA_VER=<cuda-version>"
5) run "make" to create "libgstnvvideosinks.so"
6) run "sudo make install" to install "libgstnvvideosinks.so" in
"/usr/lib/aarch64-linux-gnu/gstreamer-1.0".
7) run "make install DEST_DIR=<location>" to install at different <location>.

View File

@@ -0,0 +1,544 @@
/*
* SPDX-FileCopyrightText: Copyright (c) <2018-2025> NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: LGPL-2.1-only
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <gst/base/gstdataqueue.h>
#include "context.h"
#include "window.h"
#if NV_VIDEO_SINKS_HAS_EGL
#include "context_egl.h"
#endif
#define GST_CAT_DEFAULT gst_debug_nv_video_context
GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
struct _GstNvVideoContextPrivate
{
GstDataQueue *queue;
GThread *render_thread;
gboolean render_thread_active;
gboolean eos_handled;
GstFlowReturn last_ret;
GMutex render_lock;
GCond create_cond;
GCond quit_cond;
GCond eos_cond;
};
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstNvVideoContext, gst_nv_video_context,
GST_TYPE_OBJECT, G_ADD_PRIVATE(GstNvVideoContext));
GstNvVideoContextType
gst_nv_video_context_get_handle_type (GstNvVideoContext * context)
{
g_return_val_if_fail (GST_IS_NV_VIDEO_CONTEXT (context),
GST_NV_VIDEO_CONTEXT_TYPE_NONE);
return context->type;
}
static gpointer
gst_nv_video_context_render_thread_func (GstNvVideoContext * context)
{
GstNvVideoContextClass *context_class;
GstDataQueueItem *item = NULL;
GstFlowReturn ret = GST_FLOW_OK;
context_class = GST_NV_VIDEO_CONTEXT_GET_CLASS (context);
GST_DEBUG_OBJECT (context, "render thread started");
context_class->setup (context);
cudaError_t CUerr = cudaSuccess;
GST_LOG_OBJECT (context, "SETTING CUDA DEVICE = %d in func=%s\n", context->gpu_id, __func__);
CUerr = cudaSetDevice(context->gpu_id);
if (CUerr != cudaSuccess) {
GST_LOG_OBJECT (context,"\n *** Unable to set device in %s Line %d\n", __func__, __LINE__);
return NULL;
}
g_mutex_lock (&context->priv->render_lock);
context->priv->render_thread_active = TRUE;
context->priv->last_ret = ret;
g_cond_signal (&context->priv->create_cond);
g_mutex_unlock (&context->priv->render_lock);
while (gst_data_queue_pop (context->priv->queue, &item)) {
GstMiniObject *object = item->object;
GstBuffer *buf = NULL;
GST_TRACE_OBJECT (context,
"render thread: got data queue item %" GST_PTR_FORMAT, object);
ret = GST_FLOW_ERROR;
if (GST_IS_CAPS (object)) {
GstCaps *caps = GST_CAPS_CAST (object);
/* Check if caps have changed */
if (context->configured_caps) {
if (!gst_caps_is_equal (caps, context->configured_caps)) {
/* Reset CUDA initialization for re-initialization with new caps */
if (context->is_cuda_init) {
GstNvVideoContextClass *ctx_class = GST_NV_VIDEO_CONTEXT_GET_CLASS (context);
if (ctx_class->cuda_reset_resources) {
ctx_class->cuda_reset_resources (context);
}
}
}
}
/* NOW update configured caps and info (AFTER comparison) */
gst_caps_replace (&context->configured_caps, caps);
if (!gst_video_info_from_caps (&context->configured_info, caps)) {
GST_ERROR_OBJECT (context, "Invalid caps %" GST_PTR_FORMAT, caps);
ret = GST_FLOW_ERROR;
} else {
ret = GST_FLOW_OK;
}
} else if (!object) {
/* EOS signal */
GST_TRACE_OBJECT (context, "render thread: handle EOS");
context_class->handle_eos (context);
g_mutex_lock (&context->priv->render_lock);
g_cond_signal (&context->priv->eos_cond);
context->priv->eos_handled = TRUE;
g_mutex_unlock (&context->priv->render_lock);
GST_TRACE_OBJECT (context, "render thread: handled EOS");
ret = GST_FLOW_OK;
} else if (GST_IS_BUFFER (object)) {
buf = GST_BUFFER_CAST (item->object);
if (context_class->show_frame (context, buf)) {
ret = GST_FLOW_OK;
} else {
}
} else {
g_assert_not_reached ();
}
item->destroy (item);
g_mutex_lock (&context->priv->render_lock);
context->priv->last_ret = ret;
g_mutex_unlock (&context->priv->render_lock);
if (ret != GST_FLOW_OK) {
break;
}
GST_TRACE_OBJECT (context, "render thread: handled");
}
GST_DEBUG_OBJECT (context, "tearing down render thread");
context_class->cleanup (context);
g_mutex_lock (&context->priv->render_lock);
g_cond_signal (&context->priv->quit_cond);
context->priv->render_thread_active = FALSE;
g_mutex_unlock (&context->priv->render_lock);
GST_DEBUG_OBJECT (context, "render thread exit");
return NULL;
}
static void
gst_nv_video_context_queue_free_item (GstDataQueueItem * item)
{
GstDataQueueItem *data = item;
if (data->object)
gst_mini_object_unref (data->object);
g_slice_free (GstDataQueueItem, data);
}
static gboolean
gst_nv_video_context_render_thread_show_frame (GstNvVideoContext * context,
GstBuffer * buf)
{
gboolean last_ret;
GstDataQueueItem *item;
GstMiniObject *obj = GST_MINI_OBJECT_CAST (buf);
g_assert (obj);
g_mutex_lock (&context->priv->render_lock);
last_ret = context->priv->last_ret;
g_mutex_unlock (&context->priv->render_lock);
if (last_ret != GST_FLOW_OK) {
return FALSE;
}
item = g_slice_new (GstDataQueueItem);
item->destroy = (GDestroyNotify) gst_nv_video_context_queue_free_item;
item->object = gst_mini_object_ref (obj);
item->size = 0;
item->duration = GST_CLOCK_TIME_NONE;
item->visible = TRUE;
if (!gst_data_queue_push (context->priv->queue, item)) {
item->destroy (item);
return FALSE;
}
return TRUE;
}
static gboolean
gst_nv_video_context_queue_check_full (GstDataQueue * queue, guint visible,
guint bytes, guint64 time, gpointer checkdata)
{
return FALSE;
}
static void
gst_nv_video_context_finalize (GObject * object)
{
GstNvVideoContext *context = GST_NV_VIDEO_CONTEXT (object);
GST_DEBUG_OBJECT (context, "finalize begin");
if (context->priv->queue) {
g_object_unref (context->priv->queue);
context->priv->queue = NULL;
}
if (context->priv->render_thread) {
g_thread_unref (context->priv->render_thread);
context->priv->render_thread = NULL;
}
if (context->window) {
gst_object_unref (context->window);
context->window = NULL;
}
if (context->display) {
gst_object_unref (context->display);
context->display = NULL;
}
if (context->configured_caps) {
gst_caps_unref (context->configured_caps);
context->configured_caps = NULL;
}
g_mutex_clear (&context->priv->render_lock);
g_cond_clear (&context->priv->create_cond);
g_cond_clear (&context->priv->quit_cond);
g_cond_clear (&context->priv->eos_cond);
GST_DEBUG_OBJECT (context, "finalize done");
G_OBJECT_CLASS (gst_nv_video_context_parent_class)->finalize (object);
}
static void
gst_nv_video_context_init (GstNvVideoContext * context)
{
GstNvVideoContext *self = GST_NV_VIDEO_CONTEXT (context);
context->priv = (GstNvVideoContextPrivate *)gst_nv_video_context_get_instance_private (self);
g_mutex_init (&context->priv->render_lock);
g_cond_init (&context->priv->create_cond);
g_cond_init (&context->priv->quit_cond);
g_cond_init (&context->priv->eos_cond);
context->priv->queue = NULL;
context->priv->render_thread = NULL;
context->priv->render_thread_active = FALSE;
context->priv->eos_handled = FALSE;
context->using_NVMM = 0;
#if defined(NVOS_IS_L4T)
// Use this to avoid extra copy for cuda buffer.
context->cuda_optimized = 1;
#else
context->cuda_optimized = 0;
#endif
context->cuContext = NULL;
context->cuResource[0] = NULL;
context->cuResource[1] = NULL;
context->cuResource[2] = NULL;
context->gpu_id = 0;
context->configured_caps = NULL;
GST_DEBUG_OBJECT (context, "init done");
}
static void
gst_nv_video_context_class_init (GstNvVideoContextClass * klass)
{
G_OBJECT_CLASS (klass)->finalize = gst_nv_video_context_finalize;
}
GstNvVideoContext *
gst_nv_video_context_new (GstNvVideoDisplay * display)
{
GstNvVideoContext *context = NULL;
static gsize debug_init = 0;
const gchar *context_name = NULL;
if (g_once_init_enter (&debug_init)) {
GST_DEBUG_CATEGORY_INIT (gst_debug_nv_video_context, "nvvideocontext", 0,
"nvvideocontext");
g_once_init_leave (&debug_init, 1);
}
context_name = g_getenv ("GST_NV_VIDEO_CONTEXT");
#if NV_VIDEO_SINKS_HAS_EGL
if (!context && (!context_name || g_strstr_len (context_name, 3, "egl"))) {
context = GST_NV_VIDEO_CONTEXT (gst_nv_video_context_egl_new (display));
}
#endif
if (!context) {
GST_ERROR ("couldn't create context. GST_NV_VIDEO_CONTEXT = %s",
context_name ? context_name : NULL);
return NULL;
}
context->display = gst_object_ref (display);
GST_DEBUG_OBJECT (context, "created context for display %" GST_PTR_FORMAT,
display);
return context;
}
gboolean
gst_nv_video_context_show_frame (GstNvVideoContext * context, GstBuffer * buf)
{
g_mutex_lock (&context->priv->render_lock);
if (context->priv->render_thread_active) {
g_mutex_unlock (&context->priv->render_lock);
return gst_nv_video_context_render_thread_show_frame (context, buf);
}
g_mutex_unlock (&context->priv->render_lock);
return FALSE;
}
void
gst_nv_video_context_handle_tearing (GstNvVideoContext * context)
{
GstNvVideoContextClass *context_class =
GST_NV_VIDEO_CONTEXT_GET_CLASS (context);
context_class->handle_tearing (context);
return;
}
void
gst_nv_video_context_handle_drc (GstNvVideoContext * context)
{
GstNvVideoContextClass *context_class =
GST_NV_VIDEO_CONTEXT_GET_CLASS (context);
context_class->handle_drc (context);
return;
}
void
gst_nv_video_context_handle_eos (GstNvVideoContext * context)
{
GstNvVideoContextClass *context_class =
GST_NV_VIDEO_CONTEXT_GET_CLASS (context);
GstDataQueueItem *item;
g_mutex_lock (&context->priv->render_lock);
if (!context->priv->render_thread_active) {
g_mutex_unlock (&context->priv->render_lock);
context_class->handle_eos (context);
return;
}
// Push NULL object in queue to indicate EOS and wait till it is handled.
item = g_slice_new (GstDataQueueItem);
item->destroy = (GDestroyNotify) gst_nv_video_context_queue_free_item;
item->object = NULL;
item->size = 0;
item->duration = GST_CLOCK_TIME_NONE;
item->visible = TRUE;
if (!gst_data_queue_push (context->priv->queue, item)) {
GST_ERROR_OBJECT (context, "faild to send EOS to render thread");
item->destroy (item);
g_mutex_unlock (&context->priv->render_lock);
return;
}
GST_TRACE_OBJECT (context, "wait for render thread to handle EOS");
while (context->priv->render_thread_active && !context->priv->eos_handled) {
gint64 end = g_get_monotonic_time () + G_TIME_SPAN_SECOND;
g_cond_wait_until (&context->priv->eos_cond, &context->priv->render_lock, end);
}
GST_TRACE_OBJECT (context, "wait for render thread to handle EOS is done");
context->priv->eos_handled = FALSE;
g_mutex_unlock (&context->priv->render_lock);
}
GstCaps *
gst_nv_video_context_get_caps (GstNvVideoContext * context)
{
GstNvVideoContextClass *context_class;
if (!context) {
return NULL;
}
context_class = GST_NV_VIDEO_CONTEXT_GET_CLASS (context);
return context_class->get_caps (context);
}
gboolean
gst_nv_video_context_set_window (GstNvVideoContext * context,
GstNvVideoWindow * window)
{
if (context->window) {
gst_object_unref (context->window);
}
if (window) {
// Before the object's GObjectClass.dispose method is called, every
// GWeakRef associated with becomes empty.
g_weak_ref_set (&window->context, context);
}
context->window = window ? gst_object_ref (window) : NULL;
return TRUE;
}
void
gst_nv_video_context_destroy_render_thread (GstNvVideoContext * context)
{
if (context->priv->queue) {
gst_data_queue_set_flushing (context->priv->queue, TRUE);
gst_data_queue_flush (context->priv->queue);
}
g_mutex_lock (&context->priv->render_lock);
if (context->priv->render_thread_active) {
GST_DEBUG_OBJECT (context, "destroying render thread");
while (context->priv->render_thread_active) {
g_cond_wait (&context->priv->quit_cond, &context->priv->render_lock);
}
g_thread_join (context->priv->render_thread);
GST_DEBUG_OBJECT (context, "render thread destroyed");
}
g_mutex_unlock (&context->priv->render_lock);
}
gboolean
gst_nv_video_context_create_render_thread (GstNvVideoContext * context)
{
g_mutex_lock (&context->priv->render_lock);
if (!context->priv->render_thread) {
g_assert (context->priv->queue == NULL);
context->priv->queue =
gst_data_queue_new (gst_nv_video_context_queue_check_full, NULL, NULL,
NULL);
if (!context->priv->queue) {
g_mutex_unlock (&context->priv->render_lock);
return FALSE;
}
gst_data_queue_set_flushing (context->priv->queue, FALSE);
gst_data_queue_flush (context->priv->queue);
context->priv->render_thread =
g_thread_new ("NvVideoRenderThread",
(GThreadFunc) gst_nv_video_context_render_thread_func, context);
while (!context->priv->render_thread_active) {
g_cond_wait (&context->priv->create_cond, &context->priv->render_lock);
}
if (context->priv->last_ret != GST_FLOW_OK) {
g_object_unref (context->priv->queue);
context->priv->queue = NULL;
g_mutex_unlock (&context->priv->render_lock);
return FALSE;
}
GST_INFO_OBJECT (context, "render thread created");
}
g_mutex_unlock (&context->priv->render_lock);
return TRUE;
}
gboolean
gst_nv_video_context_create (GstNvVideoContext * context)
{
GstNvVideoContextClass *context_class;
context_class = GST_NV_VIDEO_CONTEXT_GET_CLASS (context);
return context_class->create (context);
}
void
gst_nv_video_context_set_configured_caps (GstNvVideoContext * context, GstCaps * caps)
{
g_return_if_fail (GST_IS_NV_VIDEO_CONTEXT (context));
/* Send caps to render thread for comparison and processing */
g_mutex_lock (&context->priv->render_lock);
if (context->priv->render_thread_active && context->priv->queue) {
GstDataQueueItem *item = g_slice_new (GstDataQueueItem);
item->destroy = (GDestroyNotify) gst_nv_video_context_queue_free_item;
item->object = gst_mini_object_ref (GST_MINI_OBJECT_CAST (caps));
item->size = 0;
item->duration = GST_CLOCK_TIME_NONE;
item->visible = TRUE;
if (!gst_data_queue_push (context->priv->queue, item)) {
item->destroy (item);
}
} else {
/* If no render thread, update directly */
gst_caps_replace (&context->configured_caps, caps);
if (!gst_video_info_from_caps (&context->configured_info, caps)) {
GST_ERROR_OBJECT (context, "Invalid caps %" GST_PTR_FORMAT, caps);
}
}
g_mutex_unlock (&context->priv->render_lock);
GST_DEBUG_OBJECT (context, "set configured caps %" GST_PTR_FORMAT, caps);
}

View File

@@ -0,0 +1,129 @@
/*
* SPDX-FileCopyrightText: Copyright (c) <2018-2025> NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: LGPL-2.1-only
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef __GST_NV_VIDEO_CONTEXT_H__
#define __GST_NV_VIDEO_CONTEXT_H__
#include <gst/gst.h>
#include <gst/video/gstvideosink.h>
#include <gst/video/video.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include "gstnvvideofwd.h"
#include <cuda.h>
#include <cudaGL.h>
#include <cuda_runtime.h>
G_BEGIN_DECLS
#define GST_TYPE_NV_VIDEO_CONTEXT \
(gst_nv_video_context_get_type())
#define GST_NV_VIDEO_CONTEXT(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_NV_VIDEO_CONTEXT, GstNvVideoContext))
#define GST_NV_VIDEO_CONTEXT_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_NV_VIDEO_CONTEXT, GstNvVideoContextClass))
#define GST_IS_NV_VIDEO_CONTEXT(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_NV_VIDEO_CONTEXT))
#define GST_IS_NV_VIDEO_CONTEXT_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_NV_VIDEO_CONTEXT))
#define GST_NV_VIDEO_CONTEXT_GET_CLASS(o) \
(G_TYPE_INSTANCE_GET_CLASS((o), GST_TYPE_NV_VIDEO_CONTEXT, GstNvVideoContextClass))
typedef enum
{
GST_NV_VIDEO_CONTEXT_TYPE_NONE = 0,
GST_NV_VIDEO_CONTEXT_TYPE_EGL = (1 << 0),
GST_NV_VIDEO_CONTEXT_TYPE_ANY = G_MAXUINT32
} GstNvVideoContextType;
struct _GstNvVideoContextClass
{
GstObjectClass parent_class;
gboolean (*create) (GstNvVideoContext * context);
gboolean (*setup) (GstNvVideoContext * context);
void (*cleanup) (GstNvVideoContext * context);
GstCaps *(*get_caps) (GstNvVideoContext * context);
gboolean (*show_frame) (GstNvVideoContext * context, GstBuffer * buf);
void (*handle_eos) (GstNvVideoContext * context);
void (*handle_drc) (GstNvVideoContext * context);
void (*handle_tearing) (GstNvVideoContext * context);
void (*cuda_reset_resources) (GstNvVideoContext * context);
};
struct _GstNvVideoContext
{
GstObject parent;
GstNvVideoDisplay *display;
GstNvVideoWindow *window;
GstNvVideoContextType type;
GstNvVideoContextPrivate *priv;
guint using_NVMM;
guint cuda_optimized;
GstVideoInfo configured_info;
gboolean is_cuda_init;
CUcontext cuContext;
CUgraphicsResource cuResource[3];
unsigned int gpu_id;
GstCaps *configured_caps;
};
GST_EXPORT
GstNvVideoContext * gst_nv_video_context_new (GstNvVideoDisplay * display);
GST_EXPORT
gboolean gst_nv_video_context_create (GstNvVideoContext * context);
GST_EXPORT
GstCaps * gst_nv_video_context_get_caps (GstNvVideoContext * context);
GST_EXPORT
gboolean gst_nv_video_context_set_window (GstNvVideoContext * context, GstNvVideoWindow * window);
GST_EXPORT
gboolean gst_nv_video_context_show_frame (GstNvVideoContext * context, GstBuffer * buf);
GST_EXPORT
void gst_nv_video_context_handle_eos (GstNvVideoContext * context);
GST_EXPORT
void gst_nv_video_context_handle_drc (GstNvVideoContext * context);
GST_EXPORT
void gst_nv_video_context_handle_tearing (GstNvVideoContext * context);
GST_EXPORT
gboolean gst_nv_video_context_create_render_thread (GstNvVideoContext * context);
GST_EXPORT
void gst_nv_video_context_destroy_render_thread (GstNvVideoContext * context);
GST_EXPORT
void gst_nv_video_context_set_configured_caps (GstNvVideoContext * context, GstCaps * caps);
GST_EXPORT
GstNvVideoContextType gst_nv_video_context_get_handle_type (GstNvVideoContext * context);
GType gst_nv_video_context_get_type (void);
G_END_DECLS
#endif /* __GST_NV_VIDEO_CONTEXT_H__ */

View File

@@ -0,0 +1,108 @@
/*
* SPDX-FileCopyrightText: Copyright (c) <2018-2025> NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: LGPL-2.1-only
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "display.h"
#include "context.h"
#include "window.h"
#if NV_VIDEO_SINKS_HAS_X11
#include "display_x11.h"
#endif
#define GST_CAT_DEFAULT gst_debug_nv_video_display
GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
G_DEFINE_ABSTRACT_TYPE (GstNvVideoDisplay, gst_nv_video_display,
GST_TYPE_OBJECT);
GstNvVideoDisplayType
gst_nv_video_display_get_handle_type (GstNvVideoDisplay * display)
{
g_return_val_if_fail (GST_IS_NV_VIDEO_DISPLAY (display),
GST_NV_VIDEO_DISPLAY_TYPE_NONE);
return display->type;
}
static void
gst_nv_video_display_init (GstNvVideoDisplay * display)
{
}
gboolean
gst_nv_video_display_create_context (GstNvVideoDisplay * display,
GstNvVideoContext ** ptr_context)
{
GstNvVideoContext *context = NULL;
g_return_val_if_fail (display != NULL, FALSE);
g_return_val_if_fail (ptr_context != NULL, FALSE);
context = gst_nv_video_context_new (display);
if (!context) {
GST_ERROR ("context creation failed");
return FALSE;
}
*ptr_context = context;
GST_DEBUG_OBJECT (display, "created context %" GST_PTR_FORMAT, context);
return TRUE;
}
GstNvVideoWindow *
gst_nv_video_display_create_window (GstNvVideoDisplay * display)
{
return gst_nv_video_window_new (display);
}
static void
gst_nv_video_display_class_init (GstNvVideoDisplayClass * klass)
{
}
gboolean
gst_nv_video_display_new (GstNvVideoDisplay ** display)
{
static gsize debug_init = 0;
const gchar *winsys_name = NULL;
if (g_once_init_enter (&debug_init)) {
GST_DEBUG_CATEGORY_INIT (gst_debug_nv_video_display, "nvvideodisplay", 0,
"nvvideodisplay");
g_once_init_leave (&debug_init, 1);
}
winsys_name = g_getenv ("GST_NV_VIDEO_WINSYS");
#if NV_VIDEO_SINKS_HAS_X11
if (!*display && (!winsys_name || g_strstr_len (winsys_name, 3, "x11"))) {
*display = GST_NV_VIDEO_DISPLAY (gst_nv_video_display_x11_new (NULL));
}
#endif
if (!*display) {
GST_ERROR ("couldn't create display. GST_NV_VIDEO_WINSYS = %s",
winsys_name ? winsys_name : NULL);
return FALSE;
}
return TRUE;
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef __GST_NV_VIDEO_DISPLAY_H__
#define __GST_NV_VIDEO_DISPLAY_H__
#include <gst/gst.h>
#include <gst/video/gstvideosink.h>
#include <gst/video/video.h>
#include "gstnvvideofwd.h"
G_BEGIN_DECLS
#define GST_TYPE_NV_VIDEO_DISPLAY \
(gst_nv_video_display_get_type())
#define GST_NV_VIDEO_DISPLAY(obj)\
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_NV_VIDEO_DISPLAY, GstNvVideoDisplay))
#define GST_NV_VIDEO_DISPLAY_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_NV_VIDEO_DISPLAY, GstNvVideoDisplayClass))
#define GST_IS_NV_VIDEO_DISPLAY(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_NV_VIDEO_DISPLAY))
#define GST_IS_NV_VIDEO_DISPLAY_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_NV_VIDEO_DISPLAY))
#define GST_NV_VIDEO_DISPLAY_CAST(obj) \
((GstNvVideoDisplay*)(obj))
#define GST_NV_VIDEO_DISPLAY_GET_CLASS(o) \
(G_TYPE_INSTANCE_GET_CLASS((o), GST_TYPE_NV_VIDEO_DISPLAY, GstNvVideoDisplayClass))
struct _GstNvVideoDisplayClass
{
GstObjectClass parent_class;
guintptr (*get_handle) (GstNvVideoDisplay * display);
};
typedef enum
{
GST_NV_VIDEO_DISPLAY_TYPE_NONE = 0,
GST_NV_VIDEO_DISPLAY_TYPE_X11 = (1 << 0),
GST_NV_VIDEO_DISPLAY_TYPE_ANY = G_MAXUINT32
} GstNvVideoDisplayType;
struct _GstNvVideoDisplay
{
GstObject parent;
GstNvVideoDisplayType type;
};
GST_EXPORT
gboolean gst_nv_video_display_new (GstNvVideoDisplay ** display);
GST_EXPORT
gboolean gst_nv_video_display_create_context (GstNvVideoDisplay * display, GstNvVideoContext ** ptr_context);
GST_EXPORT
GstNvVideoDisplayType gst_nv_video_display_get_handle_type (GstNvVideoDisplay * display);
GST_EXPORT
GstNvVideoWindow *gst_nv_video_display_create_window (GstNvVideoDisplay * display);
GType gst_nv_video_display_get_type (void);
G_END_DECLS
#endif /* __GST_NV_VIDEO_DISPLAY_H__ */

View File

@@ -0,0 +1,499 @@
/*
* SPDX-FileCopyrightText: Copyright (c) <2018-2025> NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: LGPL-2.1-only
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "context_egl.h"
#include "display.h"
#include "display_x11.h"
#include "window.h"
#include "nvbufsurface.h"
#include <EGL/egl.h>
G_GNUC_INTERNAL extern GstDebugCategory *gst_debug_nv_video_context;
#define GST_CAT_DEFAULT gst_debug_nv_video_context
G_DEFINE_TYPE (GstNvVideoContextEgl, gst_nv_video_context_egl,
GST_TYPE_NV_VIDEO_CONTEXT);
static GstCaps *
gst_nv_video_context_egl_new_template_caps (GstVideoFormat format)
{
return gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, gst_video_format_to_string (format),
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
}
static void
log_egl_error (GstNvVideoContext * context, const char *name)
{
GST_ERROR_OBJECT (context, "egl error: %s returned %x", name, eglGetError ());
}
static gboolean
gst_nv_video_context_egl_is_surface_changed (GstNvVideoContextEgl * context_egl)
{
gint w, h;
eglQuerySurface (context_egl->display, context_egl->surface, EGL_WIDTH, &w);
eglQuerySurface (context_egl->display, context_egl->surface, EGL_HEIGHT, &h);
if (context_egl->surface_width != w || context_egl->surface_height != h) {
context_egl->surface_width = w;
context_egl->surface_height = h;
return TRUE;
}
return FALSE;
}
static gboolean
gst_nv_video_context_egl_show_frame (GstNvVideoContext * context,
GstBuffer * buf)
{
GstNvVideoContextEgl *context_egl = GST_NV_VIDEO_CONTEXT_EGL (context);
EGLImageKHR image = EGL_NO_IMAGE_KHR;
GstMemory *mem;
NvBufSurface *in_surface = NULL;
gboolean is_cuda_mem = TRUE;
if (!context_egl->surface) {
guintptr handle = gst_nv_video_window_get_handle (context->window);
context_egl->surface =
eglCreateWindowSurface (context_egl->display, context_egl->config,
(EGLNativeWindowType) handle, NULL);
if (context_egl->surface == EGL_NO_SURFACE) {
log_egl_error (context, "eglCreateWindowSurface");
return FALSE;
}
if (!eglMakeCurrent (context_egl->display, context_egl->surface,
context_egl->surface, context_egl->context)) {
log_egl_error (context, "eglMakeCurrent");
return FALSE;
}
GST_DEBUG_OBJECT (context, "egl surface %p created", context_egl->surface);
}
if (!context_egl->renderer) {
context_egl->renderer = gst_nv_video_renderer_new (context, "gl");
if (!context_egl->renderer) {
GST_ERROR_OBJECT (context, "renderer creation failed");
return FALSE;
}
if (!gst_nv_video_renderer_setup (context_egl->renderer)) {
GST_ERROR_OBJECT (context, "renderer setup failed");
return FALSE;
}
}
if (context->using_NVMM && !context->cuda_optimized) {
if (!context->is_cuda_init) {
if (!gst_nv_video_renderer_cuda_init (context, context_egl->renderer)) {
GST_ERROR_OBJECT (context, "cuda init failed");
return FALSE;
}
}
}
if (gst_nv_video_context_egl_is_surface_changed (context_egl)) {
GST_DEBUG_OBJECT (context, "surface dimensions changed to %dx%d",
context_egl->surface_width, context_egl->surface_height);
gst_nv_video_renderer_update_viewport (context_egl->renderer,
context_egl->surface_width, context_egl->surface_height);
}
if (gst_buffer_n_memory (buf) >= 1 && (mem = gst_buffer_peek_memory (buf, 0))) {
//Software buffer handling
if (!context->using_NVMM) {
if (!gst_nv_video_renderer_fill_texture(context, context_egl->renderer, buf)) {
GST_ERROR_OBJECT (context, "fill_texture failed");
return FALSE;
}
if (!gst_nv_video_renderer_draw_2D_Texture (context_egl->renderer)) {
GST_ERROR_OBJECT (context, "draw 2D Texture failed");
return FALSE;
}
}
else {
// NvBufSurface support (NVRM and CUDA)
GstMapInfo map = { NULL, (GstMapFlags) 0, NULL, 0, 0, };
mem = gst_buffer_peek_memory (buf, 0);
gst_memory_map (mem, &map, GST_MAP_READ);
/* Types of Buffers handled -
* NvBufSurface
* - NVMM buffer type
* - Cuda buffer type
*/
/* NvBufSurface type are handled here */
in_surface = (NvBufSurface*) map.data;
NvBufSurfaceMemType memType = in_surface->memType;
if (memType == NVBUF_MEM_DEFAULT) {
#ifdef IS_DESKTOP
memType = NVBUF_MEM_CUDA_DEVICE;
#else
memType = NVBUF_MEM_SURFACE_ARRAY;
#endif
}
if (memType == NVBUF_MEM_SURFACE_ARRAY || memType == NVBUF_MEM_HANDLE) {
is_cuda_mem = FALSE;
}
if (is_cuda_mem == FALSE || context->cuda_optimized) {
/* NvBufSurface - NVMM buffer type are handled here */
if (in_surface->batchSize != 1) {
GST_ERROR_OBJECT (context,"ERROR: Batch size not 1\n");
return FALSE;
}
if (NvBufSurfaceMapEglImage (in_surface, 0) !=0 ) {
GST_ERROR_OBJECT (context,"ERROR: NvBufSurfaceMapEglImage\n");
return FALSE;
}
image = in_surface->surfaceList[0].mappedAddr.eglImage;
gst_nv_video_renderer_draw_eglimage (context_egl->renderer, image);
}
else {
/* NvBufSurface - Cuda buffer type are handled here */
if (!gst_nv_video_renderer_cuda_buffer_copy (context, context_egl->renderer, buf))
{
GST_ERROR_OBJECT (context,"cuda buffer copy failed\n");
return FALSE;
}
if (!gst_nv_video_renderer_draw_2D_Texture (context_egl->renderer)) {
GST_ERROR_OBJECT (context,"draw 2D texture failed");
return FALSE;
}
}
gst_memory_unmap (mem, &map);
}
}
if (!eglSwapBuffers (context_egl->display, context_egl->surface)) {
log_egl_error (context, "eglSwapBuffers");
}
if (image != EGL_NO_IMAGE_KHR) {
NvBufSurfaceUnMapEglImage (in_surface, 0);
}
GST_TRACE_OBJECT (context, "release %p hold %p", context_egl->last_buf, buf);
// TODO: We hold buffer used in current drawing till next swap buffer
// is completed so that decoder won't write it till GL has finished using it.
// When Triple buffering in X is enabled, this can cause tearing as completion
// of next swap buffer won't guarantee GL has finished with the buffer used in
// current swap buffer. This issue will be addresed when we transfer SyncFds
// from decoder <-> sink.
if (!context_egl->is_drc_on) {
gst_buffer_replace (&context_egl->last_buf, buf);
}
return TRUE;
}
static void
gst_nv_video_context_egl_handle_tearing (GstNvVideoContext * context)
{
GstNvVideoContextEgl *context_egl = GST_NV_VIDEO_CONTEXT_EGL (context);
context_egl->is_drc_on = 0;
return;
}
static void
gst_nv_video_context_egl_handle_drc (GstNvVideoContext * context)
{
GstNvVideoContextEgl *context_egl = GST_NV_VIDEO_CONTEXT_EGL (context);
GST_TRACE_OBJECT (context, "release last frame when resolution changes %p", context_egl->last_buf);
if (context_egl->last_buf)
context_egl->is_drc_on = 1;
gst_buffer_replace (&context_egl->last_buf, NULL);
}
static void
gst_nv_video_context_egl_handle_eos (GstNvVideoContext * context)
{
GstNvVideoContextEgl *context_egl = GST_NV_VIDEO_CONTEXT_EGL (context);
GST_TRACE_OBJECT (context, "release last frame %p", context_egl->last_buf);
gst_buffer_replace (&context_egl->last_buf, NULL);
}
static gboolean
gst_nv_video_context_egl_setup (GstNvVideoContext * context)
{
GstNvVideoDisplayX11 *display_x11 = (GstNvVideoDisplayX11 *) context->display;
GstNvVideoContextEgl *context_egl = GST_NV_VIDEO_CONTEXT_EGL (context);
EGLint major, minor;
EGLint num_configs;
EGLint attr[] = {
EGL_BUFFER_SIZE, 24,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
GST_DEBUG_OBJECT (context, "EGL context setup");
context_egl->display =
eglGetDisplay ((EGLNativeDisplayType) display_x11->dpy);
if (!eglInitialize (context_egl->display, &major, &minor)) {
log_egl_error (context, "eglInitialize");
return FALSE;
}
GST_INFO_OBJECT (context, "egl version: %d.%d", major, minor);
eglBindAPI (EGL_OPENGL_ES_API);
if (!eglChooseConfig (context_egl->display, attr, &context_egl->config, 1,
&num_configs)) {
log_egl_error (context, "eglChooseConfig");
}
context_egl->context =
eglCreateContext (context_egl->display, context_egl->config,
EGL_NO_CONTEXT, attribs);
if (context_egl->context == EGL_NO_CONTEXT) {
log_egl_error (context, "eglChooseConfig");
return FALSE;
}
GST_DEBUG_OBJECT (context, "egl context %p created", context_egl->context);
return TRUE;
}
static void
gst_nv_video_context_egl_cleanup (GstNvVideoContext * context)
{
GstNvVideoContextEgl *context_egl = GST_NV_VIDEO_CONTEXT_EGL (context);
GST_DEBUG_OBJECT (context, "egl cleanup display=%p surface=%p context=%p",
context_egl->display, context_egl->surface, context_egl->context);
if (context_egl->renderer) {
if (context->using_NVMM && !context->cuda_optimized) {
gst_nv_video_renderer_cuda_cleanup (context, context_egl->renderer);
}
gst_nv_video_renderer_cleanup (context_egl->renderer);
gst_object_unref (context_egl->renderer);
context_egl->renderer = NULL;
}
if (!eglMakeCurrent (context_egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT)) {
log_egl_error (context, "eglMakeCurrent");
}
if (context_egl->surface) {
eglDestroySurface (context_egl->display, context_egl->surface);
context_egl->surface = NULL;
}
if (context_egl->context) {
eglDestroyContext (context_egl->display, context_egl->context);
context_egl->context = NULL;
}
eglTerminate (context_egl->display);
context_egl->display = NULL;
GST_DEBUG_OBJECT (context, "egl cleanup done");
return;
}
static void
gst_nv_video_context_egl_cuda_reset_resources (GstNvVideoContext * context)
{
GstNvVideoContextEgl *context_egl = GST_NV_VIDEO_CONTEXT_EGL (context);
if (context_egl->renderer && context->is_cuda_init) {
gst_nv_video_renderer_cuda_reset_resources (context, context_egl->renderer);
context->is_cuda_init = FALSE;
}
}
static GstCaps *
gst_nv_video_context_egl_getcaps (GstNvVideoContext * context)
{
GstNvVideoContextEgl *context_egl = GST_NV_VIDEO_CONTEXT_EGL (context);
GST_LOG_OBJECT (context, "context add_caps %" GST_PTR_FORMAT,
context_egl->caps);
return gst_caps_copy (context_egl->caps);
}
static gboolean
gst_nv_video_context_egl_create (GstNvVideoContext * context)
{
return gst_nv_video_context_create_render_thread (context);
}
static void
gst_nv_video_context_egl_finalize (GObject * object)
{
GstNvVideoContext *context = GST_NV_VIDEO_CONTEXT (object);
GstNvVideoContextEgl *context_egl = GST_NV_VIDEO_CONTEXT_EGL (context);
GST_DEBUG_OBJECT (context, "finalize begin");
gst_nv_video_context_destroy_render_thread (context);
if (context_egl->caps) {
gst_caps_unref (context_egl->caps);
}
G_OBJECT_CLASS (gst_nv_video_context_egl_parent_class)->finalize (object);
GST_DEBUG_OBJECT (context, "finalize end");
}
static void
gst_nv_video_context_egl_class_init (GstNvVideoContextEglClass * klass)
{
GstNvVideoContextClass *context_class = (GstNvVideoContextClass *) klass;
context_class->create = GST_DEBUG_FUNCPTR (gst_nv_video_context_egl_create);
context_class->setup = GST_DEBUG_FUNCPTR (gst_nv_video_context_egl_setup);
context_class->get_caps =
GST_DEBUG_FUNCPTR (gst_nv_video_context_egl_getcaps);
context_class->show_frame =
GST_DEBUG_FUNCPTR (gst_nv_video_context_egl_show_frame);
context_class->handle_eos =
GST_DEBUG_FUNCPTR (gst_nv_video_context_egl_handle_eos);
context_class->handle_drc =
GST_DEBUG_FUNCPTR (gst_nv_video_context_egl_handle_drc);
context_class->handle_tearing =
GST_DEBUG_FUNCPTR (gst_nv_video_context_egl_handle_tearing);
context_class->cuda_reset_resources =
GST_DEBUG_FUNCPTR (gst_nv_video_context_egl_cuda_reset_resources);
context_class->cleanup = GST_DEBUG_FUNCPTR (gst_nv_video_context_egl_cleanup);
G_OBJECT_CLASS (klass)->finalize = gst_nv_video_context_egl_finalize;
}
static void
gst_nv_video_context_egl_init (GstNvVideoContextEgl * context_egl)
{
GstNvVideoContext *context = (GstNvVideoContext *) context_egl;
context->type = GST_NV_VIDEO_CONTEXT_TYPE_EGL;
context_egl->context = NULL;
context_egl->display = NULL;
context_egl->surface = NULL;
context_egl->config = NULL;
context_egl->surface_width = 0;
context_egl->surface_height = 0;
context_egl->last_buf = NULL;
context_egl->is_drc_on = 0;
}
GstNvVideoContextEgl *
gst_nv_video_context_egl_new (GstNvVideoDisplay * display)
{
GstNvVideoContextEgl *ret;
GstCaps *caps = NULL;
guint i, n;
// for now we need x11 display for EGL context.
if ((gst_nv_video_display_get_handle_type (display) &
GST_NV_VIDEO_DISPLAY_TYPE_X11)
== 0) {
return NULL;
}
ret = g_object_new (GST_TYPE_NV_VIDEO_CONTEXT_EGL, NULL);
gst_object_ref_sink (ret);
// TODO: query from egl
caps = gst_caps_new_empty ();
// Software buffer caps
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_RGBA));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_BGRA));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_ARGB));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_ABGR));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_RGBx));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_BGRx));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_xRGB));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_xBGR));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_AYUV));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_Y444));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_RGB));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_BGR));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_I420));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_YV12));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_NV12));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_NV21));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_Y42B));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_Y41B));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_RGB16));
n = gst_caps_get_size(caps);
// NVMM buffer caps
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_NV12));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_I420));
gst_caps_append (caps,
gst_nv_video_context_egl_new_template_caps (GST_VIDEO_FORMAT_RGBA));
for (i = n; i < n + 3; i++) {
GstCapsFeatures *features = gst_caps_features_new ("memory:NVMM", NULL);
gst_caps_set_features (caps, i, features);
}
gst_caps_replace (&ret->caps, caps);
gst_caps_unref (caps);
return ret;
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef __GST_NV_VIDEO_CONTEXT_EGL_H__
#define __GST_NV_VIDEO_CONTEXT_EGL_H__
#include "context.h"
#include "renderer.h"
G_BEGIN_DECLS
#define GST_TYPE_NV_VIDEO_CONTEXT_EGL \
(gst_nv_video_context_egl_get_type())
#define GST_NV_VIDEO_CONTEXT_EGL(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_NV_VIDEO_CONTEXT_EGL, GstNvVideoContextEgl))
#define GST_NV_VIDEO_CONTEXT_EGL_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_NV_VIDEO_CONTEXT_EGL, GstNvVideoContextEglClass))
#define GST_IS_NV_VIDEO_CONTEXT_EGL(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_NV_VIDEO_CONTEXT_EGL))
#define GST_IS_NV_VIDEO_CONTEXT_EGL_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_NV_VIDEO_CONTEXT_EGL))
#define GST_NV_VIDEO_CONTEXT_EGL_CAST(obj) \
((GstNvVideoContextEgl*)(obj))
typedef struct _GstNvVideoContextEgl GstNvVideoContextEgl;
typedef struct _GstNvVideoContextEglClass GstNvVideoContextEglClass;
struct _GstNvVideoContextEgl
{
GstNvVideoContext parent;
gpointer context;
gpointer display;
gpointer surface;
gpointer config;
gint surface_width;
gint surface_height;
GstNvVideoRenderer *renderer;
GstCaps *caps;
GstBuffer *last_buf;
gint is_drc_on;
};
struct _GstNvVideoContextEglClass
{
GstNvVideoContextClass parent_class;
};
G_GNUC_INTERNAL
GstNvVideoContextEgl * gst_nv_video_context_egl_new (GstNvVideoDisplay * display);
GType gst_nv_video_context_egl_get_type (void);
G_END_DECLS
#endif /* __GST_NV_VIDEO_CONTEXT_EGL_H__ */

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef __GST_NV_VIDEO_FWD_H__
#define __GST_NV_VIDEO_FWD_H__
#include <gst/gst.h>
G_BEGIN_DECLS
typedef struct _GstNvVideoDisplay GstNvVideoDisplay;
typedef struct _GstNvVideoDisplayClass GstNvVideoDisplayClass;
typedef struct _GstNvVideoWindow GstNvVideoWindow;
typedef struct _GstNvVideoWindowClass GstNvVideoWindowClass;
typedef struct _GstNvVideoContext GstNvVideoContext;
typedef struct _GstNvVideoContextClass GstNvVideoContextClass;
typedef struct _GstNvVideoContextPrivate GstNvVideoContextPrivate;
typedef struct _GstNvVideoRenderer GstNvVideoRenderer;
typedef struct _GstNvVideoRendererClass GstNvVideoRendererClass;
G_END_DECLS
#endif /* __GST_NV_VIDEO_FWD_H__ */

View File

@@ -0,0 +1,177 @@
/*
* Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <gst/base/gstdataqueue.h>
#include "renderer.h"
#include "context.h"
#if NV_VIDEO_SINKS_HAS_GL
#include "renderer_gl.h"
#endif
#define GST_CAT_DEFAULT gst_debug_nv_video_renderer
GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
G_DEFINE_ABSTRACT_TYPE (GstNvVideoRenderer, gst_nv_video_renderer,
GST_TYPE_OBJECT);
static void
gst_nv_video_renderer_init (GstNvVideoRenderer * renderer)
{
}
static void
gst_nv_video_renderer_class_init (GstNvVideoRendererClass * klass)
{
}
GstNvVideoRenderer *
gst_nv_video_renderer_new (GstNvVideoContext * context, const char *name)
{
GstNvVideoRenderer *renderer = NULL;
static gsize debug_init = 0;
if (g_once_init_enter (&debug_init)) {
GST_DEBUG_CATEGORY_INIT (gst_debug_nv_video_renderer, "nvvideorenderer", 0,
"nvvideorenderer");
g_once_init_leave (&debug_init, 1);
}
if (!name) {
GST_ERROR ("renderer name not valid");
}
#if NV_VIDEO_SINKS_HAS_GL
if (g_strstr_len (name, 2, "gl")) {
renderer = GST_NV_VIDEO_RENDERER (gst_nv_video_renderer_gl_new (context));
}
#endif
if (!renderer) {
GST_ERROR ("couldn't create renderer name = %s", name);
return NULL;
}
renderer->format = context->configured_info.finfo->format;
GST_DEBUG_OBJECT (renderer, "created %s renderer for context %" GST_PTR_FORMAT, name, context);
return renderer;
}
gboolean
gst_nv_video_renderer_cuda_init (GstNvVideoContext * context, GstNvVideoRenderer * renderer)
{
GstNvVideoRendererClass *renderer_class;
renderer_class = GST_NV_VIDEO_RENDERER_GET_CLASS (renderer);
return renderer_class->cuda_init (context, renderer);
}
void
gst_nv_video_renderer_cuda_cleanup (GstNvVideoContext * context, GstNvVideoRenderer * renderer)
{
GstNvVideoRendererClass *renderer_class;
renderer_class = GST_NV_VIDEO_RENDERER_GET_CLASS (renderer);
renderer_class->cuda_cleanup (context, renderer);
}
void
gst_nv_video_renderer_cuda_reset_resources (GstNvVideoContext * context, GstNvVideoRenderer * renderer)
{
GstNvVideoRendererClass *renderer_class;
renderer_class = GST_NV_VIDEO_RENDERER_GET_CLASS (renderer);
if (renderer_class->cuda_reset_resources) {
renderer_class->cuda_reset_resources (context, renderer);
}
}
void
gst_nv_video_renderer_cleanup (GstNvVideoRenderer * renderer)
{
GstNvVideoRendererClass *renderer_class;
renderer_class = GST_NV_VIDEO_RENDERER_GET_CLASS (renderer);
renderer_class->cleanup (renderer);
}
gboolean
gst_nv_video_renderer_setup (GstNvVideoRenderer * renderer)
{
GstNvVideoRendererClass *renderer_class;
renderer_class = GST_NV_VIDEO_RENDERER_GET_CLASS (renderer);
return renderer_class->setup (renderer);
}
void
gst_nv_video_renderer_update_viewport (GstNvVideoRenderer * renderer, int width, int height)
{
GstNvVideoRendererClass *renderer_class;
renderer_class = GST_NV_VIDEO_RENDERER_GET_CLASS (renderer);
renderer_class->update_viewport (renderer, width, height);
}
gboolean
gst_nv_video_renderer_fill_texture (GstNvVideoContext *context, GstNvVideoRenderer * renderer, GstBuffer * buf)
{
GstNvVideoRendererClass *renderer_class;
renderer_class = GST_NV_VIDEO_RENDERER_GET_CLASS (renderer);
return renderer_class->fill_texture (context, renderer, buf);
}
gboolean
gst_nv_video_renderer_cuda_buffer_copy (GstNvVideoContext *context, GstNvVideoRenderer * renderer, GstBuffer * buf)
{
GstNvVideoRendererClass *renderer_class;
renderer_class = GST_NV_VIDEO_RENDERER_GET_CLASS (renderer);
return renderer_class->cuda_buffer_copy (context, renderer, buf);
}
gboolean
gst_nv_video_renderer_draw_2D_Texture (GstNvVideoRenderer * renderer)
{
GstNvVideoRendererClass *renderer_class;
renderer_class = GST_NV_VIDEO_RENDERER_GET_CLASS (renderer);
return renderer_class->draw_2D_Texture (renderer);
}
gboolean
gst_nv_video_renderer_draw_eglimage (GstNvVideoRenderer * renderer, void * image)
{
GstNvVideoRendererClass *renderer_class;
renderer_class = GST_NV_VIDEO_RENDERER_GET_CLASS (renderer);
return renderer_class->draw_eglimage (renderer, image);
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef __GST_NV_VIDEO_RENDERER_H__
#define __GST_NV_VIDEO_RENDERER_H__
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstnvvideofwd.h"
G_BEGIN_DECLS
#define GST_TYPE_NV_VIDEO_RENDERER \
(gst_nv_video_renderer_get_type())
#define GST_NV_VIDEO_RENDERER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_NV_VIDEO_RENDERER, GstNvVideoRenderer))
#define GST_NV_VIDEO_RENDERER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_NV_VIDEO_RENDERER, GstNvVideoRendererClass))
#define GST_IS_NV_VIDEO_RENDERER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_NV_VIDEO_RENDERER))
#define GST_IS_NV_VIDEO_RENDERER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_NV_VIDEO_RENDERER))
#define GST_NV_VIDEO_RENDERER_GET_CLASS(o) \
(G_TYPE_INSTANCE_GET_CLASS((o), GST_TYPE_NV_VIDEO_RENDERER, GstNvVideoRendererClass))
struct _GstNvVideoRendererClass
{
GstObjectClass parent_class;
gboolean (*cuda_init) (GstNvVideoContext *context, GstNvVideoRenderer * renderer);
void (*cuda_cleanup) (GstNvVideoContext *context, GstNvVideoRenderer * renderer);
void (*cuda_reset_resources) (GstNvVideoContext *context, GstNvVideoRenderer * renderer);
gboolean (*setup) (GstNvVideoRenderer * renderer);
void (*cleanup) (GstNvVideoRenderer * renderer);
void (*update_viewport) (GstNvVideoRenderer * renderer, int width, int height);
gboolean (*fill_texture) (GstNvVideoContext *context, GstNvVideoRenderer * renderer, GstBuffer * buf);
gboolean (*cuda_buffer_copy) (GstNvVideoContext *context, GstNvVideoRenderer * renderer, GstBuffer * buf);
gboolean (*draw_2D_Texture) (GstNvVideoRenderer * renderer);
gboolean (*draw_eglimage) (GstNvVideoRenderer * renderer, void * image);
};
struct _GstNvVideoRenderer
{
GstObject parent;
GstNvVideoContext * context;
GstVideoFormat format;
};
GST_EXPORT
GstNvVideoRenderer * gst_nv_video_renderer_new (GstNvVideoContext * context, const char *name);
GST_EXPORT
gboolean gst_nv_video_renderer_cuda_init (GstNvVideoContext * context, GstNvVideoRenderer * renderer);
GST_EXPORT
void gst_nv_video_renderer_cuda_cleanup (GstNvVideoContext * context, GstNvVideoRenderer * renderer);
GST_EXPORT
void gst_nv_video_renderer_cuda_reset_resources (GstNvVideoContext * context, GstNvVideoRenderer * renderer);
GST_EXPORT
gboolean gst_nv_video_renderer_setup (GstNvVideoRenderer * renderer);
GST_EXPORT
void gst_nv_video_renderer_cleanup (GstNvVideoRenderer * renderer);
GST_EXPORT
void gst_nv_video_renderer_update_viewport (GstNvVideoRenderer * renderer, int width, int height);
GST_EXPORT
gboolean gst_nv_video_renderer_fill_texture (GstNvVideoContext *context, GstNvVideoRenderer * renderer, GstBuffer * buf);
GST_EXPORT
gboolean gst_nv_video_renderer_cuda_buffer_copy (GstNvVideoContext *context, GstNvVideoRenderer * renderer, GstBuffer * buf);
GST_EXPORT
gboolean gst_nv_video_renderer_draw_2D_Texture (GstNvVideoRenderer * renderer);
GST_EXPORT
gboolean gst_nv_video_renderer_draw_eglimage (GstNvVideoRenderer * renderer, void * image);
GType gst_nv_video_renderer_get_type (void);
G_END_DECLS
#endif /* __GST_NV_VIDEO_RENDERER_H__ */

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef __GST_NV_VIDEO_RENDERER_GL_H__
#define __GST_NV_VIDEO_RENDERER_GL_H__
#include "context.h"
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
G_BEGIN_DECLS
#define GST_TYPE_NV_VIDEO_RENDERER_GL \
(gst_nv_video_renderer_gl_get_type())
#define GST_NV_VIDEO_RENDERER_GL(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_NV_VIDEO_RENDERER_GL, GstNvVideoRendererGl))
#define GST_NV_VIDEO_RENDERER_GL_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_NV_VIDEO_RENDERER_GL, GstNvVideoRendererGlClass))
#define GST_IS_NV_VIDEO_RENDERER_GL(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_NV_VIDEO_RENDERER_GL))
#define GST_IS_NV_VIDEO_RENDERER_GL_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_NV_VIDEO_RENDERER_GL))
#define GST_NV_VIDEO_RENDERER_GL_CAST(obj) \
((GstNvVideoRendererGl*)(obj))
typedef struct _GstNvVideoRendererGl GstNvVideoRendererGl;
typedef struct _GstNvVideoRendererGlClass GstNvVideoRendererGlClass;
#define RENDERER_NUM_GL_TEXTURES 1
struct _GstNvVideoRendererGl
{
GstNvVideoRenderer parent;
GLuint vert_obj[3]; /* EGL frame, 2D frame, 2D frame border*/
GLuint frag_obj[3]; /* EGL frame, 2D frame, 2D frame border*/
GLuint prog_obj[3]; /* EGL frame, 2D frame, 2D frame border*/
GLint pos;
GLint tex_pos;
GLint tex_sampler;
GLsizei num_textures;
GLuint textures[RENDERER_NUM_GL_TEXTURES];
unsigned int vertex_buffer;
unsigned int index_buffer;
//Defining different attribs and uniforms for 2D textures
GLuint position_loc[2]; /* Frame and Border */
GLuint texpos_loc[1]; /* Frame */
GLuint tex_scale_loc[1][3]; /* [frame] RGB/Y, U/UV, V */
GLuint tex_loc[1][3]; /* [frame] RGB/Y, U/UV, V */
unsigned int vertex_buffer_2d;
unsigned int index_buffer_2d;
gint num_textures_2d;
GLuint textures_2d[3];
GLuint stride[3];
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
};
struct _GstNvVideoRendererGlClass
{
GstNvVideoRendererClass parent_class;
};
G_GNUC_INTERNAL
GstNvVideoRendererGl * gst_nv_video_renderer_gl_new (GstNvVideoContext * context);
void
gst_nv_video_renderer_gl_process_shaders (GstNvVideoRenderer * renderer, gchar ** frag_prog, const gchar *texnames[], GstVideoFormat format);
gboolean
gst_nv_video_renderer_gl_cuda_init (GstNvVideoContext * context, GstNvVideoRenderer * renderer);
GType gst_nv_video_renderer_gl_get_type (void);
G_END_DECLS
#endif /* __GST_NV_VIDEO_RENDERER_GL_H__ */

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "window.h"
#if NV_VIDEO_SINKS_HAS_X11
#include "window_x11.h"
#endif
#define GST_CAT_DEFAULT gst_debug_nv_video_window
GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
#define gst_nv_video_window_parent_class parent_class
G_DEFINE_ABSTRACT_TYPE (GstNvVideoWindow, gst_nv_video_window, GST_TYPE_OBJECT);
static void
gst_nv_video_window_finalize (GObject * object)
{
GstNvVideoWindow *window = GST_NV_VIDEO_WINDOW (object);
g_weak_ref_clear (&window->context);
gst_object_unref (window->display);
G_OBJECT_CLASS (gst_nv_video_window_parent_class)->finalize (object);
}
static void
gst_nv_video_window_init (GstNvVideoWindow * window)
{
g_weak_ref_init (&window->context, NULL);
}
static void
gst_nv_video_window_class_init (GstNvVideoWindowClass * klass)
{
G_OBJECT_CLASS (klass)->finalize = gst_nv_video_window_finalize;
}
GstNvVideoWindow *
gst_nv_video_window_new (GstNvVideoDisplay * display)
{
GstNvVideoWindow *window = NULL;
static gsize debug_init = 0;
const gchar *winsys_name = NULL;
if (g_once_init_enter (&debug_init)) {
GST_DEBUG_CATEGORY_INIT (gst_debug_nv_video_window, "nvvideowindow", 0,
"nvvideowindow");
g_once_init_leave (&debug_init, 1);
}
winsys_name = g_getenv ("GST_NV_VIDEO_WINSYS");
#if NV_VIDEO_SINKS_HAS_X11
if (!window && (!winsys_name || g_strstr_len (winsys_name, 3, "x11"))) {
window = GST_NV_VIDEO_WINDOW (gst_nv_video_window_x11_new (NULL));
}
#endif
if (!window) {
GST_ERROR ("couldn't create window. GST_NV_VIDEO_WINSYS = %s",
winsys_name ? winsys_name : NULL);
return NULL;
}
window->display = gst_object_ref (display);
GST_DEBUG_OBJECT (window, "created window for display %" GST_PTR_FORMAT,
display);
return window;
}
/* create new window handle after destroying existing */
gboolean
gst_nv_video_window_create_window (GstNvVideoWindow * window, gint x,
gint y, gint width, gint height)
{
GstNvVideoWindowClass *window_class;
window_class = GST_NV_VIDEO_WINDOW_GET_CLASS (window);
return window_class->create_window (window, x, y, width, height);
}
gboolean
gst_nv_video_window_set_handle (GstNvVideoWindow * window, guintptr id)
{
GstNvVideoWindowClass *window_class;
window_class = GST_NV_VIDEO_WINDOW_GET_CLASS (window);
return window_class->set_handle (window, id);
}
guintptr
gst_nv_video_window_get_handle (GstNvVideoWindow * window)
{
GstNvVideoWindowClass *window_class;
window_class = GST_NV_VIDEO_WINDOW_GET_CLASS (window);
return window_class->get_handle (window);
}
GstNvVideoContext *
gst_nv_video_window_get_context (GstNvVideoWindow * window)
{
g_return_val_if_fail (GST_IS_NV_VIDEO_WINDOW (window), NULL);
return (GstNvVideoContext *) g_weak_ref_get (&window->context);
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef __GST_NV_VIDEO_WINDOW_H__
#define __GST_NV_VIDEO_WINDOW_H__
#include <gst/gst.h>
#include <gst/video/gstvideosink.h>
#include <gst/video/video.h>
#include "gstnvvideofwd.h"
G_BEGIN_DECLS
#define GST_TYPE_NV_VIDEO_WINDOW \
(gst_nv_video_window_get_type())
#define GST_NV_VIDEO_WINDOW(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NV_VIDEO_WINDOW, GstNvVideoWindow))
#define GST_NV_VIDEO_WINDOW_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_NV_VIDEO_WINDOW, GstNvVideoWindowClass))
#define GST_IS_NV_VIDEO_WINDOW(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_NV_VIDEO_WINDOW))
#define GST_IS_NV_VIDEO_WINDOW_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_NV_VIDEO_WINDOW))
#define GST_NV_VIDEO_WINDOW_CAST(obj) \
((GstNvVideoWindow*)(obj))
#define GST_NV_VIDEO_WINDOW_GET_CLASS(o) \
(G_TYPE_INSTANCE_GET_CLASS((o), GST_TYPE_NV_VIDEO_WINDOW, GstNvVideoWindowClass))
struct _GstNvVideoWindowClass
{
GstObjectClass parent_class;
guintptr (*get_handle) (GstNvVideoWindow * window);
gboolean (*set_handle) (GstNvVideoWindow * window, guintptr id);
gboolean (*create_window) (GstNvVideoWindow * window, gint x, gint y, gint width, gint height);
gboolean (*draw) (GstNvVideoWindow * window, GstBuffer * buf);
};
struct _GstNvVideoWindow
{
GstObject parent;
GstNvVideoDisplay *display;
GWeakRef context;
};
GST_EXPORT
GstNvVideoWindow *gst_nv_video_window_new (GstNvVideoDisplay * display);
GST_EXPORT
gboolean gst_nv_video_window_create_window (GstNvVideoWindow * window, gint x, gint y, gint width, gint height);
GST_EXPORT
gboolean gst_nv_video_window_set_handle (GstNvVideoWindow * window, guintptr id);
GST_EXPORT
guintptr gst_nv_video_window_get_handle (GstNvVideoWindow * window);
GST_EXPORT
GstNvVideoContext *gst_nv_video_window_get_context (GstNvVideoWindow * window);
GType gst_nv_video_window_get_type (void);
G_END_DECLS
#endif /* __GST_NV_VIDEO_WINDOW_H__ */

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "display_x11.h"
G_GNUC_INTERNAL extern GstDebugCategory *gst_debug_nv_video_display;
#define GST_CAT_DEFAULT gst_debug_nv_video_display
G_DEFINE_TYPE (GstNvVideoDisplayX11, gst_nv_video_display_x11,
GST_TYPE_NV_VIDEO_DISPLAY);
static void
gst_nv_video_display_x11_finalize (GObject * object)
{
GstNvVideoDisplayX11 *display_x11 = GST_NV_VIDEO_DISPLAY_X11 (object);
GST_DEBUG ("closing X11 display connection, handle=%p", display_x11->dpy);
if (display_x11->dpy) {
XCloseDisplay (display_x11->dpy);
}
GST_DEBUG ("closed X11 display connection");
G_OBJECT_CLASS (gst_nv_video_display_x11_parent_class)->finalize (object);
}
static guintptr
gst_nv_video_display_x11_get_handle (GstNvVideoDisplay * display)
{
return (guintptr) GST_NV_VIDEO_DISPLAY_X11 (display)->dpy;
}
static void
gst_nv_video_display_x11_class_init (GstNvVideoDisplayX11Class * klass)
{
GST_NV_VIDEO_DISPLAY_CLASS (klass)->get_handle =
GST_DEBUG_FUNCPTR (gst_nv_video_display_x11_get_handle);
G_OBJECT_CLASS (klass)->finalize = gst_nv_video_display_x11_finalize;
}
static void
gst_nv_video_display_x11_init (GstNvVideoDisplayX11 * display_x11)
{
GstNvVideoDisplay *display = (GstNvVideoDisplay *) display_x11;
display->type = GST_NV_VIDEO_DISPLAY_TYPE_X11;
GST_DEBUG_OBJECT (display, "init done");
}
GstNvVideoDisplayX11 *
gst_nv_video_display_x11_new (const gchar * name)
{
GstNvVideoDisplayX11 *ret;
ret = g_object_new (GST_TYPE_NV_VIDEO_DISPLAY_X11, NULL);
gst_object_ref_sink (ret);
ret->dpy = XOpenDisplay (NULL);
if (!ret->dpy) {
GST_ERROR ("failed to open X11 display connection");
gst_object_unref (ret);
return NULL;
}
GST_DEBUG ("opened X11 display connection handle=%p", ret->dpy);
return ret;
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef __GST_NV_VIDEO_DISPLAY_X11_H__
#define __GST_NV_VIDEO_DISPLAY_X11_H__
#include <X11/Xlib.h>
#include "display.h"
G_BEGIN_DECLS
#define GST_TYPE_NV_VIDEO_DISPLAY_X11 \
(gst_nv_video_display_x11_get_type())
#define GST_NV_VIDEO_DISPLAY_X11(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_NV_VIDEO_DISPLAY_X11, GstNvVideoDisplayX11))
#define GST_NV_VIDEO_DISPLAY_X11_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_NV_VIDEO_DISPLAY_X11, GstNvVideoDisplayX11Class))
#define GST_IS_NV_VIDEO_DISPLAY_X11(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_NV_VIDEO_DISPLAY_X11))
#define GST_IS_NV_VIDEO_DISPLAY_X11_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_NV_VIDEO_DISPLAY_X11))
#define GST_NV_VIDEO_DISPLAY_X11_CAST(obj) \
((GstNvVideoDisplayX11*)(obj))
typedef struct _GstNvVideoDisplayX11 GstNvVideoDisplayX11;
typedef struct _GstNvVideoDisplayX11Class GstNvVideoDisplayX11Class;
struct _GstNvVideoDisplayX11
{
GstNvVideoDisplay parent;
Display *dpy;
};
struct _GstNvVideoDisplayX11Class
{
GstNvVideoDisplayClass parent_class;
};
GST_EXPORT
GstNvVideoDisplayX11 * gst_nv_video_display_x11_new (const gchar * name);
GType gst_nv_video_display_x11_get_type (void);
G_END_DECLS
#endif /* __GST_NV_VIDEO_DISPLAY_X11_H__ */

View File

@@ -0,0 +1,157 @@
/**
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
*
* NVIDIA Corporation and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA Corporation is strictly prohibited.
*/
#include "context.h"
#include "display_x11.h"
#include "window_x11.h"
#include <X11/Xutil.h>
G_GNUC_INTERNAL extern GstDebugCategory *gst_debug_nv_video_window;
#define GST_CAT_DEFAULT gst_debug_nv_video_window
#define gst_nv_video_window_x11_parent_class parent_class
G_DEFINE_TYPE (GstNvVideoWindowX11, gst_nv_video_window_x11,
GST_TYPE_NV_VIDEO_WINDOW);
static void
gst_nv_video_window_x11_destroy (GstNvVideoWindow * window)
{
GstNvVideoWindowX11 *window_x11 = GST_NV_VIDEO_WINDOW_X11 (window);
GstNvVideoDisplayX11 *display_x11 = (GstNvVideoDisplayX11 *) window->display;
if (window_x11->internal_window) {
GST_DEBUG_OBJECT (window, "destroy internal window %" G_GUINTPTR_FORMAT,
window_x11->handle);
XUnmapWindow (display_x11->dpy, window_x11->handle);
XDestroyWindow (display_x11->dpy, window_x11->handle);
XSync (display_x11->dpy, FALSE);
window_x11->internal_window = FALSE;
window_x11->handle = 0;
} else {
GST_DEBUG_OBJECT (window, "unset foreign window handle %" G_GUINTPTR_FORMAT,
window_x11->handle);
window_x11->handle = 0;
}
}
static void
gst_nv_video_window_x11_finalize (GObject * object)
{
GstNvVideoWindow *window = GST_NV_VIDEO_WINDOW (object);
GST_DEBUG_OBJECT (window, "finalize begin");
gst_nv_video_window_x11_destroy (window);
G_OBJECT_CLASS (gst_nv_video_window_x11_parent_class)->finalize (object);
GST_DEBUG_OBJECT (window, "finalize end");
}
static guintptr
gst_nv_video_window_x11_get_handle (GstNvVideoWindow * window)
{
GstNvVideoWindowX11 *window_x11 = GST_NV_VIDEO_WINDOW_X11 (window);
return window_x11->handle;
}
static gboolean
gst_nv_video_window_x11_set_handle (GstNvVideoWindow * window, guintptr id)
{
GstNvVideoWindowX11 *window_x11 = GST_NV_VIDEO_WINDOW_X11 (window);
gst_nv_video_window_x11_destroy (window);
window_x11->handle = id;
GST_DEBUG_OBJECT (window, "set window handle to %" G_GUINTPTR_FORMAT, id);
return FALSE;
}
static gboolean
gst_nv_video_window_x11_create (GstNvVideoWindow * window, gint x,
gint y, gint width, gint height)
{
GstNvVideoWindowX11 *window_x11 = GST_NV_VIDEO_WINDOW_X11 (window);
GstNvVideoDisplayX11 *display_x11 = (GstNvVideoDisplayX11 *) window->display;
Display *dpy = display_x11->dpy;
int screen = DefaultScreen (dpy);
XSizeHints hints = {0};
hints.flags = PPosition ;
hints.x = x;
hints.y = y;
// GstNvVideoWindow doesn't have destroy_winow method (like create_window)
// and GstNvVideoWindow object can't have multiple X windows. So if
// upper layer has existing window (foreign or internal), unset/destroy it.
//
// TODO: In case of existing internal window, we might able to re-use it
// with XResizeWindow.
gst_nv_video_window_x11_destroy (window);
window_x11->handle = XCreateSimpleWindow (dpy, RootWindow (dpy, screen),
hints.x, hints.y, width, height, 1,
BlackPixel (dpy, screen), WhitePixel (dpy, screen));
if (!window_x11->handle) {
GST_ERROR_OBJECT (window, "failed to create internal window\n");
return FALSE;
}
window_x11->internal_window = TRUE;
XSetWindowBackgroundPixmap (dpy, window_x11->handle, None);
XSetNormalHints(dpy, window_x11->handle, &hints);
XMapRaised (dpy, window_x11->handle);
XSync (dpy, FALSE);
GST_DEBUG_OBJECT (window,
"created internal window %dx%d, handle=%" G_GUINTPTR_FORMAT, width,
height, window_x11->handle);
return TRUE;
}
static void
gst_nv_video_window_x11_class_init (GstNvVideoWindowX11Class * klass)
{
GstNvVideoWindowClass *window_class = (GstNvVideoWindowClass *) klass;
window_class->create_window =
GST_DEBUG_FUNCPTR (gst_nv_video_window_x11_create);
window_class->get_handle =
GST_DEBUG_FUNCPTR (gst_nv_video_window_x11_get_handle);
window_class->set_handle =
GST_DEBUG_FUNCPTR (gst_nv_video_window_x11_set_handle);
G_OBJECT_CLASS (klass)->finalize = gst_nv_video_window_x11_finalize;
}
static void
gst_nv_video_window_x11_init (GstNvVideoWindowX11 * window)
{
window->handle = 0;
window->internal_window = FALSE;
GST_DEBUG_OBJECT (window, "init done");
}
GstNvVideoWindowX11 *
gst_nv_video_window_x11_new (const gchar * name)
{
GstNvVideoWindowX11 *ret;
ret = g_object_new (GST_TYPE_NV_VIDEO_WINDOW_X11, NULL);
gst_object_ref_sink (ret);
return ret;
}

View File

@@ -0,0 +1,54 @@
/**
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
*
* NVIDIA Corporation and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA Corporation is strictly prohibited.
*/
#ifndef __GST_NV_VIDEO_WINDOW_X11_H__
#define __GST_NV_VIDEO_WINDOW_X11_H__
#include "window.h"
G_BEGIN_DECLS
#define GST_TYPE_NV_VIDEO_WINDOW_X11 \
(gst_nv_video_window_x11_get_type())
#define GST_NV_VIDEO_WINDOW_X11(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_NV_VIDEO_WINDOW_X11, GstNvVideoWindowX11))
#define GST_NV_VIDEO_WINDOW_X11_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_NV_VIDEO_WINDOW_X11, GstNvVideoWindowX11Class))
#define GST_IS_NV_VIDEO_WINDOW_X11(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_NV_VIDEO_WINDOW_X11))
#define GST_IS_NV_VIDEO_WINDOW_X11_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_NV_VIDEO_WINDOW_X11))
#define GST_NV_VIDEO_WINDOW_X11_CAST(obj) \
((GstNvVideoWindowX11*)(obj))
typedef struct _GstNvVideoWindowX11 GstNvVideoWindowX11;
typedef struct _GstNvVideoWindowX11Class GstNvVideoWindowX11Class;
struct _GstNvVideoWindowX11
{
GstNvVideoWindow parent;
guintptr handle;
gboolean internal_window;
};
struct _GstNvVideoWindowX11Class
{
GstNvVideoWindowClass parent_class;
};
GST_EXPORT
GstNvVideoWindowX11 *gst_nv_video_window_x11_new (const gchar * name);
GType gst_nv_video_window_x11_get_type (void);
G_END_DECLS
#endif /* __GST_NV_VIDEO_WINDOW_X11_H__ */

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <gst/gst.h>
#if NV_VIDEO_SINKS_HAS_NV3DSINK
#include "nv3dsink/gstnv3dsink.h"
#endif
#if NV_VIDEO_SINKS_HAS_X11
#include <X11/Xlib.h>
#endif
GST_DEBUG_CATEGORY_STATIC (gst_nvvideosinks_debug);
#define GST_CAT_DEFAULT gst_nvvideosinks_debug
static gboolean
plugin_init (GstPlugin * plugin)
{
#if NV_VIDEO_SINKS_HAS_X11
XInitThreads ();
#endif
/* debug category for fltering log messages */
GST_DEBUG_CATEGORY_INIT (gst_nvvideosinks_debug, "nvvideosinks", 0,
"Nvidia video sinks");
#if NV_VIDEO_SINKS_HAS_NV3DSINK
if (!gst_element_register (plugin, "nv3dsink", GST_RANK_SECONDARY,
GST_TYPE_NV3DSINK)) {
return FALSE;
}
#endif
return TRUE;
}
/* PACKAGE is usually set by autotools but we are not using autotools
* to compile this code, so set it ourselves. GST_PLUGIN_DEFINE needs
* PACKAGE to be defined.
*/
#ifndef PACKAGE
#define PACKAGE "gst-plugins-nv-video-sinks"
#endif
/* gstreamer looks for this structure to register plugins */
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
nvvideosinks,
"Nvidia Video Sink Plugins",
plugin_init, "0.0.1", "Proprietary", "Nvidia Video Sink Plugins",
"http://nvidia.com/")

View File

@@ -0,0 +1,597 @@
/*
* SPDX-FileCopyrightText: Copyright (c) <2018-2025> NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: LGPL-2.1-only
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "gstnv3dsink.h"
#include "display.h"
#include "context.h"
#include "window.h"
GST_DEBUG_CATEGORY (gst_debug_nv3dsink);
#define GST_CAT_DEFAULT gst_debug_nv3dsink
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE);
#define GST_CAPS_FEATURE_MEMORY_NVMM "memory:NVMM"
static void gst_nv3dsink_videooverlay_init (GstVideoOverlayInterface * iface);
static void gst_nv3dsink_set_window_handle (GstVideoOverlay * overlay,
guintptr id);
static void gst_nv3dsink_expose (GstVideoOverlay * overlay);
static void gst_nv3dsink_handle_events (GstVideoOverlay * overlay,
gboolean handle_events);
static void gst_nv3dsink_set_render_rectangle (GstVideoOverlay * overlay,
gint x, gint y, gint width, gint height);
/* Input capabilities. */
static GstStaticPadTemplate gst_nv3dsink_sink_template_factory =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (
//Supported Software buffer caps
GST_VIDEO_CAPS_MAKE ("{ "
"RGBA, BGRA, ARGB, ABGR, " "RGBx, BGRx, xRGB, xBGR, "
"AYUV, Y444, I420, YV12, " "NV12, NV21, Y42B, Y41B, "
"RGB, BGR, RGB16 }")
";"
GST_VIDEO_CAPS_MAKE_WITH_FEATURES (
GST_CAPS_FEATURE_MEMORY_NVMM,
"{ RGBA, I420, NV12 }")
));
#define parent_class gst_nv3dsink_parent_class
G_DEFINE_TYPE_WITH_CODE (GstNv3dSink, gst_nv3dsink, GST_TYPE_VIDEO_SINK,
G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY,
gst_nv3dsink_videooverlay_init);
GST_DEBUG_CATEGORY_INIT (gst_debug_nv3dsink, "nv3dsink", 0,
"Nvidia 3D sink"));
enum
{
PROP_0,
PROP_WINDOW_X,
PROP_WINDOW_Y,
PROP_WINDOW_WIDTH,
PROP_WINDOW_HEIGHT
};
/* GObject vmethod implementations */
static void
gst_nv3dsink_videooverlay_init (GstVideoOverlayInterface * iface)
{
iface->set_window_handle = gst_nv3dsink_set_window_handle;
iface->expose = gst_nv3dsink_expose;
iface->handle_events = gst_nv3dsink_handle_events;
iface->set_render_rectangle = gst_nv3dsink_set_render_rectangle;
}
static void
gst_nv3dsink_set_window_handle (GstVideoOverlay * overlay, guintptr id)
{
GstNv3dSink *nv3dsink = GST_NV3DSINK (overlay);
gint width = 0;
gint height = 0;
g_return_if_fail (GST_IS_NV3DSINK (nv3dsink));
g_mutex_lock (&nv3dsink->win_handle_lock);
GST_DEBUG_OBJECT (nv3dsink, "set_window_handle %" G_GUINT64_FORMAT, id);
if (gst_nv_video_window_get_handle (nv3dsink->window) == id) {
g_mutex_unlock (&nv3dsink->win_handle_lock);
return;
}
if (id) {
gst_nv_video_window_set_handle (nv3dsink->window, id);
g_mutex_unlock (&nv3dsink->win_handle_lock);
return;
}
if (!GST_VIDEO_SINK_WIDTH (nv3dsink) || !GST_VIDEO_SINK_HEIGHT (nv3dsink)) {
// window will be created during caps negotiation
g_mutex_unlock (&nv3dsink->win_handle_lock);
return;
}
// create internal window
if (nv3dsink->window_width != 0 && nv3dsink->window_height != 0) {
width = nv3dsink->window_width;
height = nv3dsink->window_height;
} else {
width = GST_VIDEO_SINK_WIDTH (nv3dsink);
height = GST_VIDEO_SINK_HEIGHT (nv3dsink);
}
if (!gst_nv_video_window_create_window (nv3dsink->window,
nv3dsink->window_x, nv3dsink->window_y, width, height)) {
g_mutex_unlock (&nv3dsink->win_handle_lock);
return;
}
g_mutex_unlock (&nv3dsink->win_handle_lock);
}
static void
gst_nv3dsink_expose (GstVideoOverlay * overlay)
{
GstNv3dSink *nv3dsink = GST_NV3DSINK (overlay);
GST_DEBUG_OBJECT (nv3dsink, "expose unimplemented");
}
static void
gst_nv3dsink_handle_events (GstVideoOverlay * overlay, gboolean handle_events)
{
GstNv3dSink *nv3dsink = GST_NV3DSINK (overlay);
GST_DEBUG_OBJECT (nv3dsink, "handle_events unimplemented");
}
static void
gst_nv3dsink_set_render_rectangle (GstVideoOverlay * overlay, gint x, gint y,
gint width, gint height)
{
GstNv3dSink *nv3dsink = GST_NV3DSINK (overlay);
g_return_if_fail (GST_IS_NV3DSINK (nv3dsink));
GST_DEBUG_OBJECT (nv3dsink, "set_render_rectangle unimplemented");
return;
}
static void
gst_nv3dsink_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstNv3dSink *nv3dsink;
g_return_if_fail (GST_IS_NV3DSINK (object));
nv3dsink = GST_NV3DSINK (object);
switch (prop_id) {
case PROP_WINDOW_X:
nv3dsink->window_x = g_value_get_uint (value);
break;
case PROP_WINDOW_Y:
nv3dsink->window_y = g_value_get_uint (value);
break;
case PROP_WINDOW_WIDTH:
nv3dsink->window_width = g_value_get_uint (value);
break;
case PROP_WINDOW_HEIGHT:
nv3dsink->window_height = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_nv3dsink_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstNv3dSink *nv3dsink;
g_return_if_fail (GST_IS_NV3DSINK (object));
nv3dsink = GST_NV3DSINK (object);
switch (prop_id) {
case PROP_WINDOW_X:
g_value_set_uint (value, nv3dsink->window_x);
break;
case PROP_WINDOW_Y:
g_value_set_uint (value, nv3dsink->window_y);
break;
case PROP_WINDOW_WIDTH:
g_value_set_uint (value, nv3dsink->window_width);
break;
case PROP_WINDOW_HEIGHT:
g_value_set_uint (value, nv3dsink->window_height);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_nv3dsink_finalize (GObject * object)
{
GstNv3dSink *nv3dsink;
g_return_if_fail (GST_IS_NV3DSINK (object));
nv3dsink = GST_NV3DSINK (object);
GST_TRACE_OBJECT (nv3dsink, "finalize");
g_mutex_clear (&nv3dsink->win_handle_lock);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static gboolean
gst_nv3dsink_start (GstBaseSink * bsink)
{
GstNv3dSink *nv3dsink = GST_NV3DSINK (bsink);
GstNvVideoWindow *window;
GST_TRACE_OBJECT (nv3dsink, "start");
// TODO: Query display from application/upstream elements if there
// is such use case.
if (!nv3dsink->display) {
if (!gst_nv_video_display_new (&nv3dsink->display)) {
GST_ERROR_OBJECT (nv3dsink, "failed to create new display");
return FALSE;
}
} else {
GST_DEBUG_OBJECT (nv3dsink, "using existing display (%p)",
nv3dsink->display);
}
if (!nv3dsink->context) {
if (!gst_nv_video_display_create_context (nv3dsink->display,
&nv3dsink->context)) {
GST_ERROR_OBJECT (nv3dsink, "failed to create new context");
return FALSE;
}
} else {
GST_DEBUG_OBJECT (nv3dsink, "using existing context (%p)",
nv3dsink->context);
}
if (!nv3dsink->window) {
window = gst_nv_video_display_create_window (nv3dsink->display);
if (window == NULL) {
GST_ERROR_OBJECT (nv3dsink, "failed to create new window");
return FALSE;
}
nv3dsink->window = gst_object_ref (window);
gst_object_unref (window);
gst_nv_video_context_set_window (nv3dsink->context, nv3dsink->window);
} else {
GST_DEBUG_OBJECT (nv3dsink, "using existing window (%p)", nv3dsink->window);
}
return TRUE;
}
static gboolean
gst_nv3dsink_stop (GstBaseSink * bsink)
{
GstNv3dSink *nv3dsink = GST_NV3DSINK (bsink);
GST_TRACE_OBJECT (nv3dsink, "stop");
if (nv3dsink->configured_caps) {
gst_caps_unref (nv3dsink->configured_caps);
nv3dsink->configured_caps = NULL;
}
if (nv3dsink->context) {
gst_object_unref (nv3dsink->context);
nv3dsink->context = NULL;
}
if (nv3dsink->window) {
g_object_unref (nv3dsink->window);
nv3dsink->window = NULL;
}
if (nv3dsink->display) {
g_object_unref (nv3dsink->display);
nv3dsink->display = NULL;
}
return TRUE;
}
static GstCaps *
gst_nv3dsink_get_caps (GstBaseSink * bsink, GstCaps * filter)
{
GstNv3dSink *nv3dsink;
GstCaps *tmp = NULL;
GstCaps *result = NULL;
GstCaps *caps = NULL;
nv3dsink = GST_NV3DSINK (bsink);
tmp = gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD (bsink));
if (filter) {
GST_DEBUG_OBJECT (bsink, "intersecting with filter caps %" GST_PTR_FORMAT,
filter);
result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (tmp);
} else {
result = tmp;
}
caps = gst_nv_video_context_get_caps (nv3dsink->context);
if (caps) {
tmp = result;
result = gst_caps_intersect (result, caps);
gst_caps_unref (caps);
gst_caps_unref (tmp);
}
GST_DEBUG_OBJECT (bsink, "returning caps: %" GST_PTR_FORMAT, result);
return result;
}
static gboolean
gst_nv3dsink_set_caps (GstBaseSink * bsink, GstCaps * caps)
{
GstNv3dSink *nv3dsink;
GstVideoInfo info;
GstCapsFeatures *features;
gint width = 0;
gint height = 0;
nv3dsink = GST_NV3DSINK (bsink);
if (!nv3dsink->context || !nv3dsink->display) {
GST_ERROR_OBJECT (nv3dsink, "context or display not ready");
return FALSE;
}
GST_DEBUG_OBJECT (bsink, "set caps with %" GST_PTR_FORMAT, caps);
if (nv3dsink->configured_caps) {
if (gst_caps_is_equal (caps, nv3dsink->configured_caps)) {
return TRUE;
}
}
// Ensure render thread is active before setting caps
if (!gst_nv_video_context_create (nv3dsink->context)) {
GST_ERROR_OBJECT (nv3dsink, "failed to create render thread during caps negotiation");
return FALSE;
}
features = gst_caps_get_features (caps, 0);
if (gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_NVMM)) {
nv3dsink->context->using_NVMM = 1;
}
if (!gst_video_info_from_caps (&info, caps)) {
GST_ERROR_OBJECT (nv3dsink, "Invalid caps %" GST_PTR_FORMAT, caps);
return FALSE;
}
nv3dsink->context->configured_info = info;
int is_res_changed = 0;
if ((GST_VIDEO_SINK_WIDTH (nv3dsink)!=0 && GST_VIDEO_SINK_HEIGHT (nv3dsink)!=0) && (GST_VIDEO_SINK_WIDTH (nv3dsink) != info.width || GST_VIDEO_SINK_HEIGHT (nv3dsink) != info.height)) {
is_res_changed = 1;
}
if (is_res_changed)
{
gst_nv_video_context_handle_tearing(nv3dsink->context);
}
GST_VIDEO_SINK_WIDTH (nv3dsink) = info.width;
GST_VIDEO_SINK_HEIGHT (nv3dsink) = info.height;
g_mutex_lock (&nv3dsink->win_handle_lock);
if (!gst_nv_video_window_get_handle (nv3dsink->window)) {
g_mutex_unlock (&nv3dsink->win_handle_lock);
gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (nv3dsink));
} else {
g_mutex_unlock (&nv3dsink->win_handle_lock);
}
if (GST_VIDEO_SINK_WIDTH (nv3dsink) <= 0
|| GST_VIDEO_SINK_HEIGHT (nv3dsink) <= 0) {
GST_ERROR_OBJECT (nv3dsink, "invalid size");
return FALSE;
}
g_mutex_lock (&nv3dsink->win_handle_lock);
if (!gst_nv_video_window_get_handle (nv3dsink->window)) {
if (nv3dsink->window_width != 0 && nv3dsink->window_height != 0) {
width = nv3dsink->window_width;
height = nv3dsink->window_height;
} else {
width = GST_VIDEO_SINK_WIDTH (nv3dsink);
height = GST_VIDEO_SINK_HEIGHT (nv3dsink);
}
if (!gst_nv_video_window_create_window (nv3dsink->window,
nv3dsink->window_x, nv3dsink->window_y, width, height)) {
g_mutex_unlock (&nv3dsink->win_handle_lock);
return FALSE;
}
}
g_mutex_unlock (&nv3dsink->win_handle_lock);
gst_caps_replace (&nv3dsink->configured_caps, caps);
gst_nv_video_context_set_configured_caps (nv3dsink->context, caps);
return TRUE;
}
static gboolean
gst_nv3dsink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
{
GstNv3dSink *nv3dsink = GST_NV3DSINK (bsink);
gst_nv_video_context_handle_drc (nv3dsink->context);
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, NULL);
return TRUE;
}
static GstFlowReturn
gst_nv3dsink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
{
GstNv3dSink *nv3dsink;
nv3dsink = GST_NV3DSINK (vsink);
GST_TRACE_OBJECT (nv3dsink, "show buffer %p, window size:%ux%u", buf,
GST_VIDEO_SINK_WIDTH (nv3dsink), GST_VIDEO_SINK_HEIGHT (nv3dsink));
// Try to create render thread if not already created
// This ensures render thread is ready even if caps negotiation hasn't completed
if (!gst_nv_video_context_create (nv3dsink->context)) {
GST_DEBUG_OBJECT (nv3dsink, "failed to create render thread, dropping frame");
return GST_FLOW_FLUSHING;
}
if (!gst_nv_video_context_show_frame (nv3dsink->context, buf)) {
GST_DEBUG_OBJECT (nv3dsink, "render thread not ready, dropping frame");
return GST_FLOW_FLUSHING;
}
return GST_FLOW_OK;
}
static gboolean
gst_nv3dsink_event (GstBaseSink * bsink, GstEvent * event)
{
GstNv3dSink *nv3dsink = GST_NV3DSINK (bsink);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
gst_nv_video_context_handle_eos (nv3dsink->context);
break;
default:
break;
}
if (GST_BASE_SINK_CLASS (parent_class)->event)
return GST_BASE_SINK_CLASS (parent_class)->event (bsink, event);
else
gst_event_unref (event);
return TRUE;
}
static GstStateChangeReturn
gst_nv3dsink_change_state (GstElement * element, GstStateChange transition)
{
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
GstNv3dSink *nv3dsink = GST_NV3DSINK (element);
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY:
/* call handle_eos to unref last buffer */
gst_nv_video_context_handle_eos (nv3dsink->context);
break;
default:
break;
}
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
return ret;
}
/* initialize the plugin's class */
static void
gst_nv3dsink_class_init (GstNv3dSinkClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstBaseSinkClass *gstbasesink_class;
GstVideoSinkClass *gstvideosink_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstbasesink_class = (GstBaseSinkClass *) klass;
gstvideosink_class = (GstVideoSinkClass *) klass;
gobject_class->set_property = gst_nv3dsink_set_property;
gobject_class->get_property = gst_nv3dsink_get_property;
gst_element_class_set_static_metadata (gstelement_class, "Nvidia 3D sink",
"Sink/Video", "A videosink based on 3D graphics rendering API",
"Yogish Kulkarni <yogishk@nvidia.com>");
gobject_class->finalize = gst_nv3dsink_finalize;
gst_element_class_add_static_pad_template (gstelement_class,
&gst_nv3dsink_sink_template_factory);
gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_nv3dsink_start);
gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_nv3dsink_stop);
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_nv3dsink_set_caps);
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_nv3dsink_get_caps);
gstbasesink_class->propose_allocation =
GST_DEBUG_FUNCPTR (gst_nv3dsink_propose_allocation);
gstbasesink_class->event = gst_nv3dsink_event;
gstvideosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_nv3dsink_show_frame);
gstelement_class->change_state = gst_nv3dsink_change_state;
g_object_class_install_property (gobject_class, PROP_WINDOW_X,
g_param_spec_uint ("window-x",
"Window x coordinate",
"X coordinate of window", 0, G_MAXINT, 10,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_WINDOW_Y,
g_param_spec_uint ("window-y",
"Window y coordinate",
"Y coordinate of window", 0, G_MAXINT, 10,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_WINDOW_WIDTH,
g_param_spec_uint ("window-width",
"Window width",
"Width of window", 0, G_MAXINT, 0,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_WINDOW_HEIGHT,
g_param_spec_uint ("window-height",
"Window height",
"Height of window", 0, G_MAXINT, 0,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
/* initialize the new element */
static void
gst_nv3dsink_init (GstNv3dSink * nv3dsink)
{
GST_TRACE_OBJECT (nv3dsink, "init");
nv3dsink->display = NULL;
nv3dsink->context = NULL;
nv3dsink->window = NULL;
nv3dsink->window_x = 0;
nv3dsink->window_y = 0;
nv3dsink->window_width = 0;
nv3dsink->window_height = 0;
nv3dsink->configured_caps = NULL;
/* mutex to serialize create, set and get window handle calls */
g_mutex_init (&nv3dsink->win_handle_lock);
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 2018-2022, NVIDIA CORPORATION. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License, version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef __GST_NV3DSINK_H__
#define __GST_NV3DSINK_H__
#include <gst/gst.h>
#include <gst/video/gstvideosink.h>
#include <gst/video/video.h>
#include "gstnvvideofwd.h"
G_BEGIN_DECLS
GST_DEBUG_CATEGORY_EXTERN (gst_debug_nv3dsink);
#define GST_TYPE_NV3DSINK \
(gst_nv3dsink_get_type())
#define GST_NV3DSINK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_NV3DSINK, GstNv3dSink))
#define GST_NV3DSINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_NV3DSINK, GstNv3dSinkClass))
#define GST_IS_NV3DSINK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_NV3DSINK))
#define GST_IS_NV3DSINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_NV3DSINK))
typedef struct _GstNv3dSink GstNv3dSink;
typedef struct _GstNv3dSinkClass GstNv3dSinkClass;
struct _GstNv3dSink
{
GstVideoSink parent;
GstNvVideoDisplay *display;
GstNvVideoContext *context;
GstNvVideoWindow *window;
gint window_x;
gint window_y;
gint window_width;
gint window_height;
GMutex win_handle_lock;
GstCaps *configured_caps;
};
struct _GstNv3dSinkClass
{
GstVideoSinkClass parent_class;
};
GType gst_nv3dsink_get_type (void);
G_END_DECLS
#endif /* __GST_NV3DSINK_H__ */

1075
nvbufsurface.h Normal file
View File

File diff suppressed because it is too large Load Diff

1
push_info.txt Normal file
View File

@@ -0,0 +1 @@
jetson_38.2