diff --git a/commitFile.txt b/commitFile.txt
new file mode 100644
index 0000000..01e2445
--- /dev/null
+++ b/commitFile.txt
@@ -0,0 +1,7 @@
+Updating prebuilts and/or headers
+
+444b666f460d87e0278892a2d7520d65e68679ec - gst-nvvidconv/Makefile
+ebface35fce001fdc5889214e11a84bf13cb5fde - gst-nvvidconv/3rdpartyheaders.tbz2
+d65280463c41199eb271155cadebf929bce0bdea - gst-nvvidconv/gstnvvconv.c
+44b0e909f18f7e2f457ba501fc47d80ecedd150b - gst-nvvidconv/nvbufsurface.h
+35e7c6a5e5a32948bc89931a83df5f544585a691 - gst-nvvidconv/gstnvvconv.h
diff --git a/gst-nvvidconv/3rdpartyheaders.tbz2 b/gst-nvvidconv/3rdpartyheaders.tbz2
new file mode 100644
index 0000000..94a0430
Binary files /dev/null and b/gst-nvvidconv/3rdpartyheaders.tbz2 differ
diff --git a/gst-nvvidconv/Makefile b/gst-nvvidconv/Makefile
new file mode 100644
index 0000000..79edca7
--- /dev/null
+++ b/gst-nvvidconv/Makefile
@@ -0,0 +1,83 @@
+# Copyright (c) 2020-2022, NVIDIA CORPORATION. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+SO_NAME := libgstnvvidconv.so
+
+CC := gcc
+
+ARCH := $(shell uname -m)
+
+GST_INSTALL_DIR?=/usr/lib/$(ARCH)-linux-gnu/gstreamer-1.0/
+LIB_INSTALL_DIR?=/usr/lib/$(ARCH)-linux-gnu/tegra/
+CFLAGS:=
+LIBS:= -lnvbufsurface -lnvbufsurftransform -lcudart
+
+SRCS := $(wildcard *.c)
+
+ifdef CUDA_VER
+CUDA_PATH := /usr/local/cuda-$(CUDA_VER)
+else
+CUDA_PATH := /usr/local/cuda
+endif
+INCLUDES += -I$(CUDA_PATH)/include
+INCLUDES += -I$(CUDA_PATH)/targets/$(ARCH)-linux/include
+
+INCLUDES += -I./
+
+PKGS := gstreamer-1.0 \
+ gstreamer-base-1.0 \
+ gstreamer-video-1.0 \
+ gstreamer-allocators-1.0 \
+ glib-2.0
+
+OBJS := $(SRCS:.c=.o)
+
+CFLAGS += -fPIC
+
+CFLAGS += `pkg-config --cflags $(PKGS)`
+
+LDFLAGS = -Wl,--no-undefined -L$(LIB_INSTALL_DIR) -Wl,-rpath,$(LIB_INSTALL_DIR)
+LDFLAGS += -L$(CUDA_PATH)/targets/$(ARCH)-linux/lib/
+
+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?= $(GST_INSTALL_DIR)
+install: $(SO_NAME)
+ cp -vp $(SO_NAME) $(DEST_DIR)
+
+.PHONY: clean
+clean:
+ rm -rf $(OBJS) $(SO_NAME)
diff --git a/gst-nvvidconv/README.txt b/gst-nvvidconv/README.txt
new file mode 100644
index 0000000..cce9cd2
--- /dev/null
+++ b/gst-nvvidconv/README.txt
@@ -0,0 +1,49 @@
+# Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Steps to compile the "gst-nvvidconv" sources natively:
+
+1) Install gstreamer related packages on target using the command:
+
+ sudo apt-get install libgstreamer1.0-dev \
+ gstreamer1.0-plugins-base \
+ gstreamer1.0-plugins-good \
+ libgstreamer-plugins-base1.0-dev
+
+2) Download and extract the package "gst-nvvidconv_src.tbz2" as follows:
+
+ tar -I lbzip2 -xvf gst-nvvidconv_src.tbz2
+
+3) Run the following commands to build and install "libgstnvvidconv.so":
+ cd "gst-nvvidconv"
+ make
+ make install
+ or
+ DEST_DIR=
make install
+
+ Note: "make install" will copy library "libgstnvvidconv.so"
+ into "/usr/lib/aarch64-linux-gnu/gstreamer-1.0" directory.
diff --git a/gst-nvvidconv/gstnvvconv.c b/gst-nvvidconv/gstnvvconv.c
new file mode 100644
index 0000000..92911c5
--- /dev/null
+++ b/gst-nvvidconv/gstnvvconv.c
@@ -0,0 +1,3643 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2014-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Relation between width, height, PAR(Pixel Aspect Ratio), DAR(Display Aspect Ration):
+ *
+ * dar_n par_d
+ * width = height * ----- * -----
+ * dar_d par_n
+ *
+ * dar_d par_n
+ * height = width * ----- * -----
+ * dar_n par_d
+ *
+ * par_n height dar_n
+ * ----- = ------ * -----
+ * par_d width dar_d
+ *
+ * dar_n width par_n
+ * ----- = ------ * -----
+ * dar_d height par_d
+ */
+
+#include
+#include
+#include
+
+#include "gstnvvconv.h"
+
+#define NVBUF_MAGIC_NUM 0x70807580
+
+GST_DEBUG_CATEGORY_STATIC (gst_nvvconv_debug);
+#define GST_CAT_DEFAULT gst_nvvconv_debug
+
+/* Filter signals and args */
+enum
+{
+ /* FILL ME */
+ LAST_SIGNAL
+};
+
+/* Filter properties */
+enum
+{
+ PROP_0,
+ PROP_SILENT,
+ PROP_FLIP_METHOD,
+ PROP_NUM_OUT_BUFS,
+ PROP_INTERPOLATION_METHOD,
+ PROP_LEFT,
+ PROP_RIGHT,
+ PROP_TOP,
+ PROP_BOTTOM,
+ PROP_ENABLE_BLOCKLINEAR_OUTPUT,
+ PROP_GPU_DEVICE_ID,
+ PROP_COMPUTE_HW,
+ PROP_NVBUF_MEMORY_TYPE,
+};
+
+#undef MAX_NUM_PLANES
+#include "nvbufsurface.h"
+
+static gboolean is_nvgpu = TRUE;
+
+#define PROP_FLIP_METHOD_DEFAULT GST_VIDEO_NVFLIP_METHOD_IDENTITY
+
+#define GST_TYPE_VIDEO_NVFLIP_METHOD (gst_video_nvflip_method_get_type())
+
+static const GEnumValue video_nvflip_methods[] = {
+ {GST_VIDEO_NVFLIP_METHOD_IDENTITY, "Identity (no rotation)", "none"},
+ {GST_VIDEO_NVFLIP_METHOD_90L, "Rotate counter-clockwise 90 degrees",
+ "counterclockwise"},
+ {GST_VIDEO_NVFLIP_METHOD_180, "Rotate 180 degrees", "rotate-180"},
+ {GST_VIDEO_NVFLIP_METHOD_90R, "Rotate clockwise 90 degrees", "clockwise"},
+ {GST_VIDEO_NVFLIP_METHOD_HORIZ, "Flip horizontally", "horizontal-flip"},
+ {GST_VIDEO_NVFLIP_METHOD_INVTRANS,
+ "Flip across upper right/lower left diagonal", "upper-right-diagonal"},
+ {GST_VIDEO_NVFLIP_METHOD_VERT, "Flip vertically", "vertical-flip"},
+ {GST_VIDEO_NVFLIP_METHOD_TRANS,
+ "Flip across upper left/lower right diagonal", "upper-left-diagonal"},
+ {0, NULL, NULL},
+};
+
+static GType
+gst_video_nvflip_method_get_type (void)
+{
+ static GType video_nvflip_method_type = 0;
+
+ if (!video_nvflip_method_type) {
+ video_nvflip_method_type = g_enum_register_static ("GstNvVideoFlipMethod",
+ video_nvflip_methods);
+ }
+ return video_nvflip_method_type;
+}
+
+#define GST_TYPE_INTERPOLATION_METHOD (gst_video_interpolation_method_get_type())
+
+static const GEnumValue video_interpolation_methods[] = {
+ {GST_INTERPOLATION_NEAREST, "Nearest", "Nearest"},
+ {GST_INTERPOLATION_BILINEAR, "Bilinear", "Bilinear"},
+ {GST_INTERPOLATION_5_TAP, "5-Tap", "5-Tap"},
+ {GST_INTERPOLATION_10_TAP, "10-Tap", "10-Tap"},
+ {GST_INTERPOLATION_SMART, "Smart", "Smart"},
+ {GST_INTERPOLATION_NICEST, "Nicest", "Nicest"},
+ {0, NULL, NULL},
+};
+
+static GType
+gst_video_interpolation_method_get_type (void)
+{
+ static GType video_interpolation_method_type = 0;
+
+ if (!video_interpolation_method_type) {
+ video_interpolation_method_type = g_enum_register_static ("GstInterpolationMethod",
+ video_interpolation_methods);
+ }
+ return video_interpolation_method_type;
+}
+
+#define GST_TYPE_COMPUTE_HW (gst_compute_hw_get_type ())
+
+static const GEnumValue compute_hw[] = {
+ {NvBufSurfTransformCompute_Default, "Default, VIC for Jetson", "Default"},
+ {NvBufSurfTransformCompute_GPU, "GPU", "GPU"},
+ {NvBufSurfTransformCompute_VIC, "VIC", "VIC"},
+ {0, NULL, NULL},
+};
+
+static GType
+gst_compute_hw_get_type (void)
+{
+ static GType compute_hw_type = 0;
+
+ if(!compute_hw_type) {
+ compute_hw_type = g_enum_register_static ("GstNvVidConvComputeHWType",
+ compute_hw);
+ }
+
+ return compute_hw_type;
+}
+
+#define GST_TYPE_NVBUF_MEMORY_TYPE (gst_nvbuf_memory_get_type ())
+
+static const GEnumValue memory_format[] = {
+ { NVBUF_MEM_DEFAULT,
+ "Default memory allocated, specific to particular platform", "nvbuf-mem-default"},
+ { NVBUF_MEM_CUDA_PINNED,
+ "Allocate Pinned/Host cuda memory", "nvbuf-mem-cuda-pinned"},
+ { NVBUF_MEM_CUDA_DEVICE,
+ "Allocate Device cuda memory", "nvbuf-mem-cuda-device"},
+ { NVBUF_MEM_SURFACE_ARRAY,
+ "Allocate Surface Array memory, applicable for Jetson", "nvbuf-mem-surface-array"},
+ {0, NULL, NULL}
+};
+
+static GType
+gst_nvbuf_memory_get_type (void)
+{
+ static GType memory_format_type = 0;
+
+ if (!memory_format_type) {
+ memory_format_type = g_enum_register_static ("GstNvVidConvBufMemoryType",
+ memory_format);
+ }
+
+ return memory_format_type;
+}
+
+/* capabilities of the inputs and outputs */
+
+/* Input capabilities. */
+static GstStaticPadTemplate gst_nvvconv_sink_template =
+ GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
+ (GST_CAPS_FEATURE_MEMORY_NVMM,
+ "{ " "I420, I420_10LE, P010_10LE, I420_12LE, UYVY, YUY2, YVYU, NV12, NV16, NV24, GRAY8, BGRx, RGBA, Y42B, Y444 }") ";" GST_VIDEO_CAPS_MAKE ("{ "
+ "I420, UYVY, YUY2, YVYU, NV12, NV16, NV24, P010_10LE, GRAY8, BGRx, RGBA, Y42B, Y444 }")));
+
+/* Output capabilities. */
+static GstStaticPadTemplate gst_nvvconv_src_template =
+ GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
+ (GST_CAPS_FEATURE_MEMORY_NVMM,
+ "{ " "I420, I420_10LE, P010_10LE, UYVY, YUY2, YVYU, NV12, NV16, NV24, GRAY8, BGRx, RGBA, Y42B, Y444 }") ";" GST_VIDEO_CAPS_MAKE ("{ "
+ "I420, UYVY, YUY2, YVYU, NV12, NV16, NV24, GRAY8, BGRx, RGBA, Y42B, Y444 }")));
+
+static GstElementClass *gparent_class = NULL;
+
+#define gst_nvvconv_parent_class parent_class
+G_DEFINE_TYPE (Gstnvvconv, gst_nvvconv, GST_TYPE_BASE_TRANSFORM);
+
+/* internal methods */
+static void gst_nvvconv_init_params (Gstnvvconv * filter);
+static gboolean gst_nvvconv_get_pix_fmt (GstVideoInfo * info,
+ NvBufSurfaceColorFormat * pix_fmt, gint * isurf_count);
+static GstCaps *gst_nvvconv_caps_remove_format_info (GstCaps * caps);
+static gboolean gst_nvvconv_do_clearchroma (Gstnvvconv * filter,
+ NvBufSurface *surface);
+static void gst_nvvconv_free_buf (Gstnvvconv * filter);
+
+/* base transform vmethods */
+static gboolean gst_nvvconv_start (GstBaseTransform * btrans);
+static gboolean gst_nvvconv_stop (GstBaseTransform * btrans);
+static void gst_nvvconv_finalize (GObject * object);
+static GstStateChangeReturn gst_nvvconv_change_state (GstElement * element,
+ GstStateChange transition);
+static GstFlowReturn gst_nvvconv_transform (GstBaseTransform * btrans,
+ GstBuffer * inbuf, GstBuffer * outbuf);
+static gboolean gst_nvvconv_set_caps (GstBaseTransform * btrans,
+ GstCaps * incaps, GstCaps * outcaps);
+static GstCaps *gst_nvvconv_transform_caps (GstBaseTransform * btrans,
+ GstPadDirection direction, GstCaps * caps, GstCaps * filter);
+static gboolean gst_nvvconv_accept_caps (GstBaseTransform * btrans,
+ GstPadDirection direction, GstCaps * caps);
+static gboolean gst_nvvconv_transform_size (GstBaseTransform * btrans,
+ GstPadDirection direction, GstCaps * caps, gsize size,
+ GstCaps * othercaps, gsize * othersize);
+static gboolean gst_nvvconv_get_unit_size (GstBaseTransform * btrans,
+ GstCaps * caps, gsize * size);
+static GstCaps *gst_nvvconv_fixate_caps (GstBaseTransform * btrans,
+ GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
+static gboolean gst_nvvconv_decide_allocation (GstBaseTransform * btrans,
+ GstQuery * query);
+
+static void gst_nvvconv_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_nvvconv_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+#define GST_NV_FILTER_MEMORY_TYPE "nvfilter"
+
+/* NvFilter memory allocator Implementation */
+
+typedef struct _GstNvFilterMemory GstNvFilterMemory;
+typedef struct _GstNvFilterMemoryAllocator GstNvFilterMemoryAllocator;
+typedef struct _GstNvFilterMemoryAllocatorClass GstNvFilterMemoryAllocatorClass;
+
+struct _GstNvFilterMemory
+{
+ GstMemory mem;
+ GstNvvConvBuffer *buf;
+};
+
+struct _GstNvFilterMemoryAllocator
+{
+ GstAllocator parent;
+};
+
+struct _GstNvFilterMemoryAllocatorClass
+{
+ GstAllocatorClass parent_class;
+};
+
+/**
+ * implementation that acquire memory.
+ *
+ * @param allocator : gst memory allocatot object
+ * @param size : memory size
+ * @param params : allovcation params
+ */
+static GstMemory *
+gst_nv_filter_memory_allocator_alloc_dummy (GstAllocator * allocator,
+ gsize size, GstAllocationParams * params)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
+/**
+ * implementation that releases memory.
+ *
+ * @param allocator : gst memory allocatot object
+ * @param mem : gst memory
+ */
+static void
+gst_nv_filter_memory_allocator_free (GstAllocator * allocator, GstMemory * mem)
+{
+ gint ret = 0;
+ GstNvFilterMemory *omem = (GstNvFilterMemory *) mem;
+ GstNvvConvBuffer *nvbuf = omem->buf;
+
+ ret = NvBufSurfaceDestroy (nvbuf->surface);
+ if (ret != 0) {
+ GST_ERROR ("%s: NvBufSurfaceDestroy Failed \n", __func__);
+ goto error;
+ }
+
+error:
+ g_slice_free (GstNvvConvBuffer, nvbuf);
+ g_slice_free (GstNvFilterMemory, omem);
+}
+
+/**
+ * memory map function.
+ *
+ * @param mem : gst memory
+ * @param maxsize : memory max size
+ * @param flags : Flags for wrapped memory
+ */
+static gpointer
+gst_nv_filter_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
+{
+ GstNvFilterMemory *omem = (GstNvFilterMemory *) mem;
+
+ if (!omem) {
+ g_print ("%s: GstNvFilterMemory object ptr is NULL\n", __func__);
+ return NULL;
+ }
+
+ return (gpointer)(omem->buf->surface);
+}
+
+/**
+ * memory unmap function.
+ *
+ * @param mem : gst memory
+ */
+static void
+gst_nv_filter_memory_unmap (GstMemory * mem)
+{
+}
+
+/**
+ * memory share function.
+ *
+ * @param mem : gst memory
+ */
+static GstMemory *
+gst_nv_filter_memory_share (GstMemory * mem, gssize offset, gssize size)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
+GType gst_nv_filter_memory_allocator_get_type (void);
+G_DEFINE_TYPE (GstNvFilterMemoryAllocator, gst_nv_filter_memory_allocator,
+ GST_TYPE_ALLOCATOR);
+
+#define GST_TYPE_NV_FILTER_MEMORY_ALLOCATOR (gst_nv_filter_memory_allocator_get_type())
+#define GST_IS_NV_FILTER_MEMORY_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_NV_FILTER_MEMORY_ALLOCATOR))
+
+/**
+ * initialize the nvfilter allocator's class.
+ *
+ * @param klass : nvfilter memory allocator objectclass
+ */
+static void
+gst_nv_filter_memory_allocator_class_init (GstNvFilterMemoryAllocatorClass *
+ klass)
+{
+ GstAllocatorClass *allocator_class;
+
+ allocator_class = GST_ALLOCATOR_CLASS (klass);
+
+ allocator_class->alloc = gst_nv_filter_memory_allocator_alloc_dummy;
+ allocator_class->free = gst_nv_filter_memory_allocator_free;
+}
+
+/**
+ * nvfilter allocator init function.
+ *
+ * @param allocator : nvfilter allocator object instance
+ */
+static void
+gst_nv_filter_memory_allocator_init (GstNvFilterMemoryAllocator * allocator)
+{
+ GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
+
+ alloc->mem_type = GST_NV_FILTER_MEMORY_TYPE;
+ alloc->mem_map = gst_nv_filter_memory_map;
+ alloc->mem_unmap = gst_nv_filter_memory_unmap;
+ alloc->mem_share = gst_nv_filter_memory_share;
+
+ GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
+}
+
+/**
+ * custom memory allocation.
+ *
+ * @param allocator : nvfilter bufferpool allocator
+ * @param flags : Flags for wrapped memory
+ * @param space : nvvidconv object instance
+ */
+static GstMemory *
+gst_nv_filter_memory_allocator_alloc (GstAllocator * allocator,
+ GstMemoryFlags flags, Gstnvvconv * space)
+{
+ gint ret = 0;
+ GstNvFilterMemory *mem = NULL;
+ GstNvvConvBuffer *nvbuf = NULL;
+
+ NvBufSurfaceAllocateParams input_params = {0};
+
+ mem = g_slice_new0 (GstNvFilterMemory);
+ nvbuf = g_slice_new0 (GstNvvConvBuffer);
+
+ input_params.params.width = space->to_width;
+ input_params.params.height = space->to_height;
+ /*
+ * GPU supports only pitch linear memory for output
+ */
+ if (space->compute_hw == NvBufSurfTransformCompute_GPU) {
+ input_params.params.layout = NVBUF_LAYOUT_PITCH;
+ }
+ else {
+ if (space->enable_blocklinear_output &&
+ (space->out_pix_fmt == NVBUF_COLOR_FORMAT_NV12 ||
+ space->out_pix_fmt == NVBUF_COLOR_FORMAT_NV12_ER ||
+ space->out_pix_fmt == NVBUF_COLOR_FORMAT_NV12_709 ||
+ space->out_pix_fmt == NVBUF_COLOR_FORMAT_NV12_709_ER ||
+ space->out_pix_fmt == NVBUF_COLOR_FORMAT_NV12_2020 ||
+ space->out_pix_fmt == NVBUF_COLOR_FORMAT_NV12_10LE))
+ input_params.params.layout = NVBUF_LAYOUT_BLOCK_LINEAR;
+ else
+ input_params.params.layout = NVBUF_LAYOUT_PITCH;
+ }
+
+ input_params.params.colorFormat = space->out_pix_fmt;
+ /*
+ * GPU supports CUDA memories as well as surface array
+ * memory through EGL mapping where as VIC only supports
+ * surface array memory
+ */
+ if (space->compute_hw == NvBufSurfTransformCompute_GPU) {
+ input_params.params.memType = space->nvbuf_mem_type;
+ input_params.params.gpuId = space->gpu_id;
+ } else {
+ if (space->nvbuf_mem_type == NVBUF_MEM_CUDA_DEVICE ||
+ space->nvbuf_mem_type == NVBUF_MEM_CUDA_PINNED) {
+ GST_DEBUG ("VIC don't support CUDA memory so taking surface array memory");
+ }
+ input_params.params.memType = NVBUF_MEM_SURFACE_ARRAY;
+ }
+ input_params.memtag = NvBufSurfaceTag_VIDEO_CONVERT;
+
+ ret = NvBufSurfaceAllocate(&nvbuf->surface, 1, &input_params);
+ if (ret != 0) {
+ GST_ERROR ("%s: NvBufSurfaceAllocate Failed \n", __func__);
+ goto error;
+ }
+ nvbuf->surface->numFilled = 1;
+ nvbuf->dmabuf_fd = nvbuf->surface->surfaceList[0].bufferDesc;
+
+ flags |= GST_MEMORY_FLAG_NO_SHARE;
+
+ /* Check for init params */
+ gst_memory_init (GST_MEMORY_CAST (mem), flags, allocator, NULL,
+ sizeof(NvBufSurface), 0 /* Alignment */,
+ 0, sizeof(NvBufSurface));
+ mem->buf = nvbuf;
+ mem->buf->dmabuf_fd = nvbuf->dmabuf_fd;
+
+ return GST_MEMORY_CAST (mem);
+
+error:
+ g_slice_free (GstNvvConvBuffer, nvbuf);
+ g_slice_free (GstNvFilterMemory, mem);
+
+ return NULL;
+}
+
+/* nvfilter Buffer Pool for nvmm buffers */
+
+GQuark gst_nv_filter_data_quark = 0;
+typedef struct _GstNvFilterBufferPool GstNvFilterBufferPool;
+typedef struct _GstNvFilterBufferPoolClass GstNvFilterBufferPoolClass;
+#define GST_NV_FILTER_BUFFER_POOL(pool) ((GstNvFilterBufferPool *) pool)
+
+struct _GstNvFilterBufferPool
+{
+ GstBufferPool parent;
+
+ GstElement *element;
+
+ GstCaps *caps;
+ gboolean add_videometa;
+ GstVideoInfo video_info;
+
+ GstAllocator *allocator;
+
+ guint current_buffer_index;
+};
+
+struct _GstNvFilterBufferPoolClass
+{
+ GstBufferPoolClass parent_class;
+};
+
+GType gst_nv_filter_buffer_pool_get_type (void);
+
+G_DEFINE_TYPE (GstNvFilterBufferPool, gst_nv_filter_buffer_pool,
+ GST_TYPE_BUFFER_POOL);
+
+#define GST_TYPE_NV_FILTER_BUFFER_POOL (gst_nv_filter_buffer_pool_get_type())
+
+/**
+ * object class finallize.
+ *
+ * @param object : object
+ */
+static void
+gst_nv_filter_buffer_pool_finalize (GObject * object)
+{
+ GstNvFilterBufferPool *pool = GST_NV_FILTER_BUFFER_POOL (object);
+
+ if (pool->element)
+ gst_object_unref (pool->element);
+ pool->element = NULL;
+
+ if (pool->allocator)
+ gst_object_unref (pool->allocator);
+ pool->allocator = NULL;
+
+ if (pool->caps)
+ gst_caps_unref (pool->caps);
+ pool->caps = NULL;
+
+ G_OBJECT_CLASS (gst_nv_filter_buffer_pool_parent_class)->finalize (object);
+}
+
+/**
+ * start the bufferpool.
+ *
+ * @param bpool : nvfilter bufferpool object
+ */
+static gboolean
+gst_nv_filter_buffer_pool_start (GstBufferPool * bpool)
+{
+ GstNvFilterBufferPool *pool = GST_NV_FILTER_BUFFER_POOL (bpool);
+
+ GST_DEBUG_OBJECT (pool, "start");
+
+ GST_OBJECT_LOCK (pool);
+ /* Start the pool only if we have component attached to it. */
+ if (!pool->element) {
+ GST_OBJECT_UNLOCK (pool);
+ return FALSE;
+ }
+ GST_OBJECT_UNLOCK (pool);
+
+ return
+ GST_BUFFER_POOL_CLASS (gst_nv_filter_buffer_pool_parent_class)->start
+ (bpool);
+}
+
+/**
+ * stop the bufferpool.
+ *
+ * @param bpool : nvfilter bufferpool object
+ */
+static gboolean
+gst_nv_filter_buffer_pool_stop (GstBufferPool * bpool)
+{
+ GstNvFilterBufferPool *pool = GST_NV_FILTER_BUFFER_POOL (bpool);
+
+ GST_DEBUG_OBJECT (pool, "stop");
+
+ if (pool->caps)
+ gst_caps_unref (pool->caps);
+
+ pool->caps = NULL;
+ pool->add_videometa = FALSE;
+
+ return
+ GST_BUFFER_POOL_CLASS (gst_nv_filter_buffer_pool_parent_class)->stop
+ (bpool);
+}
+
+
+/**
+ * get a list of options supported by this pool.
+ *
+ * @param bpool : nvfilter bufferpool object
+ */
+static const gchar **
+gst_nv_filter_buffer_pool_get_options (GstBufferPool * bpool)
+{
+ static const gchar *video_options[] =
+ { GST_BUFFER_POOL_OPTION_VIDEO_META, NULL };
+
+ /* Currently, we are only providing VIDEO_META option by default. */
+
+ return video_options;
+}
+
+/**
+ * apply the bufferpool configuration.
+ *
+ * @param bpool : nvfilter bufferpool object
+ * @param config : config parameters
+ */
+static gboolean
+gst_nv_filter_buffer_pool_set_config (GstBufferPool * bpool,
+ GstStructure * config)
+{
+ GstNvFilterBufferPool *pool = GST_NV_FILTER_BUFFER_POOL (bpool);
+ GstCaps *caps = NULL;
+
+ GST_DEBUG_OBJECT (pool, "set_config");
+
+ GST_OBJECT_LOCK (pool);
+
+ if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
+ goto wrong_config;
+
+ if (caps == NULL)
+ goto no_caps;
+
+ GstVideoInfo info = {0};
+
+ /* now parse the caps from the config */
+ if (!gst_video_info_from_caps (&info, caps))
+ goto wrong_video_caps;
+
+ /* enable metadata based on config of the pool */
+ pool->add_videometa =
+ gst_buffer_pool_config_has_option (config,
+ GST_BUFFER_POOL_OPTION_VIDEO_META);
+
+ pool->video_info = info;
+
+ if (pool->caps)
+ gst_caps_unref (pool->caps);
+ pool->caps = gst_caps_ref (caps);
+
+ GST_OBJECT_UNLOCK (pool);
+
+ return
+ GST_BUFFER_POOL_CLASS (gst_nv_filter_buffer_pool_parent_class)->set_config
+ (bpool, config);
+
+ /* ERRORS */
+wrong_config:
+ {
+ GST_OBJECT_UNLOCK (pool);
+ GST_WARNING_OBJECT (pool, "invalid config");
+ return FALSE;
+ }
+no_caps:
+ {
+ GST_OBJECT_UNLOCK (pool);
+ GST_WARNING_OBJECT (pool, "no caps in config");
+ return FALSE;
+ }
+wrong_video_caps:
+ {
+ GST_OBJECT_UNLOCK (pool);
+ GST_WARNING_OBJECT (pool,
+ "failed getting geometry from caps %" GST_PTR_FORMAT, caps);
+ return FALSE;
+ }
+}
+
+/**
+ * allocate a buffer.
+ *
+ * @param bpool : nvfilter bufferpool object
+ * @param buffer : GstBuffer of pool
+ * @param params : pool acquire parameters
+ */
+static GstFlowReturn
+gst_nv_filter_buffer_pool_alloc_buffer (GstBufferPool * bpool,
+ GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
+{
+ GstNvFilterBufferPool *pool = GST_NV_FILTER_BUFFER_POOL (bpool);
+ Gstnvvconv *space = GST_NVVCONV (pool->element);
+ GstBuffer *buf = NULL;
+ GstMemory *mem = NULL;
+
+ GST_DEBUG_OBJECT (pool, "alloc_buffer");
+
+ mem = gst_nv_filter_memory_allocator_alloc (pool->allocator, 0, space);
+ g_return_val_if_fail (mem, GST_FLOW_ERROR);
+
+ buf = gst_buffer_new ();
+ gst_buffer_append_memory (buf, mem);
+
+ if (pool->add_videometa) {
+ /* TODO : Add video meta to buffer */
+ }
+
+ gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (mem),
+ gst_nv_filter_data_quark, buf, NULL);
+
+ *buffer = buf;
+
+ pool->current_buffer_index++;
+
+ return GST_FLOW_OK;
+}
+
+
+/**
+ * free a buffer.
+ *
+ * @param bpool : nvfilter bufferpool object
+ * @param buffer : GstBuffer of pool
+ */
+static void
+gst_nv_filter_buffer_pool_free_buffer (GstBufferPool * bpool,
+ GstBuffer * buffer)
+{
+ GstMemory *memory;
+ GstNvFilterBufferPool *pool = GST_NV_FILTER_BUFFER_POOL (bpool);
+
+ GST_DEBUG_OBJECT (pool, "free_buffer");
+
+ memory = gst_buffer_peek_memory (buffer, 0);
+
+ gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (memory),
+ gst_nv_filter_data_quark, NULL, NULL);
+
+ GST_BUFFER_POOL_CLASS (gst_nv_filter_buffer_pool_parent_class)->free_buffer
+ (bpool, buffer);
+}
+
+/**
+ * get a new buffer from the nvfilter bufferpool.
+ *
+ * @param bpool : nvfilter bufferpool object
+ * @param buffer : GstBuffer of pool
+ * @param params : pool acquire parameters
+ */
+static GstFlowReturn
+gst_nv_filter_buffer_pool_acquire_buffer (GstBufferPool * bpool,
+ GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
+{
+ GstFlowReturn ret;
+ GstNvFilterBufferPool *pool = GST_NV_FILTER_BUFFER_POOL (bpool);
+
+ GST_DEBUG_OBJECT (pool, "acquire_buffer");
+
+ ret =
+ GST_BUFFER_POOL_CLASS (gst_nv_filter_buffer_pool_parent_class)->
+ acquire_buffer (bpool, buffer, params);
+
+ return ret;
+}
+
+/**
+ * release a buffer back in the nvfilter bufferpool.
+ *
+ * @param bpool : nvfilter bufferpool object
+ * @param buffer : GstBuffer of pool
+ */
+static void
+gst_nv_filter_buffer_pool_release_buffer (GstBufferPool * bpool,
+ GstBuffer * buffer)
+{
+ GstNvFilterBufferPool *pool = GST_NV_FILTER_BUFFER_POOL (bpool);
+
+ GST_DEBUG_OBJECT (pool, "release_buffer");
+
+ GST_BUFFER_POOL_CLASS (gst_nv_filter_buffer_pool_parent_class)->release_buffer
+ (bpool, buffer);
+}
+
+/**
+ * initialize the nvfilter bufferpool's class.
+ *
+ * @param klass : nvfilter bufferpool objectclass
+ */
+static void
+gst_nv_filter_buffer_pool_class_init (GstNvFilterBufferPoolClass * klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
+
+ gst_nv_filter_data_quark =
+ g_quark_from_static_string ("GstNvFilterBufferData");
+
+ gobject_class->finalize = gst_nv_filter_buffer_pool_finalize;
+ gstbufferpool_class->start = gst_nv_filter_buffer_pool_start;
+ gstbufferpool_class->stop = gst_nv_filter_buffer_pool_stop;
+ gstbufferpool_class->get_options = gst_nv_filter_buffer_pool_get_options;
+ gstbufferpool_class->set_config = gst_nv_filter_buffer_pool_set_config;
+ gstbufferpool_class->alloc_buffer = gst_nv_filter_buffer_pool_alloc_buffer;
+ gstbufferpool_class->free_buffer = gst_nv_filter_buffer_pool_free_buffer;
+ gstbufferpool_class->acquire_buffer =
+ gst_nv_filter_buffer_pool_acquire_buffer;
+ gstbufferpool_class->release_buffer =
+ gst_nv_filter_buffer_pool_release_buffer;
+}
+
+/**
+ * nvfilter bufferpool init function.
+ *
+ * @param pool : nvfilter bufferpool object instance
+ */
+static void
+gst_nv_filter_buffer_pool_init (GstNvFilterBufferPool * pool)
+{
+ pool->allocator =
+ g_object_new (gst_nv_filter_memory_allocator_get_type (), NULL);
+ pool->current_buffer_index = 0;
+}
+
+/**
+ * Create nvfilter bufferpool object instance.
+ *
+ * @param element : GstElement object instance
+ */
+static GstBufferPool *
+gst_nv_filter_buffer_pool_new (GstElement * element)
+{
+ GstNvFilterBufferPool *pool;
+
+ pool = g_object_new (GST_TYPE_NV_FILTER_BUFFER_POOL, NULL);
+ pool->element = gst_object_ref (element);
+
+ return GST_BUFFER_POOL (pool);
+}
+
+/**
+ * copies the given caps.
+ *
+ * @param caps : given pad caps
+ */
+static GstCaps *
+gst_nvvconv_caps_remove_format_info (GstCaps * caps)
+{
+ GstStructure *str;
+ GstCapsFeatures *features;
+ gint i, n;
+ GstCaps *ret;
+
+ ret = gst_caps_new_empty ();
+
+ n = gst_caps_get_size (caps);
+ for (i = 0; i < n; i++) {
+ str = gst_caps_get_structure (caps, i);
+ features = gst_caps_get_features (caps, i);
+
+ /* If this is already expressed by the existing caps
+ * skip this structure */
+ if (i > 0 && gst_caps_is_subset_structure_full (ret, str, features))
+ continue;
+
+ str = gst_structure_copy (str);
+ /* Only remove format info for the cases when we can actually convert */
+ {
+ gst_structure_remove_fields (str, "format", "colorimetry", "chroma-site",
+ NULL);
+
+ gst_structure_set (str, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
+ "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
+
+ /* if pixel aspect ratio, make a range */
+ if (gst_structure_has_field (str, "pixel-aspect-ratio")) {
+ gst_structure_set (str, "pixel-aspect-ratio",
+ GST_TYPE_FRACTION_RANGE, 1, G_MAXINT, G_MAXINT, 1, NULL);
+ }
+ }
+ gst_caps_append_structure_full (ret, str,
+ gst_caps_features_copy (features));
+ }
+
+ return ret;
+}
+
+/**
+ * Determine pixel format.
+ *
+ * @param info : Information describing frame properties
+ * @param pix_fmt : pixel format
+ * @param isurf_count : intermediate surface count
+ */
+static gboolean
+gst_nvvconv_get_pix_fmt (GstVideoInfo * info,
+ NvBufSurfaceColorFormat * pix_fmt, gint * isurf_count)
+{
+ gboolean ret = TRUE;
+
+ if (GST_VIDEO_INFO_IS_YUV (info)) {
+ switch (GST_VIDEO_FORMAT_INFO_FORMAT (info->finfo)) {
+ case GST_VIDEO_FORMAT_I420:
+ *pix_fmt = NVBUF_COLOR_FORMAT_YUV420;
+ break;
+ case GST_VIDEO_FORMAT_UYVY:
+ *pix_fmt = NVBUF_COLOR_FORMAT_UYVY;
+ *isurf_count = 1;
+ if (info->colorimetry.range == GST_VIDEO_COLOR_RANGE_0_255) {
+ if (info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT709) {
+ *pix_fmt = NVBUF_COLOR_FORMAT_UYVY_709_ER;
+ }
+ else
+ *pix_fmt = NVBUF_COLOR_FORMAT_UYVY_ER;
+ }
+ else if (info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT709) {
+ *pix_fmt = NVBUF_COLOR_FORMAT_UYVY_709;
+ }
+ else if (info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT2020) {
+ *pix_fmt = NVBUF_COLOR_FORMAT_UYVY_2020;
+ }
+ break;
+ case GST_VIDEO_FORMAT_YUY2:
+ *pix_fmt = NVBUF_COLOR_FORMAT_YUYV;
+ *isurf_count = 1;
+ break;
+ case GST_VIDEO_FORMAT_Y42B:
+ *pix_fmt = NVBUF_COLOR_FORMAT_YUV422;
+ *isurf_count=3;
+ break;
+ case GST_VIDEO_FORMAT_YVYU:
+ *pix_fmt = NVBUF_COLOR_FORMAT_YVYU;
+ *isurf_count = 1;
+ break;
+ case GST_VIDEO_FORMAT_NV12:
+ *pix_fmt = NVBUF_COLOR_FORMAT_NV12;
+ *isurf_count = 2;
+ if (info->colorimetry.range == GST_VIDEO_COLOR_RANGE_0_255) {
+ if (info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT709) {
+ *pix_fmt = NVBUF_COLOR_FORMAT_NV12_709_ER;
+ }
+ else
+ *pix_fmt = NVBUF_COLOR_FORMAT_NV12_ER;
+ }
+ else if (info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT709) {
+ *pix_fmt = NVBUF_COLOR_FORMAT_NV12_709;
+ }
+ else if (info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT2020) {
+ *pix_fmt = NVBUF_COLOR_FORMAT_NV12_2020;
+ }
+ break;
+ case GST_VIDEO_FORMAT_NV16:
+ *pix_fmt = NVBUF_COLOR_FORMAT_NV16;
+ *isurf_count = 2;
+ break;
+ case GST_VIDEO_FORMAT_NV24:
+ *pix_fmt = NVBUF_COLOR_FORMAT_NV24;
+ *isurf_count = 2;
+ break;
+ case GST_VIDEO_FORMAT_I420_10LE:
+ case GST_VIDEO_FORMAT_P010_10LE:
+ *pix_fmt = NVBUF_COLOR_FORMAT_NV12_10LE;
+ *isurf_count = 2;
+ break;
+ case GST_VIDEO_FORMAT_I420_12LE:
+ *pix_fmt = NVBUF_COLOR_FORMAT_NV12_12LE;
+ *isurf_count = 2;
+ break;
+ case GST_VIDEO_FORMAT_Y444:
+ *pix_fmt = NVBUF_COLOR_FORMAT_YUV444;
+ *isurf_count = 3;
+ break;
+ default:
+ ret = FALSE;
+ break;
+ }
+ } else if (GST_VIDEO_INFO_IS_GRAY (info)) {
+ switch (GST_VIDEO_FORMAT_INFO_BITS (info->finfo)) {
+ case 8:
+ *pix_fmt = NVBUF_COLOR_FORMAT_GRAY8;
+ *isurf_count = 1;
+ break;
+ default:
+ ret = FALSE;
+ break;
+ }
+ } else if (GST_VIDEO_INFO_IS_RGB (info)) {
+ switch (GST_VIDEO_FORMAT_INFO_FORMAT (info->finfo)) {
+ case GST_VIDEO_FORMAT_BGRx:
+ *pix_fmt = NVBUF_COLOR_FORMAT_BGRx;
+ *isurf_count = 1;
+ break;
+ case GST_VIDEO_FORMAT_RGBA:
+ *pix_fmt = NVBUF_COLOR_FORMAT_RGBA;
+ *isurf_count = 1;
+ break;
+ default:
+ ret = FALSE;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * Initialize nvvconv instance structure members.
+ *
+ * @param filter : Gstnvvconv object instance
+ */
+static void
+gst_nvvconv_init_params (Gstnvvconv * filter)
+{
+ filter->silent = FALSE;
+ filter->to_width = 0;
+ filter->to_height = 0;
+ filter->from_width = 0;
+ filter->from_height = 0;
+ filter->tsurf_width = 0;
+ filter->tsurf_height = 0;
+
+ filter->inbuf_type = BUF_NOT_SUPPORTED;
+ filter->inbuf_memtype = BUF_MEM_SW;
+ filter->outbuf_memtype = BUF_MEM_SW;
+
+ memset(&filter->src_rect, 0, sizeof(NvBufSurfTransformRect));
+ memset(&filter->transform_params, 0, sizeof(NvBufSurfTransformParams));
+ filter->in_pix_fmt = NVBUF_COLOR_FORMAT_INVALID;
+ filter->out_pix_fmt = NVBUF_COLOR_FORMAT_INVALID;
+
+ filter->do_scaling = FALSE;
+ filter->need_intersurf = FALSE;
+ filter->isurf_flag = FALSE;
+ filter->nvfilterpool = FALSE;
+
+ filter->insurf_count = 0;
+ filter->isurf_count = 0;
+ filter->tsurf_count = 0;
+ filter->ibuf_count = 0;
+
+ filter->silent = FALSE;
+ filter->no_dimension = FALSE;
+ filter->do_flip = FALSE;
+ filter->flip_method = GST_VIDEO_NVFLIP_METHOD_IDENTITY;
+ filter->interpolation_method = GST_INTERPOLATION_NEAREST;
+ filter->negotiated = FALSE;
+ filter->num_output_buf = NVFILTER_MAX_BUF;
+ /* TODO: change default value to TRUE once BL pipelines are supported for OpenRM */
+ filter->enable_blocklinear_output = is_nvgpu;
+
+ filter->do_cropping = FALSE;
+ filter->crop_right = 0;
+ filter->crop_left = 0;
+ filter->crop_top = 0;
+ filter->crop_bottom = 0;
+
+ filter->compute_hw = NvBufSurfTransformCompute_Default;
+ filter->gpu_id = 0;
+ filter->nvbuf_mem_type = NVBUF_MEM_DEFAULT;
+
+ filter->sinkcaps =
+ gst_static_pad_template_get_caps (&gst_nvvconv_sink_template);
+ filter->srccaps =
+ gst_static_pad_template_get_caps (&gst_nvvconv_src_template);
+
+ g_mutex_init (&filter->flow_lock);
+}
+
+/**
+ * clear the chroma
+ *
+ * @param filter : Gstnvvconv object instance
+ * @param dmabuf_fd : process buffer fd
+ */
+static gboolean
+gst_nvvconv_do_clearchroma (Gstnvvconv * filter, NvBufSurface *surface)
+{
+ gint ret = 0;
+ guint i, size;
+
+ for (i = 1; i < filter->tsurf_count; i++) {
+ ret = NvBufSurfaceMap (surface, 0, i, NVBUF_MAP_READ_WRITE);
+ if (ret != 0) {
+ g_print ("%s: NvBufSurfaceMap Failed \n", __func__);
+ return FALSE;
+ }
+
+ ret = NvBufSurfaceSyncForCpu (surface, 0, i);
+ if (ret != 0) {
+ g_print ("%s: NvBufSurfaceSyncForCpu Failed \n", __func__);
+ return FALSE;
+ }
+
+ size = surface->surfaceList[0].planeParams.height[i] * surface->surfaceList[0].planeParams.pitch[i];
+ memset (surface->surfaceList[0].mappedAddr.addr[i], 0x80, size);
+
+ ret = NvBufSurfaceSyncForDevice (surface, 0, i);
+ if (ret != 0) {
+ GST_ERROR ("%s: NvBufSurfaceSyncForDevice Failed \n", __func__);
+ return FALSE;
+ }
+
+ ret = NvBufSurfaceUnMap (surface, 0, i);
+ if (ret != 0) {
+ g_print ("%s: NvBufSurfaceUnMap Failed \n", __func__);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/* GObject vmethod implementations */
+
+/**
+ * initialize the nvvconv's class.
+ *
+ * @param klass : Gstnvvconv objectclass
+ */
+static void
+gst_nvvconv_class_init (GstnvvconvClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseTransformClass *gstbasetransform_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ gstbasetransform_class = (GstBaseTransformClass *) klass;
+
+ gparent_class = g_type_class_peek_parent (gstbasetransform_class);
+
+ gobject_class->set_property = gst_nvvconv_set_property;
+ gobject_class->get_property = gst_nvvconv_get_property;
+ gobject_class->finalize = gst_nvvconv_finalize;
+
+ gstelement_class->change_state = gst_nvvconv_change_state;
+
+ gstbasetransform_class->set_caps = GST_DEBUG_FUNCPTR (gst_nvvconv_set_caps);
+ gstbasetransform_class->transform_caps =
+ GST_DEBUG_FUNCPTR (gst_nvvconv_transform_caps);
+ gstbasetransform_class->accept_caps =
+ GST_DEBUG_FUNCPTR (gst_nvvconv_accept_caps);
+ gstbasetransform_class->transform_size =
+ GST_DEBUG_FUNCPTR (gst_nvvconv_transform_size);
+ gstbasetransform_class->get_unit_size =
+ GST_DEBUG_FUNCPTR (gst_nvvconv_get_unit_size);
+ gstbasetransform_class->transform = GST_DEBUG_FUNCPTR (gst_nvvconv_transform);
+ gstbasetransform_class->start = GST_DEBUG_FUNCPTR (gst_nvvconv_start);
+ gstbasetransform_class->stop = GST_DEBUG_FUNCPTR (gst_nvvconv_stop);
+ gstbasetransform_class->fixate_caps =
+ GST_DEBUG_FUNCPTR (gst_nvvconv_fixate_caps);
+ gstbasetransform_class->decide_allocation =
+ GST_DEBUG_FUNCPTR (gst_nvvconv_decide_allocation);
+
+ gstbasetransform_class->passthrough_on_same_caps = TRUE;
+
+ g_object_class_install_property (gobject_class, PROP_SILENT,
+ g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?",
+ FALSE, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_FLIP_METHOD,
+ g_param_spec_enum ("flip-method", "Flip-Method", "video flip methods",
+ GST_TYPE_VIDEO_NVFLIP_METHOD, PROP_FLIP_METHOD_DEFAULT,
+ GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_NUM_OUT_BUFS,
+ g_param_spec_uint ("output-buffers", "Output-Buffers",
+ "number of output buffers",
+ 1, G_MAXUINT, NVFILTER_MAX_BUF,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_PLAYING));
+
+ g_object_class_install_property (gobject_class, PROP_INTERPOLATION_METHOD,
+ g_param_spec_enum ("interpolation-method", "Interpolation-method", "Set interpolation methods",
+ GST_TYPE_INTERPOLATION_METHOD, GST_INTERPOLATION_NEAREST,
+ GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_LEFT,
+ g_param_spec_int ("left", "left", "Pixels to crop at left",
+ 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_RIGHT,
+ g_param_spec_int ("right", "right", "Pixels to crop at right",
+ 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_TOP,
+ g_param_spec_int ("top", "top", "Pixels to crop at top",
+ 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_BOTTOM,
+ g_param_spec_int ("bottom", "bottom", "Pixels to crop at bottom",
+ 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /* TODO: change default value to TRUE once BL pipelines are supported for OpenRM */
+ g_object_class_install_property (gobject_class, PROP_ENABLE_BLOCKLINEAR_OUTPUT,
+ g_param_spec_boolean ("bl-output", " Enable BlockLinear output",
+ "Blocklinear output, applicable only for memory:NVMM NV12 format output buffer when compute hw is VIC",
+ is_nvgpu, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_COMPUTE_HW,
+ g_param_spec_enum ("compute-hw", "compute-hw", "Compute Scaling HW",
+ GST_TYPE_COMPUTE_HW, NvBufSurfTransformCompute_Default,
+ (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_CONTROLLABLE | G_PARAM_CONSTRUCT)));
+
+ g_object_class_install_property (gobject_class, PROP_GPU_DEVICE_ID,
+ g_param_spec_uint ("gpu-id", "Set GPU Device ID for operation",
+ "Set GPU Device ID for operation", 0, G_MAXUINT, 0,
+ (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY)));
+
+ g_object_class_install_property (gobject_class, PROP_NVBUF_MEMORY_TYPE,
+ g_param_spec_enum ("nvbuf-memory-type", "Type of NvBufSurface memory allocated",
+ "Type of NvBufSurface Memory to be allocated for output buffers when compute hw is GPU and memory is NVMM",
+ GST_TYPE_NVBUF_MEMORY_TYPE, NVBUF_MEM_DEFAULT,
+ (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_READY)));
+
+ gst_element_class_set_details_simple (gstelement_class,
+ "NvVidConv Plugin",
+ "Filter/Converter/Video/Scaler",
+ "Converts video from one colorspace to another & Resizes",
+ "amit pandya ");
+
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&gst_nvvconv_src_template));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&gst_nvvconv_sink_template));
+}
+
+/**
+ * initialize nvvconv instance structure.
+ *
+ * @param filter : Gstnvvconv object instance
+ */
+static void
+gst_nvvconv_init (Gstnvvconv * filter)
+{
+ gst_nvvconv_init_params (filter);
+}
+
+static void
+get_NvBufferTransform(Gstnvvconv * filter)
+{
+ switch (filter->flip_method)
+ {
+ case GST_VIDEO_NVFLIP_METHOD_IDENTITY:
+ filter->transform_params.transform_flip = NvBufSurfTransform_None;
+ break;
+ case GST_VIDEO_NVFLIP_METHOD_90L:
+ filter->transform_params.transform_flip = NvBufSurfTransform_Rotate90;
+ break;
+ case GST_VIDEO_NVFLIP_METHOD_180:
+ filter->transform_params.transform_flip = NvBufSurfTransform_Rotate180;
+ break;
+ case GST_VIDEO_NVFLIP_METHOD_90R:
+ filter->transform_params.transform_flip = NvBufSurfTransform_Rotate270;
+ break;
+ case GST_VIDEO_NVFLIP_METHOD_HORIZ:
+ filter->transform_params.transform_flip = NvBufSurfTransform_FlipX;
+ break;
+ case GST_VIDEO_NVFLIP_METHOD_VERT:
+ filter->transform_params.transform_flip = NvBufSurfTransform_FlipY;
+ break;
+ case GST_VIDEO_NVFLIP_METHOD_TRANS:
+ filter->transform_params.transform_flip = NvBufSurfTransform_Transpose;
+ break;
+ case GST_VIDEO_NVFLIP_METHOD_INVTRANS:
+ filter->transform_params.transform_flip = NvBufSurfTransform_InvTranspose;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+get_NvBufferTransform_filter(Gstnvvconv * filter)
+{
+ switch(filter->interpolation_method)
+ {
+ case GST_INTERPOLATION_NEAREST:
+ filter->transform_params.transform_filter = NvBufSurfTransformInter_Nearest;
+ break;
+ case GST_INTERPOLATION_BILINEAR:
+ filter->transform_params.transform_filter = NvBufSurfTransformInter_Bilinear;
+ break;
+ case GST_INTERPOLATION_5_TAP:
+ filter->transform_params.transform_filter = NvBufSurfTransformInter_Algo1;
+ break;
+ case GST_INTERPOLATION_10_TAP:
+ filter->transform_params.transform_filter = NvBufSurfTransformInter_Algo2;
+ break;
+ case GST_INTERPOLATION_SMART:
+ filter->transform_params.transform_filter = NvBufSurfTransformInter_Algo3;
+ break;
+ case GST_INTERPOLATION_NICEST:
+ filter->transform_params.transform_filter = NvBufSurfTransformInter_Algo4;
+ break;
+ default:
+ filter->transform_params.transform_filter = NvBufSurfTransformInter_Algo3;
+ break;
+ }
+}
+
+/**
+ * initialize nvvconv instance structure.
+ *
+ * @param filter : Gstnvvconv object instance
+ */
+static void
+gst_nvvconv_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ Gstnvvconv *filter = GST_NVVCONV (object);
+
+ switch (prop_id) {
+ case PROP_SILENT:
+ filter->silent = g_value_get_boolean (value);
+ break;
+ case PROP_FLIP_METHOD:
+ filter->transform_params.transform_flag |= NVBUFSURF_TRANSFORM_FLIP;
+ filter->do_flip = TRUE;
+ filter->flip_method = g_value_get_enum (value);
+ get_NvBufferTransform (filter);
+ gst_base_transform_reconfigure_src (GST_BASE_TRANSFORM(filter));
+ break;
+ case PROP_NUM_OUT_BUFS:
+ filter->num_output_buf = g_value_get_uint (value);
+ break;
+ case PROP_INTERPOLATION_METHOD:
+ filter->transform_params.transform_flag |= NVBUFSURF_TRANSFORM_FILTER;
+ filter->interpolation_method = g_value_get_enum (value);
+ get_NvBufferTransform_filter (filter);
+ break;
+ case PROP_LEFT:
+ filter->transform_params.transform_flag |= NVBUFSURF_TRANSFORM_CROP_SRC;
+ filter->do_cropping = TRUE;
+ filter->crop_left = g_value_get_int (value);
+ filter->src_rect.left = filter->crop_left;
+ filter->transform_params.src_rect = &filter->src_rect;
+ break;
+ case PROP_RIGHT:
+ filter->transform_params.transform_flag |= NVBUFSURF_TRANSFORM_CROP_SRC;
+ filter->do_cropping = TRUE;
+ filter->crop_right = g_value_get_int (value);
+ filter->src_rect.width = (filter->crop_right - filter->crop_left);
+ filter->transform_params.src_rect = &filter->src_rect;
+ break;
+ case PROP_TOP:
+ filter->transform_params.transform_flag |= NVBUFSURF_TRANSFORM_CROP_SRC;
+ filter->do_cropping = TRUE;
+ filter->crop_top = g_value_get_int (value);
+ filter->src_rect.top = filter->crop_top;
+ filter->transform_params.src_rect = &filter->src_rect;
+ break;
+ case PROP_BOTTOM:
+ filter->transform_params.transform_flag |= NVBUFSURF_TRANSFORM_CROP_SRC;
+ filter->do_cropping = TRUE;
+ filter->crop_bottom = g_value_get_int (value);
+ filter->src_rect.height = (filter->crop_bottom - filter->crop_top);
+ filter->transform_params.src_rect = &filter->src_rect;
+ break;
+ case PROP_ENABLE_BLOCKLINEAR_OUTPUT:
+ filter->enable_blocklinear_output = g_value_get_boolean (value);
+ break;
+ case PROP_COMPUTE_HW:
+ filter->compute_hw = g_value_get_enum (value);
+ break;
+ case PROP_GPU_DEVICE_ID:
+ filter->gpu_id = g_value_get_uint (value);
+ break;
+ case PROP_NVBUF_MEMORY_TYPE:
+ filter->nvbuf_mem_type = g_value_get_enum (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/**
+ * initialize nvvconv instance structure.
+ *
+ * @param filter : Gstnvvconv object instance
+ */
+static void
+gst_nvvconv_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ Gstnvvconv *filter = GST_NVVCONV (object);
+
+ switch (prop_id) {
+ case PROP_SILENT:
+ g_value_set_boolean (value, filter->silent);
+ break;
+ case PROP_FLIP_METHOD:
+ g_value_set_enum (value, filter->flip_method);
+ break;
+ case PROP_NUM_OUT_BUFS:
+ g_value_set_uint (value, filter->num_output_buf);
+ break;
+ case PROP_INTERPOLATION_METHOD:
+ g_value_set_enum (value, filter->interpolation_method);
+ break;
+ case PROP_LEFT:
+ g_value_set_int (value, filter->crop_left);
+ break;
+ case PROP_RIGHT:
+ g_value_set_int (value, filter->crop_right);
+ break;
+ case PROP_TOP:
+ g_value_set_int (value, filter->crop_top);
+ break;
+ case PROP_BOTTOM:
+ g_value_set_int (value, filter->crop_bottom);
+ break;
+ case PROP_ENABLE_BLOCKLINEAR_OUTPUT:
+ g_value_set_boolean (value, filter->enable_blocklinear_output);
+ break;
+ case PROP_COMPUTE_HW:
+ g_value_set_enum (value, filter->compute_hw);
+ break;
+ case PROP_GPU_DEVICE_ID:
+ g_value_set_uint (value, filter->gpu_id);
+ break;
+ case PROP_NVBUF_MEMORY_TYPE:
+ g_value_set_enum (value, filter->nvbuf_mem_type);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/**
+ * Free all allocated resources(Rmsurface).
+ *
+ * @param filter : Gstnvvconv object instance
+ */
+static void
+gst_nvvconv_free_buf (Gstnvvconv * filter)
+{
+ gint ret;
+
+ if (filter->input_interbuf.isurface) {
+ ret = NvBufSurfaceDestroy (filter->input_interbuf.isurface);
+ if (ret != 0) {
+ GST_ERROR ("%s: intermediate NvBufferDestroy Failed \n", __func__);
+ }
+ filter->input_interbuf.isurface = NULL;
+ filter->ibuf_count--;
+ }
+ if (filter->output_interbuf.isurface) {
+ ret = NvBufSurfaceDestroy (filter->output_interbuf.isurface);
+ if (ret != 0) {
+ GST_ERROR ("%s: intermediate NvBufferDestroy Failed \n", __func__);
+ }
+ filter->output_interbuf.isurface = NULL;
+ filter->ibuf_count--;
+ }
+ filter->isurf_count = 0;
+ filter->ibuf_count = 0;
+}
+
+/**
+ * nvvidconv element state change function.
+ *
+ * @param element : Gstnvvconv element instance
+ * @param transition : state transition
+ */
+static GstStateChangeReturn
+gst_nvvconv_change_state (GstElement * element, GstStateChange transition)
+{
+ GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
+ Gstnvvconv *space;
+
+ space = GST_NVVCONV (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:{
+ }
+ break;
+ case GST_STATE_CHANGE_READY_TO_PAUSED:{
+ }
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{
+ }
+ break;
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:{
+ }
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:{
+ }
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:{
+ }
+ break;
+ case GST_STATE_CHANGE_NULL_TO_NULL:{
+ }
+ break;
+ case GST_STATE_CHANGE_READY_TO_READY:{
+ }
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_PAUSED:{
+ }
+ break;
+ case GST_STATE_CHANGE_PLAYING_TO_PLAYING:{
+ }
+ break;
+ }
+
+ GST_ELEMENT_CLASS (gparent_class)->change_state (element, transition);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:{
+ }
+ break;
+ case GST_STATE_CHANGE_READY_TO_PAUSED:{
+ }
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{
+ }
+ break;
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:{
+ }
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:{
+ gst_nvvconv_free_buf (space);
+ }
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:{
+ }
+ break;
+ case GST_STATE_CHANGE_NULL_TO_NULL:{
+ }
+ break;
+ case GST_STATE_CHANGE_READY_TO_READY:{
+ }
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_PAUSED:{
+ }
+ break;
+ case GST_STATE_CHANGE_PLAYING_TO_PLAYING:{
+ }
+ break;
+ }
+
+ return result;
+}
+
+/**
+ * nvvidconv element finalize function.
+ *
+ * @param object : element object instance
+ */
+static void
+gst_nvvconv_finalize (GObject * object)
+{
+ Gstnvvconv *filter;
+
+ filter = GST_NVVCONV(object);
+
+ if (filter->sinkcaps) {
+ gst_caps_unref (filter->sinkcaps);
+ filter->sinkcaps = NULL;
+ }
+
+ if (filter->srccaps) {
+ gst_caps_unref (filter->srccaps);
+ filter->srccaps = NULL;
+ }
+
+ g_mutex_clear (&filter->flow_lock);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/* GstBaseTransform vmethod implementations */
+
+/**
+ * notified of the actual caps set.
+ *
+ * @param btrans : basetransform object instance
+ * @param incaps : input capabilities
+ * @param outcaps : output capabilities
+ */
+static gboolean
+gst_nvvconv_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
+ GstCaps * outcaps)
+{
+ gboolean ret = TRUE;
+ Gstnvvconv *space;
+ gint from_dar_n = 0, from_dar_d = 0, to_dar_n = 0, to_dar_d = 0;
+ GstVideoInfo in_info = {0}, out_info = {0};
+ GstBufferPool *newpool, *oldpool;
+ GstStructure *config = NULL;
+ gint min, surf_count = 0;
+ GstCapsFeatures *ift = NULL;
+ GstCapsFeatures *oft = NULL;
+ int existing_from_width = 0;
+ int existing_from_height = 0;
+
+ space = GST_NVVCONV (btrans);
+
+ /* input caps */
+ if (!gst_video_info_from_caps (&in_info, incaps))
+ goto invalid_caps;
+
+ /* output caps */
+ if (!gst_video_info_from_caps (&out_info, outcaps))
+ goto invalid_caps;
+
+ space->in_info = in_info;
+ space->out_info = out_info;
+
+ existing_from_width = space->from_width;
+ existing_from_height = space->from_height;
+ space->from_width = GST_VIDEO_INFO_WIDTH (&in_info);
+ space->from_height = GST_VIDEO_INFO_HEIGHT (&in_info);
+ if (existing_from_width != space->from_width || existing_from_height != space->from_height) {
+ space->resolution_changed = TRUE;
+ GST_DEBUG_OBJECT (space, "Resolution changed: %d\n", space->resolution_changed);
+ }
+
+ space->to_width = GST_VIDEO_INFO_WIDTH (&out_info);
+ space->to_height = GST_VIDEO_INFO_HEIGHT (&out_info);
+
+ if ((space->from_width != space->to_width)
+ || (space->from_height != space->to_height))
+ space->do_scaling = TRUE;
+
+ /* get input pixel format */
+ ret =
+ gst_nvvconv_get_pix_fmt (&in_info, &space->in_pix_fmt,
+ &surf_count);
+ if (ret != TRUE)
+ goto invalid_pix_fmt;
+
+ if (space->compute_hw == NvBufSurfTransformCompute_GPU) {
+ if ((space->in_pix_fmt == NVBUF_COLOR_FORMAT_YUV422) ||
+ (space->in_pix_fmt == NVBUF_COLOR_FORMAT_NV24) ||
+ (space->in_pix_fmt == NVBUF_COLOR_FORMAT_NV16) ||
+ (space->in_pix_fmt == NVBUF_COLOR_FORMAT_UYVY) ||
+ (space->in_pix_fmt == NVBUF_COLOR_FORMAT_YVYU) ||
+ (space->in_pix_fmt == NVBUF_COLOR_FORMAT_YUYV)) {
+ g_print ("Transform not supported using GPU for provided input format\n");
+ goto invalid_pix_fmt;
+ }
+ }
+
+ /* get output pixel format */
+ ret =
+ gst_nvvconv_get_pix_fmt (&out_info, &space->out_pix_fmt,
+ &surf_count);
+ if (ret != TRUE)
+ goto invalid_pix_fmt;
+
+ if (space->compute_hw == NvBufSurfTransformCompute_GPU) {
+ if ((space->out_pix_fmt == NVBUF_COLOR_FORMAT_YUV422) ||
+ (space->out_pix_fmt == NVBUF_COLOR_FORMAT_NV24) ||
+ (space->out_pix_fmt == NVBUF_COLOR_FORMAT_NV16) ||
+ (space->out_pix_fmt == NVBUF_COLOR_FORMAT_UYVY) ||
+ (space->out_pix_fmt == NVBUF_COLOR_FORMAT_YVYU) ||
+ (space->out_pix_fmt == NVBUF_COLOR_FORMAT_YUYV)) {
+ g_print ("Transform not supported using GPU for provided output format\n");
+ goto invalid_pix_fmt;
+ }
+ }
+
+ ift = gst_caps_get_features (incaps, 0);
+ if (gst_caps_features_contains (ift, GST_CAPS_FEATURE_MEMORY_NVMM))
+ space->inbuf_memtype = BUF_MEM_HW;
+
+ oft = gst_caps_get_features (outcaps, 0);
+ if (gst_caps_features_contains (oft, GST_CAPS_FEATURE_MEMORY_NVMM))
+ space->outbuf_memtype = BUF_MEM_HW;
+
+ if (gst_caps_features_is_equal (ift, oft) &&
+ (space->in_pix_fmt == space->out_pix_fmt) &&
+ (!space->do_scaling) &&
+ (!space->do_cropping) &&
+ (!space->flip_method)) {
+ /* We are not processing input buffer. Initializations/allocations in this
+ function can be skipped */
+ gst_base_transform_set_passthrough (btrans, TRUE);
+ return TRUE;
+ }
+
+ switch (space->in_pix_fmt) {
+ case NVBUF_COLOR_FORMAT_YUV420:
+ case NVBUF_COLOR_FORMAT_YUV422:
+ case NVBUF_COLOR_FORMAT_YUV444:
+ space->inbuf_type = BUF_TYPE_YUV;
+ space->insurf_count = 3;
+ break;
+ case NVBUF_COLOR_FORMAT_NV12:
+ case NVBUF_COLOR_FORMAT_NV16:
+ case NVBUF_COLOR_FORMAT_NV24:
+ case NVBUF_COLOR_FORMAT_NV12_10LE:
+ case NVBUF_COLOR_FORMAT_NV12_12LE:
+ case NVBUF_COLOR_FORMAT_NV12_709:
+ case NVBUF_COLOR_FORMAT_NV12_2020:
+ case NVBUF_COLOR_FORMAT_NV12_709_ER:
+ case NVBUF_COLOR_FORMAT_NV12_ER:
+ space->inbuf_type = BUF_TYPE_YUV;
+ space->insurf_count = 2;
+ break;
+ case NVBUF_COLOR_FORMAT_UYVY:
+ case NVBUF_COLOR_FORMAT_YUYV:
+ case NVBUF_COLOR_FORMAT_YVYU:
+ case NVBUF_COLOR_FORMAT_UYVY_709:
+ case NVBUF_COLOR_FORMAT_UYVY_2020:
+ case NVBUF_COLOR_FORMAT_UYVY_709_ER:
+ case NVBUF_COLOR_FORMAT_UYVY_ER:
+ space->inbuf_type = BUF_TYPE_YUV;
+ space->insurf_count = 1;
+ break;
+ case NVBUF_COLOR_FORMAT_BGRx:
+ case NVBUF_COLOR_FORMAT_RGBA:
+ space->inbuf_type = BUF_TYPE_RGB;
+ space->insurf_count = 1;
+ break;
+ case NVBUF_COLOR_FORMAT_GRAY8:
+ space->inbuf_type = BUF_TYPE_GRAY;
+ space->insurf_count = 1;
+ break;
+ default:
+ goto not_supported_inbuf;
+ break;
+ }
+
+ min = space->num_output_buf;
+
+ space->tsurf_width = space->to_width;
+ space->tsurf_height = space->to_height;
+
+ switch (space->out_pix_fmt) {
+ case NVBUF_COLOR_FORMAT_YUV420:
+ case NVBUF_COLOR_FORMAT_YUV422:
+ case NVBUF_COLOR_FORMAT_YUV444:
+ space->tsurf_count = 3;
+ break;
+ case NVBUF_COLOR_FORMAT_NV12:
+ case NVBUF_COLOR_FORMAT_NV16:
+ case NVBUF_COLOR_FORMAT_NV24:
+ case NVBUF_COLOR_FORMAT_NV12_10LE:
+ case NVBUF_COLOR_FORMAT_NV12_709:
+ case NVBUF_COLOR_FORMAT_NV12_2020:
+ case NVBUF_COLOR_FORMAT_NV12_709_ER:
+ case NVBUF_COLOR_FORMAT_NV12_ER:
+ space->tsurf_count = 2;
+ break;
+ case NVBUF_COLOR_FORMAT_UYVY:
+ case NVBUF_COLOR_FORMAT_YUYV:
+ case NVBUF_COLOR_FORMAT_YVYU:
+ case NVBUF_COLOR_FORMAT_UYVY_709:
+ case NVBUF_COLOR_FORMAT_UYVY_2020:
+ case NVBUF_COLOR_FORMAT_UYVY_709_ER:
+ case NVBUF_COLOR_FORMAT_UYVY_ER:
+ space->tsurf_count = 1;
+ break;
+ case NVBUF_COLOR_FORMAT_BGRx:
+ case NVBUF_COLOR_FORMAT_RGBA:
+ case NVBUF_COLOR_FORMAT_GRAY8:
+ space->tsurf_count = 1;
+ break;
+ default:
+ goto not_supported_outbuf;
+ break;
+ }
+
+ if ((space->in_pix_fmt != space->out_pix_fmt) ||
+ (space->do_scaling) ||
+ (space->flip_method) ||
+ (space->do_cropping)) {
+ space->need_intersurf = TRUE;
+ space->isurf_flag = TRUE;
+ }
+
+ if (!gst_util_fraction_multiply (in_info.width,
+ in_info.height, in_info.par_n, in_info.par_d, &from_dar_n,
+ &from_dar_d)) {
+ from_dar_n = from_dar_d = -1;
+ }
+
+ if (!gst_util_fraction_multiply (out_info.width,
+ out_info.height, out_info.par_n, out_info.par_d, &to_dar_n,
+ &to_dar_d)) {
+ to_dar_n = to_dar_d = -1;
+ }
+
+ if (to_dar_n != from_dar_n || to_dar_d != from_dar_d) {
+ GST_WARNING_OBJECT (space, "Cannot keep DAR");
+ }
+
+ /* check for outcaps feature */
+ ift = gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_NVMM, NULL);
+ if (gst_caps_features_is_equal (gst_caps_get_features (outcaps, 0), ift)) {
+ space->nvfilterpool = TRUE;
+ }
+ gst_caps_features_free (ift);
+
+ if (space->nvfilterpool) {
+ g_mutex_lock (&space->flow_lock);
+ newpool = gst_nv_filter_buffer_pool_new (GST_ELEMENT_CAST (space));
+
+ config = gst_buffer_pool_get_config (newpool);
+ gst_buffer_pool_config_set_params (config, outcaps, sizeof (NvBufSurface), min, min);
+ gst_buffer_pool_config_set_allocator (config,
+ ((GstNvFilterBufferPool *) newpool)->allocator, NULL);
+ if (!gst_buffer_pool_set_config (newpool, config))
+ goto config_failed;
+
+ oldpool = space->pool;
+ space->pool = newpool;
+
+ g_mutex_unlock (&space->flow_lock);
+
+ /* unref the old nvfilter bufferpool */
+ if (oldpool) {
+ gst_object_unref (oldpool);
+ }
+ }
+
+ gst_base_transform_set_passthrough (btrans, FALSE);
+
+ GST_DEBUG_OBJECT (space, "from=%dx%d (par=%d/%d dar=%d/%d), size %"
+ G_GSIZE_FORMAT " -> to=%dx%d (par=%d/%d dar=%d/%d), "
+ "size %" G_GSIZE_FORMAT,
+ in_info.width, in_info.height, in_info.par_n, in_info.par_d,
+ from_dar_n, from_dar_d, in_info.size, out_info.width,
+ out_info.height, out_info.par_n, out_info.par_d, to_dar_n, to_dar_d,
+ out_info.size);
+
+ space->negotiated = ret;
+
+ return ret;
+
+ /* ERRORS */
+config_failed:
+ {
+ GST_ERROR ("failed to set config on bufferpool");
+ g_mutex_unlock (&space->flow_lock);
+ return FALSE;
+ }
+not_supported_inbuf:
+ {
+ GST_ERROR ("input buffer type not supported");
+ return FALSE;
+ }
+not_supported_outbuf:
+ {
+ GST_ERROR ("output buffer type not supported");
+ return FALSE;
+ }
+invalid_pix_fmt:
+ {
+ GST_ERROR ("could not configure for input/output format");
+ space->in_pix_fmt = NVBUF_COLOR_FORMAT_INVALID;
+ space->out_pix_fmt = NVBUF_COLOR_FORMAT_INVALID;
+ return FALSE;
+ }
+invalid_caps:
+ {
+ GST_ERROR ("invalid caps");
+ space->negotiated = FALSE;
+ return FALSE;
+ }
+}
+
+/**
+ * Open external resources.
+ *
+ * @param btrans : basetransform object instance
+ */
+static gboolean
+gst_nvvconv_start (GstBaseTransform * btrans)
+{
+ Gstnvvconv *space;
+
+ space = GST_NVVCONV (btrans);
+
+ space->session_created = 0;
+
+ return TRUE;
+}
+
+/**
+ * Close external resources.
+ *
+ * @param btrans : basetransform object instance
+ */
+static gboolean
+gst_nvvconv_stop (GstBaseTransform * btrans)
+{
+ Gstnvvconv *space;
+
+ space = GST_NVVCONV (btrans);
+ if (space->pool) {
+ g_mutex_lock (&space->flow_lock);
+ gst_object_unref (space->pool);
+ space->pool = NULL;
+ g_mutex_unlock (&space->flow_lock);
+ }
+
+ if (space->session_created == 1) {
+ if (space->config_params.cuda_stream)
+ cudaStreamDestroy(space->config_params.cuda_stream);
+ space->config_params.cuda_stream = 0;
+ space->session_created = 0;
+ }
+
+ return TRUE;
+}
+
+/**
+ * calculate the size in bytes of a buffer on the other pad
+ * with the given other caps, output size only depends on the caps,
+ * not on the input caps.
+ *
+ * @param btrans : basetransform object instance
+ * @param direction : pad direction
+ * @param caps : input caps
+ * @param size : input buffer size
+ * @param othercaps : other caps
+ * @param othersize : otherpad buffer size
+ */
+static gboolean
+gst_nvvconv_transform_size (GstBaseTransform * btrans,
+ GstPadDirection direction, GstCaps * caps, gsize size,
+ GstCaps * othercaps, gsize * othersize)
+{
+ gboolean ret = TRUE;
+ GstVideoInfo vinfo = {0};
+
+ /* size of input buffer cannot be zero */
+ g_assert (size);
+
+ ret = gst_video_info_from_caps (&vinfo, othercaps);
+ if (ret) {
+ *othersize = vinfo.size;
+ }
+
+ GST_DEBUG_OBJECT (btrans, "Othersize %" G_GSIZE_FORMAT " bytes"
+ "for othercaps %" GST_PTR_FORMAT, *othersize, othercaps);
+
+ return ret;
+}
+
+static gboolean
+subsampling_unchanged (GstVideoInfo * in_info, GstVideoInfo * out_info)
+{
+ const GstVideoFormatInfo *in_format, *out_format;
+
+ if (GST_VIDEO_INFO_N_COMPONENTS (in_info) !=
+ GST_VIDEO_INFO_N_COMPONENTS (out_info))
+ return FALSE;
+
+ in_format = in_info->finfo;
+ out_format = out_info->finfo;
+
+ for (guint i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (in_info); i++) {
+ if (GST_VIDEO_FORMAT_INFO_W_SUB (in_format,
+ i) != GST_VIDEO_FORMAT_INFO_W_SUB (out_format, i))
+ return FALSE;
+ if (GST_VIDEO_FORMAT_INFO_H_SUB (in_format,
+ i) != GST_VIDEO_FORMAT_INFO_H_SUB (out_format, i))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+transfer_colorimetry_from_input (Gstnvvconv * trans, GstCaps * caps,
+ GstCaps * othercaps) {
+ GstStructure *in_struct = gst_caps_get_structure (caps, 0);
+ GstStructure *out_struct = gst_caps_get_structure (othercaps, 0);
+ const GValue *in_colorimetry =
+ gst_structure_get_value (in_struct, "colorimetry");
+
+ GstVideoInfo in_info, out_info;
+
+ if (!gst_video_info_from_caps (&in_info, caps)) {
+ GST_WARNING_OBJECT (trans,
+ "Failed to convert sink pad caps to video info");
+ return;
+ }
+
+ if (!gst_video_info_from_caps (&out_info, othercaps)) {
+ GST_WARNING_OBJECT (trans,
+ "Failed to convert src pad caps to video info");
+ return;
+ }
+
+ if (in_colorimetry != NULL) {
+ if ((GST_VIDEO_INFO_IS_YUV (&out_info)
+ && GST_VIDEO_INFO_IS_YUV (&in_info))
+ || (GST_VIDEO_INFO_IS_RGB (&out_info)
+ && GST_VIDEO_INFO_IS_RGB (&in_info))
+ || (GST_VIDEO_INFO_IS_GRAY (&out_info)
+ && GST_VIDEO_INFO_IS_GRAY (&in_info))) {
+ /* Can transfer the colorimetry intact from the input if it has it */
+ gst_structure_set_value (out_struct, "colorimetry", in_colorimetry);
+ } else {
+ gchar *colorimetry_str;
+
+ /* Changing between YUV/RGB - forward primaries and transfer function, but use
+ * default range and matrix.
+ * the primaries is used for conversion between RGB and XYZ (CIE 1931 coordinate).
+ * the transfer function could be another reference (e.g., HDR)
+ */
+ out_info.colorimetry.primaries = in_info.colorimetry.primaries;
+ out_info.colorimetry.transfer = in_info.colorimetry.transfer;
+
+ colorimetry_str =
+ gst_video_colorimetry_to_string (&out_info.colorimetry);
+ gst_caps_set_simple (othercaps, "colorimetry", G_TYPE_STRING,
+ colorimetry_str, NULL);
+ g_free (colorimetry_str);
+ }
+
+ }
+
+ /* Only YUV output needs chroma-site. If the input was also YUV and had the same chroma
+ * subsampling, transfer the siting. If the sub-sampling is changing, then the planes get
+ * scaled anyway so there's no real reason to prefer the input siting. */
+ if (GST_VIDEO_INFO_IS_YUV (&out_info)) {
+ if (GST_VIDEO_INFO_IS_YUV (&in_info)) {
+ const GValue *in_chroma_site =
+ gst_structure_get_value (in_struct, "chroma-site");
+ if (in_chroma_site != NULL
+ && subsampling_unchanged (&in_info, &out_info))
+ gst_structure_set_value (out_struct, "chroma-site", in_chroma_site);
+ }
+ }
+}
+/**
+ * Get the size in bytes of one unit for the given caps.
+ *
+ * @param btrans : basetransform object instance
+ * @param caps : given caps
+ * @param size : size of one unit
+ */
+static gboolean
+gst_nvvconv_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
+ gsize * size)
+{
+ gboolean ret = TRUE;
+ GstVideoInfo vinfo = {0};
+
+ if (!gst_video_info_from_caps (&vinfo, caps)) {
+ GST_WARNING_OBJECT (btrans, "Parsing failed for caps %" GST_PTR_FORMAT, caps);
+ return FALSE;
+ }
+
+ *size = vinfo.size;
+
+ GST_DEBUG_OBJECT (btrans, "size %" G_GSIZE_FORMAT " bytes"
+ "for caps %" GST_PTR_FORMAT, *size, caps);
+
+ return ret;
+}
+
+/**
+ * Given the pad in direction and the given caps,
+ * fixate the caps on the other pad.
+ *
+ * @param btrans : basetransform object instance
+ * @param direction : pad direction
+ * @param caps : given caps
+ * @param othercaps : other caps
+ */
+static GstCaps *
+gst_nvvconv_fixate_caps (GstBaseTransform * btrans,
+ GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
+{
+ Gstnvvconv *space;
+ gint tt_width = 0, tt_height = 0;
+ GstStructure *in_struct, *out_struct;
+ const GValue *from_pix_ar, *to_pix_ar;
+ const gchar *from_fmt = NULL, *to_fmt = NULL;
+ const gchar *from_interlace_mode = NULL;
+ const gchar *to_interlace_mode = NULL;
+ GValue from_par = { 0, }, to_par = {
+ 0,};
+ gint n, i, index = 0;
+ GstCapsFeatures *features = NULL;
+ gboolean have_nvfeature = FALSE;
+
+ space = GST_NVVCONV (btrans);
+ GstCapsFeatures *ift = NULL;
+ ift = gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_NVMM, NULL);
+
+ n = gst_caps_get_size (othercaps);
+ for (i = 0; i < n; i++) {
+ features = gst_caps_get_features (othercaps, i);
+ if (gst_caps_features_is_equal (features, ift)) {
+ index = i;
+ have_nvfeature = TRUE;
+ }
+ }
+ gst_caps_features_free (ift);
+
+ if (have_nvfeature) {
+ while (index > 0) {
+ gst_caps_remove_structure (othercaps, 0);
+ index--;
+ }
+ }
+
+ othercaps = gst_caps_truncate (othercaps);
+ othercaps = gst_caps_make_writable (othercaps);
+
+ GST_DEBUG_OBJECT (space, "trying to fixate othercaps %" GST_PTR_FORMAT
+ " based on caps %" GST_PTR_FORMAT, othercaps, caps);
+
+ in_struct = gst_caps_get_structure (caps, 0);
+ out_struct = gst_caps_get_structure (othercaps, 0);
+
+ from_pix_ar = gst_structure_get_value (in_struct, "pixel-aspect-ratio");
+ to_pix_ar = gst_structure_get_value (out_struct, "pixel-aspect-ratio");
+
+ from_fmt = gst_structure_get_string (in_struct, "format");
+ to_fmt = gst_structure_get_string (out_struct, "format");
+
+ if (!to_fmt) {
+ /* Output format not fixed */
+ if (!gst_structure_fixate_field_string (out_struct, "format", from_fmt)) {
+ GST_ERROR_OBJECT (space, "Failed to fixate output format");
+ goto finish;
+ }
+ }
+
+ if (gst_structure_has_field (out_struct, "interlace-mode")) {
+ /* interlace-mode present */
+ to_interlace_mode = gst_structure_get_string (out_struct, "interlace-mode");
+ if (!to_interlace_mode) {
+ /* interlace-mode not fixed */
+ from_interlace_mode = gst_structure_get_string (in_struct, "interlace-mode");
+ if (from_interlace_mode)
+ gst_structure_fixate_field_string (out_struct, "interlace-mode", from_interlace_mode);
+ else
+ gst_structure_fixate_field_string (out_struct, "interlace-mode", "progessive");
+ }
+ }
+
+ /* If fixating from the sinkpad always set the PAR and
+ * assume that missing PAR on the sinkpad means 1/1 and
+ * missing PAR on the srcpad means undefined
+ */
+ if (direction == GST_PAD_SINK) {
+ if (!from_pix_ar) {
+ g_value_init (&from_par, GST_TYPE_FRACTION);
+ gst_value_set_fraction (&from_par, 1, 1);
+ from_pix_ar = &from_par;
+ }
+ if (!to_pix_ar) {
+ g_value_init (&to_par, GST_TYPE_FRACTION_RANGE);
+ gst_value_set_fraction_range_full (&to_par, 1, G_MAXINT, G_MAXINT, 1);
+ to_pix_ar = &to_par;
+ }
+ } else {
+ if (!to_pix_ar) {
+ g_value_init (&to_par, GST_TYPE_FRACTION);
+ gst_value_set_fraction (&to_par, 1, 1);
+ to_pix_ar = &to_par;
+
+ gst_structure_set (out_struct, "pixel-aspect-ratio", GST_TYPE_FRACTION, 1,
+ 1, NULL);
+ }
+ if (!from_pix_ar) {
+ g_value_init (&from_par, GST_TYPE_FRACTION);
+ gst_value_set_fraction (&from_par, 1, 1);
+ from_pix_ar = &from_par;
+ }
+ }
+
+ /* have both PAR but they might not be fixated */
+ {
+ gint f_width = 0, f_height = 0, f_par_n = 0, f_par_d = 0, t_par_n = 0, t_par_d = 0;
+ gint t_width = 0, t_height = 0;
+ gint f_dar_n = 0, f_dar_d = 0;
+ gint numerator = 0, denominator = 0;
+
+ /* from_pix_ar should be fixed */
+ g_return_val_if_fail (gst_value_is_fixed (from_pix_ar), othercaps);
+
+ f_par_n = gst_value_get_fraction_numerator (from_pix_ar);
+ f_par_d = gst_value_get_fraction_denominator (from_pix_ar);
+
+ gst_structure_get_int (in_struct, "width", &f_width);
+ gst_structure_get_int (in_struct, "height", &f_height);
+
+ gst_structure_get_int (out_struct, "width", &t_width);
+ gst_structure_get_int (out_struct, "height", &t_height);
+
+ /* if both width and height are already fixed, can't do anything
+ * about it anymore */
+ if (t_width && t_height) {
+ guint num, den;
+
+ GST_DEBUG_OBJECT (space, "dimensions already set to %dx%d, not fixating",
+ t_width, t_height);
+ if (!gst_value_is_fixed (to_pix_ar)) {
+ if (gst_video_calculate_display_ratio (&num, &den, f_width, f_height,
+ f_par_n, f_par_d, t_width, t_height)) {
+ GST_DEBUG_OBJECT (space, "fixating to_pix_ar to %dx%d", num, den);
+ if (gst_structure_has_field (out_struct, "pixel-aspect-ratio")) {
+ gst_structure_fixate_field_nearest_fraction (out_struct,
+ "pixel-aspect-ratio", num, den);
+ } else if (num != den) {
+ gst_structure_set (out_struct, "pixel-aspect-ratio",
+ GST_TYPE_FRACTION, num, den, NULL);
+ }
+ }
+ }
+ goto finish;
+ }
+
+ /* Calc input DAR */
+ if (!gst_util_fraction_multiply (f_width, f_height, f_par_n, f_par_d,
+ &f_dar_n, &f_dar_d)) {
+ GST_ERROR_OBJECT (space, "calculation of the output"
+ "scaled size error");
+ goto finish;
+ }
+
+ GST_DEBUG_OBJECT (space, "Input DAR: %d / %d", f_dar_n, f_dar_d);
+
+ /* If either w or h are fixed either except choose a height or
+ * width and PAR that matches the DAR as near as possible
+ */
+ if (t_width) {
+ /* width is already fixed */
+ gint set_par_n;
+ gint set_par_d;
+
+ gint s_height = 0;
+ GstStructure *tmp_struct = NULL;
+
+ /* Choose the height nearest to
+ * height with same DAR, as PAR is fixed */
+ if (gst_value_is_fixed (to_pix_ar)) {
+ /* get PAR denominator */
+ t_par_d = gst_value_get_fraction_denominator (to_pix_ar);
+ /* get PAR numerator */
+ t_par_n = gst_value_get_fraction_numerator (to_pix_ar);
+
+ if (!gst_util_fraction_multiply (f_dar_n, f_dar_d,
+ t_par_d, t_par_n,
+ &numerator, &denominator)) {
+ GST_ERROR_OBJECT (space, "calculation of the output"
+ "scaled size error");
+ goto finish;
+ }
+
+ /* calc height */
+ t_height = (guint) gst_util_uint64_scale_int (t_width,
+ denominator, numerator);
+ /* set height */
+ gst_structure_fixate_field_nearest_int (out_struct, "height", t_height);
+
+ goto finish;
+ }
+
+ /* The PAR is not fixed set arbitrary PAR. */
+
+ /* can keep the input height check */
+ tmp_struct = gst_structure_copy (out_struct);
+ gst_structure_fixate_field_nearest_int (tmp_struct, "height", f_height);
+ gst_structure_get_int (tmp_struct, "height", &s_height);
+
+ /* May failed but try to keep the DAR however by
+ * adjusting the PAR */
+ if (!gst_util_fraction_multiply (f_dar_n, f_dar_d, s_height, t_width,
+ &t_par_n, &t_par_d)) {
+ GST_ERROR_OBJECT (space, "calculation of the output"
+ "scaled size error");
+ gst_structure_free (tmp_struct);
+ goto finish;
+ }
+
+ if (!gst_structure_has_field (tmp_struct, "pixel-aspect-ratio")) {
+ gst_structure_set_value (tmp_struct, "pixel-aspect-ratio", to_pix_ar);
+ }
+
+ /* set fixate PAR */
+ if (gst_structure_fixate_field_nearest_fraction (tmp_struct,
+ "pixel-aspect-ratio",
+ t_par_n, t_par_d)) {
+ /* get PAR */
+ if (gst_structure_get_field_type (tmp_struct, "pixel-aspect-ratio") !=
+ G_TYPE_INVALID) {
+ if(!gst_structure_get_fraction (tmp_struct,
+ "pixel-aspect-ratio",
+ &set_par_n, &set_par_d))
+ GST_ERROR_OBJECT (space, "PAR values set failed");
+ }
+ /* values set correctly */
+ if (tmp_struct) {
+ gst_structure_free (tmp_struct);
+ tmp_struct = NULL;
+ }
+ }
+
+ if (set_par_n == t_par_n) {
+ if (set_par_d == t_par_d) {
+ /* Check for PAR field */
+ if (gst_structure_has_field (out_struct, "pixel-aspect-ratio") ||
+ !(set_par_n == set_par_d)) {
+ /* set height & PAR */
+ gst_structure_set (out_struct,
+ "height", G_TYPE_INT, s_height,
+ "pixel-aspect-ratio", GST_TYPE_FRACTION,
+ set_par_n, set_par_d,
+ NULL);
+ }
+ goto finish;
+ }
+ }
+
+ if (!gst_util_fraction_multiply (f_dar_n, f_dar_d,
+ set_par_d, set_par_n,
+ &numerator, &denominator)) {
+ GST_ERROR_OBJECT (space, "calculation of the output"
+ "scaled size error");
+ goto finish;
+ }
+
+ /* Calc height */
+ t_height = (guint) gst_util_uint64_scale_int (t_width,
+ denominator, numerator);
+ /* Set height */
+ gst_structure_fixate_field_nearest_int (out_struct, "height", t_height);
+
+ /* If struct has field PAR then set PAR */
+ if (gst_structure_has_field (out_struct, "pixel-aspect-ratio") ||
+ !(set_par_n == set_par_d)) {
+ /* set PAR */
+ gst_structure_set (out_struct, "pixel-aspect-ratio", GST_TYPE_FRACTION,
+ set_par_n, set_par_d,
+ NULL);
+ }
+ goto finish;
+ } else if (t_height) {
+ /* height is already fixed */
+ gint set_par_n;
+ gint set_par_d;
+
+ gint s_width = 0;
+ GstStructure *tmp_struct = NULL;
+
+ /* Choose the width nearest to the
+ * width with same DAR, as PAR is fixed */
+ if (gst_value_is_fixed (to_pix_ar)) {
+ /* get PAR denominator */
+ t_par_d = gst_value_get_fraction_denominator (to_pix_ar);
+ /* get PAR numerator */
+ t_par_n = gst_value_get_fraction_numerator (to_pix_ar);
+
+ if (!gst_util_fraction_multiply (f_dar_n, f_dar_d, t_par_d,
+ t_par_n, &numerator, &denominator)) {
+ GST_ERROR_OBJECT (space, "calculation of the output"
+ "scaled size error");
+ goto finish;
+ }
+
+ /* calc width */
+ t_width =
+ (guint) gst_util_uint64_scale_int (t_height, numerator,
+ denominator);
+ /* set width */
+ gst_structure_fixate_field_nearest_int (out_struct, "width", t_width);
+
+ goto finish;
+ }
+
+ /* PAR is not fixed set arbitrary PAR */
+
+ tmp_struct = gst_structure_copy (out_struct);
+ gst_structure_fixate_field_nearest_int (tmp_struct, "width", f_width);
+ gst_structure_get_int (tmp_struct, "width", &s_width);
+
+ /* May failed but try to keep the DAR however by
+ * adjusting the PAR */
+ if (!gst_util_fraction_multiply (f_dar_n, f_dar_d, t_height, s_width,
+ &t_par_n, &t_par_d)) {
+ GST_ERROR_OBJECT (space, "calculation of the output"
+ "scaled size error");
+ gst_structure_free (tmp_struct);
+ goto finish;
+ }
+
+ if (!gst_structure_has_field (tmp_struct, "pixel-aspect-ratio")) {
+ gst_structure_set_value (tmp_struct, "pixel-aspect-ratio", to_pix_ar);
+ }
+
+ /* set fixate PAR */
+ if (gst_structure_fixate_field_nearest_fraction (tmp_struct,
+ "pixel-aspect-ratio",
+ t_par_n, t_par_d)) {
+ if (gst_structure_get_field_type (tmp_struct, "pixel-aspect-ratio") !=
+ G_TYPE_INVALID) {
+ /* get PAR */
+ if (!gst_structure_get_fraction (tmp_struct,
+ "pixel-aspect-ratio",
+ &set_par_n, &set_par_d))
+ GST_ERROR_OBJECT (space, "PAR values set failed");
+ }
+ /* values set correctly */
+ if (tmp_struct) {
+ gst_structure_free (tmp_struct);
+ tmp_struct = NULL;
+ }
+ }
+
+ if (set_par_n == t_par_n) {
+ if (set_par_d == t_par_d) {
+ /* check for PAR field */
+ if (gst_structure_has_field (out_struct, "pixel-aspect-ratio") ||
+ !(set_par_n == set_par_d)) {
+ /* set width & PAR */
+ gst_structure_set (out_struct,
+ "width", G_TYPE_INT, s_width,
+ "pixel-aspect-ratio", GST_TYPE_FRACTION,
+ set_par_n, set_par_d,
+ NULL);
+ }
+ goto finish;
+ }
+ }
+
+ if (!gst_util_fraction_multiply (f_dar_n, f_dar_d,
+ set_par_d, set_par_n,
+ &numerator, &denominator)) {
+ GST_ERROR_OBJECT (space, "calculation of the output"
+ "scaled size error");
+ goto finish;
+ }
+
+ /* Calc width */
+ t_width = (guint) gst_util_uint64_scale_int (t_height,
+ numerator, denominator);
+
+ /* Set width */
+ gst_structure_fixate_field_nearest_int (out_struct, "width", t_width);
+
+ /* If struct has field PAR then set PAR */
+ if (gst_structure_has_field (out_struct, "pixel-aspect-ratio") ||
+ !(set_par_n == set_par_d)) {
+ /* set PAR*/
+ gst_structure_set (out_struct, "pixel-aspect-ratio", GST_TYPE_FRACTION,
+ set_par_n, set_par_d,
+ NULL);
+ }
+
+ goto finish;
+ } else if (gst_value_is_fixed (to_pix_ar)) {
+
+ gint s_height = 0;
+ gint s_width = 0;
+ gint from_hight = 0;
+ gint from_width = 0;
+ GstStructure *tmp_struct = NULL;
+
+ /* Get PAR denominator */
+ t_par_d = gst_value_get_fraction_denominator (to_pix_ar);
+ /* Get PAR numerator */
+ t_par_n = gst_value_get_fraction_numerator (to_pix_ar);
+
+ /* find scale factor for change in PAR */
+ if (!gst_util_fraction_multiply (f_dar_n, f_dar_d,
+ t_par_n, t_par_d,
+ &numerator, &denominator)) {
+ GST_ERROR_OBJECT (space, "calculation of the output"
+ "scaled size error");
+ goto finish;
+ }
+
+ tmp_struct = gst_structure_copy (out_struct);
+
+ gst_structure_fixate_field_nearest_int (tmp_struct, "height", f_height);
+ gst_structure_get_int (tmp_struct, "height", &s_height);
+
+ /* This may failed but however scale the width to keep DAR */
+ t_width =
+ (guint) gst_util_uint64_scale_int (s_height, numerator, denominator);
+ gst_structure_fixate_field_nearest_int (tmp_struct, "width", t_width);
+ gst_structure_get_int (tmp_struct, "width", &s_width);
+ gst_structure_free (tmp_struct);
+
+ /* kept DAR and the height is nearest to the original height */
+ if (s_width == t_width) {
+ gst_structure_set (out_struct, "width", G_TYPE_INT, s_width, "height",
+ G_TYPE_INT, s_height, NULL);
+ goto finish;
+ }
+
+ from_hight = s_height;
+ from_width = s_width;
+
+ /* If former failed, try to keep the input width at least */
+ tmp_struct = gst_structure_copy (out_struct);
+ gst_structure_fixate_field_nearest_int (tmp_struct, "width", f_width);
+ gst_structure_get_int (tmp_struct, "width", &s_width);
+
+ /* This may failed but however try to scale the width to keep DAR */
+ t_height =
+ (guint) gst_util_uint64_scale_int (s_width, denominator, numerator);
+ gst_structure_fixate_field_nearest_int (tmp_struct, "height", t_height);
+ gst_structure_get_int (tmp_struct, "height", &s_height);
+ gst_structure_free (tmp_struct);
+
+ /* We kept the DAR and the width is nearest to the original width */
+ if (s_height == t_height) {
+ gst_structure_set (out_struct, "width", G_TYPE_INT, s_width, "height",
+ G_TYPE_INT, s_height, NULL);
+ goto finish;
+ }
+
+ /* If all failed, keep the height that nearest to the orignal
+ * height and the nearest possible width.
+ */
+ gst_structure_set (out_struct, "width", G_TYPE_INT, from_width, "height",
+ G_TYPE_INT, from_hight, NULL);
+ goto finish;
+ } else {
+ gint tmp_struct2 = 0;
+ gint set_par_n = 0;
+ gint set_par_d = 0;
+ gint s_height = 0;
+ gint s_width = 0;
+ GstStructure *tmp_struct = NULL;
+
+ /* width, height and PAR are not fixed though passthrough impossible */
+
+ /* keep height and width as fine as possible & scale PAR */
+ tmp_struct = gst_structure_copy (out_struct);
+
+ if (gst_structure_fixate_field_nearest_int (tmp_struct, "height", f_height))
+ gst_structure_get_int (tmp_struct, "height", &s_height);
+
+ if (gst_structure_fixate_field_nearest_int (tmp_struct, "width", f_width))
+ gst_structure_get_int (tmp_struct, "width", &s_width);
+
+ if (!gst_util_fraction_multiply (f_dar_n, f_dar_d,
+ s_height, s_width,
+ &t_par_n, &t_par_d)) {
+ GST_ERROR_OBJECT (space, "calculation of the output"
+ "scaled size error");
+ goto finish;
+ }
+
+ if (!gst_structure_has_field (tmp_struct, "pixel-aspect-ratio")) {
+ gst_structure_set_value (tmp_struct, "pixel-aspect-ratio", to_pix_ar);
+ }
+
+ if (gst_structure_fixate_field_nearest_fraction (tmp_struct, "pixel-aspect-ratio",
+ t_par_n, t_par_d)) {
+ gst_structure_get_fraction (tmp_struct, "pixel-aspect-ratio",
+ &set_par_n, &set_par_d);
+ }
+ gst_structure_free (tmp_struct);
+
+ if (set_par_n == t_par_n) {
+ if (set_par_d == t_par_d) {
+ gst_structure_set (out_struct,
+ "width", G_TYPE_INT, s_width,
+ "height", G_TYPE_INT, s_height,
+ NULL);
+
+ if (gst_structure_has_field (out_struct, "pixel-aspect-ratio") ||
+ !(set_par_n == set_par_d))
+ gst_structure_set (out_struct, "pixel-aspect-ratio", GST_TYPE_FRACTION,
+ set_par_n, set_par_d,
+ NULL);
+ space->no_dimension = TRUE;
+ goto finish;
+ }
+ }
+
+ /* Or scale width to keep the DAR with the set
+ * PAR and height */
+ if (!gst_util_fraction_multiply (f_dar_n, f_dar_d,
+ set_par_d, set_par_n,
+ &numerator, &denominator)) {
+ GST_ERROR_OBJECT (space, "calculation of the output"
+ "scaled size error");
+ goto finish;
+ }
+
+ t_width =
+ (guint) gst_util_uint64_scale_int (s_height, numerator, denominator);
+ tmp_struct = gst_structure_copy (out_struct);
+
+ if (gst_structure_fixate_field_nearest_int (tmp_struct, "width", t_width)) {
+ gst_structure_get_int (tmp_struct, "width", &tmp_struct2);
+ }
+ gst_structure_free (tmp_struct);
+
+ if (tmp_struct2 == t_width) {
+ gst_structure_set (out_struct,
+ "width", G_TYPE_INT, tmp_struct2,
+ "height", G_TYPE_INT, s_height,
+ NULL);
+ if (gst_structure_has_field (out_struct, "pixel-aspect-ratio")
+ || (set_par_n != set_par_d))
+ gst_structure_set (out_struct, "pixel-aspect-ratio",
+ GST_TYPE_FRACTION, set_par_n, set_par_d,
+ NULL);
+ space->no_dimension = TRUE;
+ goto finish;
+ }
+
+ t_height =
+ (guint) gst_util_uint64_scale_int (s_width, denominator, numerator);
+ tmp_struct = gst_structure_copy (out_struct);
+
+ if (gst_structure_fixate_field_nearest_int (tmp_struct, "height", t_height)) {
+ gst_structure_get_int (tmp_struct, "height", &tmp_struct2);
+ }
+ gst_structure_free (tmp_struct);
+
+ if (tmp_struct2 == t_height) {
+ gst_structure_set (out_struct,
+ "width", G_TYPE_INT, s_width,
+ "height", G_TYPE_INT, tmp_struct2,
+ NULL);
+ if (gst_structure_has_field (out_struct, "pixel-aspect-ratio") ||
+ set_par_n != set_par_d)
+ gst_structure_set (out_struct, "pixel-aspect-ratio",
+ GST_TYPE_FRACTION, set_par_n, set_par_d,
+ NULL);
+ space->no_dimension = TRUE;
+ goto finish;
+ }
+
+ /* If all failed can't keep DAR & take nearest values for all */
+ gst_structure_set (out_struct,
+ "width", G_TYPE_INT, s_width,
+ "height", G_TYPE_INT, s_height,
+ NULL);
+ if (gst_structure_has_field (out_struct, "pixel-aspect-ratio") ||
+ (set_par_n != set_par_d))
+ gst_structure_set (out_struct, "pixel-aspect-ratio", GST_TYPE_FRACTION,
+ set_par_n, set_par_d,
+ NULL);
+ space->no_dimension = TRUE;
+ }
+ }
+
+finish:
+ if (space->no_dimension && space->do_flip) {
+ switch (space->flip_method) {
+ case GST_VIDEO_NVFLIP_METHOD_90R:
+ case GST_VIDEO_NVFLIP_METHOD_90L:
+ case GST_VIDEO_NVFLIP_METHOD_INVTRANS:
+ case GST_VIDEO_NVFLIP_METHOD_TRANS:
+ if (gst_structure_get_int (out_struct, "width", &tt_width) &&
+ gst_structure_get_int (out_struct, "height", &tt_height)) {
+ gst_structure_set (out_struct, "width", G_TYPE_INT, tt_height,
+ "height", G_TYPE_INT, tt_width, NULL);
+ }
+ break;
+ case GST_VIDEO_NVFLIP_METHOD_IDENTITY:
+ case GST_VIDEO_NVFLIP_METHOD_180:
+ case GST_VIDEO_NVFLIP_METHOD_HORIZ:
+ case GST_VIDEO_NVFLIP_METHOD_VERT:
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ }
+
+ if (from_pix_ar == &from_par)
+ g_value_unset (&from_par);
+ if (to_pix_ar == &to_par)
+ g_value_unset (&to_par);
+
+ if (direction == GST_PAD_SINK) {
+ /* Try and preserve input colorimetry / chroma information */
+ gboolean have_colorimetry =
+ gst_structure_has_field (out_struct, "colorimetry");
+ gboolean have_chroma_site =
+ gst_structure_has_field (out_struct, "chroma-site");
+
+ /* If the output already has colorimetry and chroma-site, stop,
+ * otherwise try and transfer what we can from the input caps */
+ if (!have_colorimetry && !have_chroma_site) {
+ transfer_colorimetry_from_input (space, caps, othercaps);
+ }
+ }
+
+ GST_DEBUG_OBJECT (space, "fixated othercaps to %" GST_PTR_FORMAT, othercaps);
+ return othercaps;
+}
+
+/**
+ * Given the pad in direction and the given caps,
+ * provide allowed caps on the other pad.
+ *
+ * @param btrans : basetransform object instance
+ * @param direction : pad direction
+ * @param caps : given caps
+ * @param filter : other caps
+ */
+static GstCaps *
+gst_nvvconv_transform_caps (GstBaseTransform * btrans,
+ GstPadDirection direction, GstCaps * caps, GstCaps * filter)
+{
+ GstCaps *ret = NULL;
+ GstCaps *tmp1, *tmp2;
+ GstCapsFeatures *features = NULL;
+
+ GST_DEBUG_OBJECT (btrans,
+ "Transforming caps %" GST_PTR_FORMAT " in direction %s", caps,
+ (direction == GST_PAD_SINK) ? "sink" : "src");
+
+ /* Get all possible caps that we can transform into */
+ tmp1 = gst_nvvconv_caps_remove_format_info (caps);
+
+ if (filter) {
+ if (direction == GST_PAD_SRC) {
+ GstCapsFeatures *ift = NULL;
+ ift = gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_NVMM, NULL);
+ features = gst_caps_get_features (filter, 0);
+ if (!gst_caps_features_is_equal (features, ift)) {
+ gint n, i;
+ GstCapsFeatures *tft;
+ n = gst_caps_get_size (tmp1);
+ for (i = 0; i < n; i++) {
+ tft = gst_caps_get_features (tmp1, i);
+ if (gst_caps_features_get_size (tft))
+ gst_caps_features_remove (tft, GST_CAPS_FEATURE_MEMORY_NVMM);
+ }
+ }
+ gst_caps_features_free (ift);
+ }
+
+ tmp2 = gst_caps_intersect_full (filter, tmp1, GST_CAPS_INTERSECT_FIRST);
+ gst_caps_unref (tmp1);
+ tmp1 = tmp2;
+ }
+
+ if (gst_caps_is_empty(tmp1)) {
+ ret = gst_caps_copy(filter);
+ gst_caps_unref (tmp1);
+ } else {
+ ret = tmp1;
+ }
+
+ if (!filter) {
+ GstStructure *str;
+ str = gst_structure_copy (gst_caps_get_structure (ret, 0));
+
+ GstCapsFeatures *ift;
+ ift = gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_NVMM, NULL);
+
+ gst_caps_append_structure_full (ret, str, ift);
+
+ str = gst_structure_copy (gst_caps_get_structure (ret, 0));
+ gst_caps_append_structure_full (ret, str, NULL);
+ }
+
+ GST_DEBUG_OBJECT (btrans, "transformed %" GST_PTR_FORMAT " into %"
+ GST_PTR_FORMAT, caps, ret);
+
+ return ret;
+}
+
+/**
+ * check if caps can be handled by the element.
+ *
+ * @param btrans : basetransform object instance
+ * @param direction : pad direction
+ * @param caps : given caps
+ */
+static gboolean
+gst_nvvconv_accept_caps (GstBaseTransform * btrans,
+ GstPadDirection direction, GstCaps * caps)
+{
+ gboolean ret = TRUE;
+ Gstnvvconv *space = NULL;
+ GstCaps *allowed = NULL;
+
+ space = GST_NVVCONV (btrans);
+
+ GST_DEBUG_OBJECT (btrans, "accept caps %" GST_PTR_FORMAT, caps);
+
+ /* get all the formats we can handle on this pad */
+ if (direction == GST_PAD_SINK)
+ allowed = space->sinkcaps;
+ else
+ allowed = space->srccaps;
+
+ if (!allowed) {
+ GST_DEBUG_OBJECT (btrans, "failed to get allowed caps");
+ goto no_transform_possible;
+ }
+
+ GST_DEBUG_OBJECT (btrans, "allowed caps %" GST_PTR_FORMAT, allowed);
+
+ /* intersect with the requested format */
+ ret = gst_caps_is_subset (caps, allowed);
+ if (!ret) {
+ goto no_transform_possible;
+ }
+
+done:
+ return ret;
+
+ /* ERRORS */
+no_transform_possible:
+ {
+ GST_DEBUG_OBJECT (btrans,
+ "could not transform %" GST_PTR_FORMAT " in anything we support", caps);
+ ret = FALSE;
+ goto done;
+ }
+}
+
+/**
+ * Setup the allocation parameters for allocating output buffers.
+ *
+ * @param btrans : basetransform object instance
+ * @param query : downstream allocation query
+ */
+static gboolean
+gst_nvvconv_decide_allocation (GstBaseTransform * btrans, GstQuery * query)
+{
+ guint j, metas_no;
+ Gstnvvconv *space = NULL;
+ GstCaps *outcaps = NULL;
+ GstCaps *myoutcaps = NULL;
+ GstBufferPool *pool = NULL;
+ guint size, minimum, maximum;
+ GstAllocator *allocator = NULL;
+ GstAllocationParams params = { 0, 0, 0, 0 };
+ GstStructure *config = NULL;
+ GstVideoInfo info;
+ gboolean modify_allocator;
+
+ space = GST_NVVCONV (btrans);
+
+ metas_no = gst_query_get_n_allocation_metas (query);
+ for (j = 0; j < metas_no; j++) {
+ gboolean remove_meta;
+ GType meta_api;
+ const GstStructure *param_str = NULL;
+
+ meta_api = gst_query_parse_nth_allocation_meta (query, j, ¶m_str);
+
+ if (gst_meta_api_type_has_tag (meta_api, GST_META_TAG_MEMORY)) {
+ /* Different memory will get allocated for input and output.
+ remove all memory dependent metadata */
+ GST_DEBUG_OBJECT (space, "remove memory specific metadata %s",
+ g_type_name (meta_api));
+ remove_meta = TRUE;
+ } else {
+ /* Default remove all metadata */
+ GST_DEBUG_OBJECT (space, "remove metadata %s", g_type_name (meta_api));
+ remove_meta = TRUE;
+ }
+
+ if (remove_meta) {
+ gst_query_remove_nth_allocation_meta (query, j);
+ j--;
+ metas_no--;
+ }
+ }
+
+ gst_query_parse_allocation (query, &outcaps, NULL);
+ if (outcaps == NULL)
+ goto no_caps;
+
+ /* Use nvfilter custom buffer pool */
+ if (space->nvfilterpool) {
+ g_mutex_lock (&space->flow_lock);
+ pool = space->pool;
+ if (pool)
+ gst_object_ref (pool);
+ g_mutex_unlock (&space->flow_lock);
+
+ if (pool != NULL) {
+ config = gst_buffer_pool_get_config (pool);
+ gst_buffer_pool_config_get_params (config, &myoutcaps, &size, NULL, NULL);
+
+ GST_DEBUG_OBJECT (space, "we have a pool with caps %" GST_PTR_FORMAT,
+ myoutcaps);
+
+ if (!gst_caps_is_equal (outcaps, myoutcaps)) {
+ /* different caps, we can't use current pool */
+ GST_DEBUG_OBJECT (space, "pool has different caps");
+ gst_object_unref (pool);
+ pool = NULL;
+ }
+ gst_structure_free (config);
+ }
+
+ if (pool == NULL) {
+ if (!gst_video_info_from_caps (&info, outcaps))
+ goto invalid_caps;
+
+ size = info.size;
+ minimum = space->num_output_buf;
+
+ GST_DEBUG_OBJECT (space, "create new pool");
+
+ g_mutex_lock (&space->flow_lock);
+ pool = gst_nv_filter_buffer_pool_new (GST_ELEMENT_CAST (space));
+
+ if (pool) {
+ config = gst_buffer_pool_get_config (pool);
+ gst_buffer_pool_config_set_params (config, outcaps, sizeof (NvBufSurface), minimum, minimum);
+ gst_buffer_pool_config_set_allocator (config,
+ ((GstNvFilterBufferPool *) pool)->allocator, NULL);
+ if (!gst_buffer_pool_set_config (pool, config))
+ goto config_failed;
+ space->pool = gst_object_ref (pool);
+ }
+
+ g_mutex_unlock (&space->flow_lock);
+ }
+
+ if (pool) {
+ config = gst_buffer_pool_get_config (pool);
+ gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms);
+ gst_buffer_pool_config_get_params (config, &myoutcaps, &size, &minimum, &maximum);
+
+ /* Add check, params may be empty e.g. fakesink */
+ if (gst_query_get_n_allocation_params (query) > 0) {
+ /* Set allocation params */
+ gst_query_set_nth_allocation_param (query, 0, allocator, ¶ms);
+ } else {
+ /* Add allocation params */
+ gst_query_add_allocation_param (query, allocator, ¶ms);
+ }
+
+ /* Set allocation pool */
+ if (gst_query_get_n_allocation_pools (query) > 0) {
+ gst_query_set_nth_allocation_pool (query, 0, pool, size, minimum, maximum);
+ } else {
+ gst_query_add_allocation_pool (query, pool, size, minimum, maximum);
+ }
+
+ gst_structure_free (config);
+ gst_object_unref (pool);
+ }
+ } else {
+ /* Use oss buffer pool */
+ if (gst_query_get_n_allocation_params (query) > 0) {
+ /* Get allocation params */
+ gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms);
+ modify_allocator = TRUE;
+ } else {
+ allocator = NULL;
+ gst_allocation_params_init (¶ms);
+ modify_allocator = FALSE;
+ }
+
+ if (gst_query_get_n_allocation_pools (query) > 0) {
+ /* Parse pool to get size, min & max */
+ gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &minimum, &maximum);
+ if (pool == NULL) {
+ GST_DEBUG_OBJECT (btrans, "no pool available, creating new oss pool");
+ pool = gst_buffer_pool_new ();
+ }
+ } else {
+ pool = NULL;
+ size = 0;
+ minimum = 0;
+ maximum = 0;
+ }
+
+ if (pool) {
+ config = gst_buffer_pool_get_config (pool);
+ /* Set params on config */
+ gst_buffer_pool_config_set_params (config, outcaps, size, minimum, maximum);
+ /* Set allocator on config */
+ gst_buffer_pool_config_set_allocator (config, allocator, ¶ms);
+ /* Set config on pool */
+ gst_buffer_pool_set_config (pool, config);
+ }
+
+ if (modify_allocator) {
+ /* Set allocation params */
+ gst_query_set_nth_allocation_param (query, 0, allocator, ¶ms);
+ } else {
+ /* Add allocation params */
+ gst_query_add_allocation_param (query, allocator, ¶ms);
+ }
+
+ if (allocator) {
+ gst_object_unref (allocator);
+ }
+
+ if (pool) {
+ gst_query_set_nth_allocation_pool (query, 0, pool, size, minimum, maximum);
+ gst_object_unref (pool);
+ }
+ }
+
+ return TRUE;
+/* ERROR */
+no_caps:
+ {
+ GST_ERROR ("no caps specified");
+ return FALSE;
+ }
+invalid_caps:
+ {
+ GST_ERROR ("invalid caps specified");
+ return FALSE;
+ }
+config_failed:
+ {
+ GST_ERROR ("failed to set config on bufferpool");
+ g_mutex_unlock (&space->flow_lock);
+ return FALSE;
+ }
+}
+
+static gint
+get_bytes_per_pix_from_color (NvBufSurfaceColorFormat pix_fmt, gint plane_id)
+{
+ gint bytes_per_pix = 1;
+ switch (pix_fmt) {
+ case NVBUF_COLOR_FORMAT_YUV420:
+ case NVBUF_COLOR_FORMAT_YUV422:
+ case NVBUF_COLOR_FORMAT_YUV420_709:
+ case NVBUF_COLOR_FORMAT_YUV420_709_ER:
+ case NVBUF_COLOR_FORMAT_YUV420_ER:
+ case NVBUF_COLOR_FORMAT_YUV444:
+ bytes_per_pix = 1;
+ break;
+ case NVBUF_COLOR_FORMAT_NV12:
+ case NVBUF_COLOR_FORMAT_NV12_709:
+ case NVBUF_COLOR_FORMAT_NV12_709_ER:
+ case NVBUF_COLOR_FORMAT_NV12_ER:
+ case NVBUF_COLOR_FORMAT_NV12_2020:
+ case NVBUF_COLOR_FORMAT_NV21:
+ case NVBUF_COLOR_FORMAT_NV16:
+ case NVBUF_COLOR_FORMAT_NV24:
+ if (plane_id == 0)
+ bytes_per_pix = 1;
+ else
+ bytes_per_pix = 2;
+ break;
+ case NVBUF_COLOR_FORMAT_NV12_12LE:
+ case NVBUF_COLOR_FORMAT_NV12_10LE:
+ case NVBUF_COLOR_FORMAT_NV12_10LE_709:
+ case NVBUF_COLOR_FORMAT_NV12_10LE_2020:
+ case NVBUF_COLOR_FORMAT_NV12_10LE_ER:
+ case NVBUF_COLOR_FORMAT_NV12_10LE_709_ER:
+ if (plane_id == 0)
+ bytes_per_pix = 2;
+ else
+ bytes_per_pix = 4;
+ break;
+ case NVBUF_COLOR_FORMAT_UYVY:
+ case NVBUF_COLOR_FORMAT_UYVY_709:
+ case NVBUF_COLOR_FORMAT_UYVY_2020:
+ case NVBUF_COLOR_FORMAT_UYVY_709_ER:
+ case NVBUF_COLOR_FORMAT_UYVY_ER:
+ case NVBUF_COLOR_FORMAT_YUYV:
+ case NVBUF_COLOR_FORMAT_YVYU:
+ bytes_per_pix = 2;
+ break;
+ case NVBUF_COLOR_FORMAT_BGRx:
+ case NVBUF_COLOR_FORMAT_RGBA:
+ bytes_per_pix = 4;
+ break;
+ case NVBUF_COLOR_FORMAT_BGR:
+ case NVBUF_COLOR_FORMAT_RGB:
+ bytes_per_pix = 3;
+ break;
+ case NVBUF_COLOR_FORMAT_GRAY8:
+ case NVBUF_COLOR_FORMAT_R8_G8_B8:
+ case NVBUF_COLOR_FORMAT_B8_G8_R8:
+ bytes_per_pix = 1;
+ break;
+ case NVBUF_COLOR_FORMAT_R32F_G32F_B32F:
+ case NVBUF_COLOR_FORMAT_B32F_G32F_R32F:
+ bytes_per_pix = sizeof (float);
+ break;
+ default:
+ break;
+ }
+
+ return bytes_per_pix;
+}
+
+static void
+surface_list_init (Gstnvvconv * space, NvBufSurface * surf,
+ GstMapInfo * surf_list_map, gboolean flag)
+{
+ gpointer surf_list_data = surf_list_map->data;
+ guint bytesPerPixel;
+ gsize surf_list_size = surf_list_map->size;
+
+ surf->gpuId = space->gpu_id;
+ surf->batchSize = 1;
+ surf->numFilled = 1;
+ surf->memType = NVBUF_MEM_SYSTEM;
+ GstVideoInfo *surf_list_info = NULL;
+ /* Flag is set as 1 if input surface needs to be populated and to 0 if output
+ * surface has to be populated.
+ */
+ if (flag) {
+ bytesPerPixel = get_bytes_per_pix_from_color (space->in_pix_fmt, 0);
+ surf->surfaceList->planeParams.num_planes = space->in_info.finfo->n_planes;
+ surf->surfaceList->pitch = space->in_info.stride[0];
+ surf->surfaceList->colorFormat = space->in_pix_fmt;
+ surf->surfaceList->planeParams.offset[0] = space->in_info.offset[0];
+ surf->surfaceList->width = space->from_width;
+ surf->surfaceList->height = space->from_height;
+ surf->surfaceList->planeParams.width[0] = space->from_width;
+ surf->surfaceList->planeParams.height[0] = space->from_height;
+ surf->surfaceList->planeParams.psize[0] =
+ space->from_height * surf->surfaceList->pitch;
+ surf_list_info = &(space->in_info);
+ } else {
+ bytesPerPixel = get_bytes_per_pix_from_color (space->out_pix_fmt, 0);
+ surf->surfaceList->planeParams.num_planes = space->out_info.finfo->n_planes;
+ surf->surfaceList->pitch = space->out_info.stride[0];
+ surf->surfaceList->colorFormat = space->out_pix_fmt;
+ surf->surfaceList->planeParams.offset[0] = space->out_info.offset[0];
+ surf->surfaceList->width = space->to_width;
+ surf->surfaceList->height = space->to_height;
+ surf->surfaceList->planeParams.width[0] = space->to_width;
+ surf->surfaceList->planeParams.height[0] = space->to_height;
+ surf->surfaceList->planeParams.psize[0] =
+ space->to_height * surf->surfaceList->pitch;
+ surf_list_info = &(space->out_info);
+ }
+ surf->surfaceList->dataSize = surf_list_size; // size of allocated hw mem
+ surf->surfaceList->dataPtr = surf_list_data;
+ surf->surfaceList->layout = NVBUF_LAYOUT_PITCH;
+ surf->surfaceList->planeParams.pitch[0] = surf->surfaceList->pitch;
+ surf->surfaceList->planeParams.bytesPerPix[0] = bytesPerPixel;
+
+ for (uint32_t j = 1; j < surf_list_info->finfo->n_planes; j++) {
+ guint comp_width = GST_VIDEO_INFO_COMP_WIDTH (surf_list_info, j);
+ guint comp_height = GST_VIDEO_INFO_COMP_HEIGHT (surf_list_info, j);
+ guint comp_pitch = surf_list_info->stride[j];
+ surf->surfaceList->planeParams.height[j] = comp_height;
+ surf->surfaceList->planeParams.pitch[j] = comp_pitch;
+ surf->surfaceList->planeParams.offset[j] = surf_list_info->offset[j];
+ surf->surfaceList->planeParams.psize[j] = comp_pitch * comp_height;
+ bytesPerPixel =
+ get_bytes_per_pix_from_color (surf->surfaceList->colorFormat, j);
+ surf->surfaceList->planeParams.width[j] = comp_width;
+ surf->surfaceList->planeParams.bytesPerPix[j] = bytesPerPixel;
+ }
+}
+
+/**
+ * Transforms one incoming buffer to one outgoing buffer.
+ *
+ * @param inbuf : input buffer
+ * @param outbuf : output buffer
+ */
+static GstFlowReturn
+gst_nvvconv_transform (GstBaseTransform * btrans, GstBuffer * inbuf,
+ GstBuffer * outbuf)
+{
+ gint retn = 0;
+ gboolean ret = TRUE;
+ GstFlowReturn flow_ret = GST_FLOW_OK;
+
+ Gstnvvconv *space = NULL;
+
+ GstMemory *inmem = NULL;
+ GstMemory *outmem = NULL;
+ GstNvFilterMemory *omem = NULL;
+
+ GstMapInfo inmap = GST_MAP_INFO_INIT;
+ GstMapInfo outmap = GST_MAP_INFO_INIT;
+
+ NvBufSurfaceAllocateParams input_params = {0};
+
+ gpointer data = NULL;
+
+ space = GST_NVVCONV (btrans);
+ char context[100];
+ sprintf(context,"gst_nvvconv_transform()_ctx=%p",space);
+ NvBufSurfTransform_Error err = NvBufSurfTransformError_Success;
+ cudaError_t CUerr = cudaSuccess;
+
+ if (G_UNLIKELY (!space->negotiated))
+ goto unknown_format;
+
+ inmem = gst_buffer_peek_memory (inbuf, 0);
+ if (!inmem)
+ goto no_memory;
+
+ outmem = gst_buffer_peek_memory (outbuf, 0);
+ if (!outmem)
+ goto no_memory;
+ omem = (GstNvFilterMemory *) outmem;
+
+ if (!gst_buffer_map (inbuf, &inmap, GST_MAP_READ))
+ goto invalid_inbuf;
+
+ if (!gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE))
+ goto invalid_outbuf;
+
+ if (!gst_buffer_copy_into (outbuf, inbuf, GST_BUFFER_COPY_META, 0, -1)) {
+ GST_DEBUG ("Buffer metadata copy failed \n");
+ }
+
+ if (space->compute_hw == NvBufSurfTransformCompute_GPU) {
+ CUerr = cudaSetDevice (space->gpu_id);
+ if (CUerr != cudaSuccess) {
+ g_print ("Unable to set cuda device\n");
+ goto cuda_errors;
+ }
+ } else {
+ if (space->inbuf_memtype == BUF_MEM_HW) {
+ NvBufSurface *surf = ((NvBufSurface *) inmap.data);
+ if (surf->memType == NVBUF_MEM_CUDA_DEVICE || surf->memType == NVBUF_MEM_CUDA_PINNED) {
+ CUerr = cudaSetDevice (space->gpu_id);
+ if (CUerr != cudaSuccess) {
+ g_print ("Unable to set cuda device\n");
+ goto cuda_errors;
+ }
+ }
+ }
+ }
+
+ data = gst_mini_object_get_qdata ((GstMiniObject *)inbuf, g_quark_from_static_string("NV_BUF"));
+
+ if(data == (gpointer)NVBUF_MAGIC_NUM)
+ {
+ space->inbuf_memtype = BUF_MEM_HW;
+ }
+
+ if (space->session_created == 0)
+ {
+ space->config_params.compute_mode = space->compute_hw;
+ if (space->compute_hw == NvBufSurfTransformCompute_GPU) {
+ space->config_params.gpu_id = space->gpu_id;
+ cudaStreamCreateWithFlags (&(space->config_params.cuda_stream), cudaStreamNonBlocking);
+ }
+ space->session_created = 1;
+ }
+
+ err = NvBufSurfTransformSetSessionParams (&space->config_params);
+ if (err != NvBufSurfTransformError_Success) {
+ g_print ("Set session params failed \n");
+ flow_ret = GST_FLOW_ERROR;
+ goto done;
+ }
+
+ switch (space->inbuf_type) {
+ case BUF_TYPE_YUV:
+ case BUF_TYPE_GRAY:
+ case BUF_TYPE_RGB:
+ if ((space->in_pix_fmt == NVBUF_COLOR_FORMAT_GRAY8) &&
+ ((space->out_pix_fmt != NVBUF_COLOR_FORMAT_YUV420) &&
+ (space->out_pix_fmt != NVBUF_COLOR_FORMAT_GRAY8))) {
+ g_print ("%s: Transform not supported \n", __func__);
+ flow_ret = GST_FLOW_ERROR;
+ goto done;
+ }
+
+ if (space->inbuf_memtype == BUF_MEM_HW && space->outbuf_memtype == BUF_MEM_SW) {
+ NvBufSurface *surf = ((NvBufSurface *) inmap.data);
+ NvBufSurface op_surf;
+ NvBufSurfaceParams surfaceList[1];
+ memset (&surfaceList[0], 0, sizeof (NvBufSurfaceParams));
+ op_surf.surfaceList = &surfaceList[0];
+ surface_list_init (space, &op_surf, &outmap, 0);
+
+ /*
+ * If colorimetry is not defined in caps, the format change due to colorimetry difference
+ * is not recognized during caps negotiation. To determine whether to transform or copy,
+ * check the colorFormat difference between the input and output buffers.
+ */
+ if (surf->surfaceList->colorFormat != op_surf.surfaceList->colorFormat)
+ {
+ space->need_intersurf = TRUE;
+ space->isurf_flag = TRUE;
+ }
+
+ if (space->need_intersurf || space->do_scaling || space->flip_method) {
+ if ((space->isurf_flag == TRUE && space->ibuf_count < 1) || space->resolution_changed) {
+ if (space->output_interbuf.isurface) {
+ NvBufSurfaceDestroy(space->output_interbuf.isurface);
+ space->output_interbuf.isurface = NULL;
+ }
+ input_params.params.width = space->to_width;
+ input_params.params.height = space->to_height;
+ input_params.params.layout = NVBUF_LAYOUT_PITCH;
+ input_params.params.colorFormat = space->out_pix_fmt;
+ if (space->compute_hw == NvBufSurfTransformCompute_GPU) {
+ input_params.params.gpuId = space->gpu_id;
+ input_params.params.memType = space->nvbuf_mem_type;
+ } else {
+ input_params.params.memType = NVBUF_MEM_SURFACE_ARRAY;
+ }
+ input_params.memtag = NvBufSurfaceTag_VIDEO_CONVERT;
+
+ retn = NvBufSurfaceAllocate(&space->output_interbuf.isurface, 1, &input_params);
+ if (retn != 0) {
+ GST_ERROR ("%s: intermediate NvBufSurfaceAllocate Failed \n", __func__);
+ flow_ret = GST_FLOW_ERROR;
+ goto done;
+ }
+ space->output_interbuf.isurface->numFilled = 1;
+ space->output_interbuf.idmabuf_fd = space->output_interbuf.isurface->surfaceList[0].bufferDesc;
+
+ space->ibuf_count += 1;
+ space->isurf_flag = FALSE;
+ }
+
+ retn = NvBufSurfTransform (surf, space->output_interbuf.isurface, &space->transform_params);
+ if (retn != 0) {
+ g_print ("%s: NvBufSurfTransform Failed \n", __func__);
+ flow_ret = GST_FLOW_ERROR;
+ goto done;
+ }
+
+ NvBufSurfaceCopy (space->output_interbuf.isurface, &op_surf);
+
+ } else {
+ NvBufSurfaceCopy (surf, &op_surf);
+ }
+ } else if (space->inbuf_memtype == BUF_MEM_SW && space->outbuf_memtype == BUF_MEM_HW) {
+ NvBufSurface *op_surf = (NvBufSurface *) outmap.data;
+ NvBufSurface ip_surf;
+ NvBufSurfaceParams surfaceList[1];
+ memset (&surfaceList[0], 0, sizeof (NvBufSurfaceParams));
+ ip_surf.surfaceList = &surfaceList[0];
+ surface_list_init (space, &ip_surf, &inmap, 1);
+
+ /*
+ * If colorimetry is not defined in caps, the format change due to colorimetry difference
+ * is not recognized during caps negotiation. To determine whether to transform or copy,
+ * check the colorFormat difference between the input and output buffers.
+ */
+ if (ip_surf.surfaceList->colorFormat != op_surf->surfaceList->colorFormat)
+ {
+ space->need_intersurf = TRUE;
+ space->isurf_flag = TRUE;
+ }
+ if (space->need_intersurf || space->do_scaling || space->flip_method) {
+ if ((space->isurf_flag == TRUE && space->ibuf_count < 1) || space->resolution_changed) {
+ if (space->input_interbuf.isurface) {
+ NvBufSurfaceDestroy(space->input_interbuf.isurface);
+ space->input_interbuf.isurface = NULL;
+ }
+ /* TODO : Check for PayloadInfo.TimeStamp = gst_util_uint64_scale (GST_BUFFER_PTS (inbuf), GST_MSECOND * 10, GST_SECOND); */
+ input_params.params.width = space->from_width;
+ input_params.params.height = space->from_height;
+ input_params.params.layout = NVBUF_LAYOUT_PITCH;
+ input_params.params.colorFormat = space->in_pix_fmt;
+ if (space->compute_hw == NvBufSurfTransformCompute_GPU) {
+ input_params.params.gpuId = space->gpu_id;
+ input_params.params.memType = space->nvbuf_mem_type;
+ } else {
+ input_params.params.memType = NVBUF_MEM_SURFACE_ARRAY;
+ }
+ input_params.memtag = NvBufSurfaceTag_VIDEO_CONVERT;
+
+ retn = NvBufSurfaceAllocate(&space->input_interbuf.isurface, 1, &input_params);
+ if (retn != 0) {
+ GST_ERROR ("%s: intermediate NvBufSurfaceAllocate Failed \n", __func__);
+ flow_ret = GST_FLOW_ERROR;
+ goto done;
+ }
+ space->input_interbuf.isurface->numFilled = 1;
+ space->input_interbuf.idmabuf_fd = space->input_interbuf.isurface->surfaceList[0].bufferDesc;
+
+ space->isurf_flag = FALSE;
+ space->ibuf_count += 1;
+ }
+
+ NvBufSurfaceCopy (&ip_surf, space->input_interbuf.isurface);
+
+ retn = NvBufSurfTransform (space->input_interbuf.isurface, op_surf, &space->transform_params);
+ if (retn != 0) {
+ g_print ("%s: NvBufSurfTransform Failed \n", __func__);
+ flow_ret = GST_FLOW_ERROR;
+ goto done;
+ }
+
+ /*
+ * Ideally this should not be required at application level
+ * but keeping it for VIC due to legacy code
+ */
+ if (space->compute_hw == NvBufSurfTransformCompute_VIC) {
+ if ((space->in_pix_fmt == NVBUF_COLOR_FORMAT_GRAY8) &&
+ (space->out_pix_fmt == NVBUF_COLOR_FORMAT_YUV420)) {
+ ret = gst_nvvconv_do_clearchroma (space, omem->buf->surface);
+ if (ret != TRUE) {
+ GST_ERROR ("%s: Clear chroma failed \n", __func__);
+ flow_ret = GST_FLOW_ERROR;
+ goto done;
+ }
+ }
+ }
+ } else {
+ NvBufSurfaceCopy (&ip_surf, op_surf);
+ op_surf->numFilled = 1;
+ }
+ } else if (space->inbuf_memtype == BUF_MEM_HW && space->outbuf_memtype == BUF_MEM_HW) {
+ NvBufSurface *surf = ((NvBufSurface *) inmap.data);
+ if (!surf) {
+ flow_ret = GST_FLOW_ERROR;
+ goto done;
+ }
+ /* TODO : Check for PayloadInfo.TimeStamp = gst_util_uint64_scale (GST_BUFFER_PTS (inbuf), GST_MSECOND * 10, GST_SECOND); */
+
+ /*
+ * If colorimetry is not defined in caps, the format change due to colorimetry difference
+ * is not recognized during caps negotiation. To determine whether to transform or copy,
+ * check the colorFormat difference between the input and output buffers.
+ */
+ if (surf->surfaceList->colorFormat != omem->buf->surface->surfaceList->colorFormat)
+ {
+ space->need_intersurf = TRUE;
+ space->isurf_flag = TRUE;
+ }
+ if (space->need_intersurf || space->do_scaling || space->flip_method ||
+ surf->surfaceList->layout != omem->buf->surface->surfaceList->layout) {
+ retn = NvBufSurfTransform (surf, omem->buf->surface, &space->transform_params);
+ if (retn != 0) {
+ g_print ("%s: NvBufSurfTransform Failed \n", __func__);
+ flow_ret = GST_FLOW_ERROR;
+ goto done;
+ }
+
+ /*
+ * Ideally this should not be required at application level
+ * but keeping it for VIC due to legacy code
+ */
+ if (space->compute_hw == NvBufSurfTransformCompute_VIC) {
+ if ((space->in_pix_fmt == NVBUF_COLOR_FORMAT_GRAY8) &&
+ (space->out_pix_fmt == NVBUF_COLOR_FORMAT_YUV420)) {
+ ret = gst_nvvconv_do_clearchroma (space, omem->buf->surface);
+ if (ret != TRUE) {
+ GST_ERROR ("%s: Clear chroma failed \n", __func__);
+ flow_ret = GST_FLOW_ERROR;
+ goto done;
+ }
+ }
+ }
+ } else {
+ NvBufSurfaceCopy (surf, omem->buf->surface);
+ }
+ } else if (space->inbuf_memtype == BUF_MEM_SW && space->outbuf_memtype == BUF_MEM_SW) {
+ /* input surface initialisations */
+ NvBufSurface ip_surf;
+ NvBufSurfaceParams surfaceListIp;
+ memset (&surfaceListIp, 0, sizeof (surfaceListIp));
+ ip_surf.surfaceList = &surfaceListIp;
+ surface_list_init (space, &ip_surf, &inmap, 1);
+
+ /* output surface initialisations */
+ NvBufSurface op_surf;
+ NvBufSurfaceParams surfaceListOp;
+ memset (&surfaceListOp, 0, sizeof (surfaceListOp));
+ op_surf.surfaceList = &surfaceListOp;
+ surface_list_init (space, &op_surf, &outmap, 0);
+
+ /*
+ * If colorimetry is not defined in caps, the format change due to colorimetry difference
+ * is not recognized during caps negotiation. To determine whether to transform or copy,
+ * check the colorFormat difference between the input and output buffers.
+ */
+ if (ip_surf.surfaceList->colorFormat != op_surf.surfaceList->colorFormat)
+ {
+ space->need_intersurf = TRUE;
+ space->isurf_flag = TRUE;
+ }
+ if (space->need_intersurf || space->do_scaling || space->flip_method) {
+ if (space->isurf_flag == TRUE) {
+
+ NvBufSurfaceAllocateParams input_params = { 0 };
+
+ if (space->ibuf_count < 1 || space->resolution_changed) {
+ if (space->input_interbuf.isurface) {
+ NvBufSurfaceDestroy(space->input_interbuf.isurface);
+ space->input_interbuf.isurface = NULL;
+ }
+ input_params.params.width = space->from_width;
+ input_params.params.height = space->from_height;
+ input_params.params.layout = NVBUF_LAYOUT_PITCH;
+ input_params.params.colorFormat = space->in_pix_fmt;
+ if (space->compute_hw == NvBufSurfTransformCompute_GPU) {
+ input_params.params.gpuId = space->gpu_id;
+ input_params.params.memType = space->nvbuf_mem_type;
+ } else {
+ input_params.params.memType = NVBUF_MEM_SURFACE_ARRAY;
+ }
+ input_params.memtag = NvBufSurfaceTag_VIDEO_CONVERT;
+
+ retn = NvBufSurfaceAllocate(&space->input_interbuf.isurface, 1, &input_params);
+ if (retn != 0) {
+ GST_ERROR ("%s: intermediate NvBufSurfaceAllocate Failed \n", __func__);
+ flow_ret = GST_FLOW_ERROR;
+ goto done;
+ }
+ space->input_interbuf.isurface->numFilled = 1;
+ space->input_interbuf.idmabuf_fd = space->input_interbuf.isurface->surfaceList[0].bufferDesc;
+
+ space->ibuf_count += 1;
+ }
+
+ if (space->ibuf_count < 2 || space->resolution_changed) {
+ if (space->output_interbuf.isurface) {
+ NvBufSurfaceDestroy(space->output_interbuf.isurface);
+ space->output_interbuf.isurface = NULL;
+ }
+ input_params.params.width = space->to_width;
+ input_params.params.height = space->to_height;
+ input_params.params.layout = NVBUF_LAYOUT_PITCH;
+ input_params.params.colorFormat = space->out_pix_fmt;
+ if (space->compute_hw == NvBufSurfTransformCompute_GPU) {
+ input_params.params.gpuId = space->gpu_id;
+ input_params.params.memType = space->nvbuf_mem_type;
+ } else {
+ input_params.params.memType = NVBUF_MEM_SURFACE_ARRAY;
+ }
+ input_params.memtag = NvBufSurfaceTag_VIDEO_CONVERT;
+
+ retn = NvBufSurfaceAllocate(&space->output_interbuf.isurface, 1, &input_params);
+ if (retn != 0) {
+ GST_ERROR ("%s: intermediate NvBufSurfaceAllocate Failed \n", __func__);
+ flow_ret = GST_FLOW_ERROR;
+ goto done;
+ }
+ space->output_interbuf.isurface->numFilled = 1;
+ space->output_interbuf.idmabuf_fd = space->output_interbuf.isurface->surfaceList[0].bufferDesc;
+
+ space->ibuf_count += 1;
+ }
+
+ space->isurf_flag = FALSE;
+ }
+
+ NvBufSurfaceCopy (&ip_surf, space->input_interbuf.isurface);
+
+ retn = NvBufSurfTransform (space->input_interbuf.isurface, space->output_interbuf.isurface, &space->transform_params);
+ if (retn != 0) {
+ g_print ("%s: NvBufSurfTransform Failed \n", __func__);
+ flow_ret = GST_FLOW_ERROR;
+ goto done;
+ }
+
+ NvBufSurfaceCopy (space->output_interbuf.isurface, &op_surf);
+
+ } else {
+ NvBufSurfaceCopy (&ip_surf, &op_surf);
+ }
+ } else {
+ flow_ret = GST_FLOW_ERROR;
+ goto done;
+ }
+ break;
+
+ default:
+ GST_ERROR ("%s: Unsupported input buffer \n", __func__);
+ flow_ret = GST_FLOW_ERROR;
+ goto done;
+ break;
+ }
+
+done:
+ gst_buffer_unmap (inbuf, &inmap);
+ gst_buffer_unmap (outbuf, &outmap);
+ space->resolution_changed = FALSE;
+
+ return flow_ret;
+
+ /* ERRORS */
+no_memory:
+ {
+ GST_ERROR ("no memory block");
+ return GST_FLOW_ERROR;
+ }
+unknown_format:
+ {
+ GST_ERROR ("unknown format");
+ return GST_FLOW_NOT_NEGOTIATED;
+ }
+invalid_inbuf:
+ {
+ GST_ERROR ("input buffer mapinfo failed");
+ return GST_FLOW_ERROR;
+ }
+invalid_outbuf:
+ {
+ GST_ERROR ("output buffer mapinfo failed");
+ gst_buffer_unmap (inbuf, &inmap);
+ return GST_FLOW_ERROR;
+ }
+cuda_errors:
+ {
+ gst_buffer_unmap (inbuf, &inmap);
+ gst_buffer_unmap (outbuf, &outmap);
+ return GST_FLOW_ERROR;
+ }
+}
+
+/**
+ * nvvconv plugin init.
+ *
+ * @param nvvconv : plugin instance
+ */
+static gboolean
+nvvconv_init (GstPlugin * nvvconv)
+{
+ int result = -1;
+
+ result = (gboolean)system("lsmod | grep 'nvgpu' > /dev/null");
+ if (result == 0) {
+ is_nvgpu = TRUE;
+ } else {
+ is_nvgpu = FALSE;
+ }
+
+ GST_DEBUG_CATEGORY_INIT (gst_nvvconv_debug, "nvvidconv",
+ 0, "nvvidconv plugin");
+
+ return gst_element_register (nvvconv, "nvvidconv", GST_RANK_PRIMARY,
+ GST_TYPE_NVVCONV);
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ nvvidconv,
+ PACKAGE_DESCRIPTION,
+ nvvconv_init, VERSION, PACKAGE_LICENSE, PACKAGE_NAME, PACKAGE_URL)
diff --git a/gst-nvvidconv/gstnvvconv.h b/gst-nvvidconv/gstnvvconv.h
new file mode 100644
index 0000000..e575f75
--- /dev/null
+++ b/gst-nvvidconv/gstnvvconv.h
@@ -0,0 +1,239 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2014-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GST_NVVCONV_H__
+#define __GST_NVVCONV_H__
+
+#include
+#include
+#include
+
+#include "nvbufsurface.h"
+#include "nvbufsurftransform.h"
+
+#include
+#include
+
+G_BEGIN_DECLS
+#define GST_TYPE_NVVCONV \
+ (gst_nvvconv_get_type())
+#define GST_NVVCONV(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NVVCONV,Gstnvvconv))
+#define GST_NVVCONV_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NVVCONV,GstnvvconvClass))
+#define GST_IS_NVVCONV(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NVVCONV))
+#define GST_IS_NVVCONV_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NVVCONV))
+
+/* Name of package */
+#define PACKAGE "gstreamer-nvvconv-plugin"
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "GStreamer nvvconv Plugin"
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "GStreamer nvvconv 1.2.3"
+/* Information about the purpose of the plugin. */
+#define PACKAGE_DESCRIPTION "video Colorspace conversion & scaler"
+/* Define to the home page for this package. */
+#define PACKAGE_URL "http://nvidia.com/"
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.2.3"
+/* Define under which licence the package has been released */
+#define PACKAGE_LICENSE "Proprietary"
+/* Version number of package */
+#define VERSION "1.2.3"
+
+#define NVRM_MAX_SURFACES 3
+#define NVFILTER_MAX_BUF 4
+#define GST_CAPS_FEATURE_MEMORY_NVMM "memory:NVMM"
+
+typedef struct _Gstnvvconv Gstnvvconv;
+typedef struct _GstnvvconvClass GstnvvconvClass;
+
+typedef struct _GstNvvConvBuffer GstNvvConvBuffer;
+typedef struct _GstNvInterBuffer GstNvInterBuffer;
+
+/**
+ * BufType:
+ *
+ * Buffer type enum.
+ */
+typedef enum
+{
+ BUF_TYPE_YUV,
+ BUF_TYPE_GRAY,
+ BUF_TYPE_RGB,
+ BUF_NOT_SUPPORTED
+} BufType;
+
+/**
+ * BufMemType:
+ *
+ * Buffer memory type enum.
+ */
+typedef enum
+{
+ BUF_MEM_SW,
+ BUF_MEM_HW
+} BufMemType;
+
+/**
+ * GstVideoFlipMethods:
+ *
+ * Video flip methods type enum.
+ */
+typedef enum
+{
+ GST_VIDEO_NVFLIP_METHOD_IDENTITY,
+ GST_VIDEO_NVFLIP_METHOD_90L,
+ GST_VIDEO_NVFLIP_METHOD_180,
+ GST_VIDEO_NVFLIP_METHOD_90R,
+ GST_VIDEO_NVFLIP_METHOD_HORIZ,
+ GST_VIDEO_NVFLIP_METHOD_INVTRANS,
+ GST_VIDEO_NVFLIP_METHOD_VERT,
+ GST_VIDEO_NVFLIP_METHOD_TRANS
+} GstVideoFlipMethods;
+
+/**
+ * GstInterpolationMethods:
+ *
+ * Interpolation methods type enum.
+ */
+typedef enum
+{
+ GST_INTERPOLATION_NEAREST,
+ GST_INTERPOLATION_BILINEAR,
+ GST_INTERPOLATION_5_TAP,
+ GST_INTERPOLATION_10_TAP,
+ GST_INTERPOLATION_SMART,
+ GST_INTERPOLATION_NICEST,
+} GstInterpolationMethods;
+
+/**
+ * GstNvvConvBuffer:
+ *
+ * Nvfilter buffer.
+ */
+struct _GstNvvConvBuffer
+{
+ gint dmabuf_fd;
+ GstBuffer *gst_buf;
+ NvBufSurface *surface;
+};
+
+/**
+ * GstNvInterBuffer:
+ *
+ * Intermediate transform buffer.
+ */
+struct _GstNvInterBuffer
+{
+ gint idmabuf_fd;
+ NvBufSurface *isurface;
+};
+
+/**
+ * Gstnvvconv:
+ *
+ * Opaque object data structure.
+ */
+struct _Gstnvvconv
+{
+ GstBaseTransform element;
+
+ /* source and sink pad caps */
+ GstCaps *sinkcaps;
+ GstCaps *srccaps;
+
+ gint to_width;
+ gint to_height;
+ gint from_width;
+ gint from_height;
+ gint tsurf_width;
+ gint tsurf_height;
+
+ gint crop_left;
+ gint crop_right;
+ gint crop_top;
+ gint crop_bottom;
+
+ BufType inbuf_type;
+ BufMemType inbuf_memtype;
+ BufMemType outbuf_memtype;
+
+ NvBufSurfTransformParams transform_params;
+ NvBufSurfaceColorFormat in_pix_fmt;
+ NvBufSurfaceColorFormat out_pix_fmt;
+ NvBufSurfTransformRect src_rect;
+
+ guint insurf_count;
+ guint tsurf_count;
+ guint isurf_count;
+ guint ibuf_count;
+ gint flip_method;
+ guint num_output_buf;
+ gint interpolation_method;
+
+ gboolean silent;
+ gboolean no_dimension;
+ gboolean do_scaling;
+ gboolean do_flip;
+ gboolean do_cropping;
+ gboolean need_intersurf;
+ gboolean isurf_flag;
+ gboolean negotiated;
+ gboolean nvfilterpool;
+ gboolean enable_blocklinear_output;
+ gboolean resolution_changed;
+
+ GstBufferPool *pool;
+ GMutex flow_lock;
+
+ GstNvInterBuffer input_interbuf;
+ GstNvInterBuffer output_interbuf;
+
+ gint compute_hw;
+ gint gpu_id;
+ gint nvbuf_mem_type;
+ guint session_created;
+ GstVideoInfo in_info;
+ GstVideoInfo out_info;
+ NvBufSurfTransformConfigParams config_params;
+};
+
+struct _GstnvvconvClass
+{
+ GstBaseTransformClass parent_class;
+};
+
+GType gst_nvvconv_get_type (void);
+
+G_END_DECLS
+#endif /* __GST_NVVCONV_H__ */
diff --git a/gst-nvvidconv/nvbufsurface.h b/gst-nvvidconv/nvbufsurface.h
new file mode 100644
index 0000000..56349f8
--- /dev/null
+++ b/gst-nvvidconv/nvbufsurface.h
@@ -0,0 +1,1075 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2019-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ * SPDX-License-Identifier: LicenseRef-NvidiaProprietary
+ *
+ * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
+ * property and proprietary rights in and to this material, related
+ * documentation and any modifications thereto. Any use, reproduction,
+ * disclosure or distribution of this material and related documentation
+ * without an express license agreement from NVIDIA CORPORATION or
+ * its affiliates is strictly prohibited.
+ */
+
+/**
+ * @file nvbufsurface.h
+ * NvBufSurface Interface
+ *
+ * This file specifies the NvBufSurface management API.
+ *
+ * The NvBufSurface API provides methods to allocate / deallocate, map / unmap
+ * and copy batched buffers.
+ */
+ /**
+ * @defgroup ds_nvbuf_api Buffer Management API module
+ *
+ * This section describes types and functions of NvBufSurface application
+ * programming interface.
+ *
+ */
+
+#ifndef NVBUFSURFACE_H_
+#define NVBUFSURFACE_H_
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/** @defgroup ds_aaa NvBufSurface Types and Functions
+ * Defines types and functions of \ref NvBufSurface application
+ * programming interface.
+ * @ingroup ds_nvbuf_api
+ * @{ */
+
+/** Defines the default padding length for reserved fields of structures. */
+#define STRUCTURE_PADDING 4
+
+/** Defines the maximum number of planes. */
+#define NVBUF_MAX_PLANES 4
+
+/**
+ * Defines the default values for chroma subsampling.
+ * The default value matches JPEG/MPEG use cases.
+ */
+#define NVBUFSURFACE_CHROMA_SUBSAMPLING_HORIZ_DEFAULT 0
+#define NVBUFSURFACE_CHROMA_SUBSAMPLING_VERT_DEFAULT 1
+
+#define NVBUFSURFACE_CHROMA_SUBSAMPLING_PARAMS_DEFAULT \
+ { \
+ NVBUFSURFACE_CHROMA_SUBSAMPLING_HORIZ_DEFAULT, \
+ NVBUFSURFACE_CHROMA_SUBSAMPLING_VERT_DEFAULT \
+ }
+
+/**
+ * Defines mapping types of NvBufSurface.
+ */
+typedef enum
+{
+ NVBUF_MAP_READ, /**< Specifies \ref NvBufSurface mapping type "read." */
+ NVBUF_MAP_WRITE, /**< Specifies \ref NvBufSurface mapping type
+ "write." */
+ NVBUF_MAP_READ_WRITE, /**< Specifies \ref NvBufSurface mapping type
+ "read/write." */
+} NvBufSurfaceMemMapFlags;
+
+/**
+ * Defines tags that identify the components requesting a memory allocation.
+ * The tags can be used later to identify the total memory allocated to
+ * particular types of components.
+ * TODO: Check if DeepStream require more tags to be defined.
+ */
+typedef enum
+{
+ /** tag None. */
+ NvBufSurfaceTag_NONE = 0x0,
+ /** tag for Camera. */
+ NvBufSurfaceTag_CAMERA = 0x200,
+ /** tag for Jpeg Encoder/Decoder. */
+ NvBufSurfaceTag_JPEG = 0x1500,
+ /** tag for VPR Buffers. */
+ NvBufSurfaceTag_PROTECTED = 0x1504,
+ /** tag for H264/H265 Video Encoder. */
+ NvBufSurfaceTag_VIDEO_ENC = 0x1200,
+ /** tag for H264/H265/VP9 Video Decoder. */
+ NvBufSurfaceTag_VIDEO_DEC = 0x1400,
+ /** tag for Video Transform/Composite/Blend. */
+ NvBufSurfaceTag_VIDEO_CONVERT = 0xf01,
+} NvBufSurfaceTag;
+
+/**
+ * Defines color formats for NvBufSurface.
+ */
+typedef enum
+{
+ /** Specifies an invalid color format. */
+ NVBUF_COLOR_FORMAT_INVALID,
+ /** Specifies 8 bit GRAY scale - single plane */
+ NVBUF_COLOR_FORMAT_GRAY8,
+ /** Specifies BT.601 colorspace - YUV420 multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV420,
+ /** Specifies BT.601 colorspace - YUV420 multi-planar. */
+ NVBUF_COLOR_FORMAT_YVU420,
+ /** Specifies BT.601 colorspace - YUV420 ER multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV420_ER,
+ /** Specifies BT.601 colorspace - YVU420 ER multi-planar. */
+ NVBUF_COLOR_FORMAT_YVU420_ER,
+ /** Specifies BT.601 colorspace - Y/CbCr 4:2:0 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV12,
+ /** Specifies BT.601 colorspace - Y/CbCr ER 4:2:0 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV12_ER,
+ /** Specifies BT.601 colorspace - Y/CbCr 4:2:0 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV21,
+ /** Specifies BT.601 colorspace - Y/CbCr ER 4:2:0 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV21_ER,
+ /** Specifies BT.601 colorspace - YUV 4:2:2 planar. */
+ NVBUF_COLOR_FORMAT_UYVY,
+ /** Specifies BT.601 colorspace - YUV ER 4:2:2 planar. */
+ NVBUF_COLOR_FORMAT_UYVY_ER,
+ /** Specifies BT.601 colorspace - YUV 4:2:2 planar. */
+ NVBUF_COLOR_FORMAT_VYUY,
+ /** Specifies BT.601 colorspace - YUV ER 4:2:2 planar. */
+ NVBUF_COLOR_FORMAT_VYUY_ER,
+ /** Specifies BT.601 colorspace - YUV 4:2:2 planar. */
+ NVBUF_COLOR_FORMAT_YUYV,
+ /** Specifies BT.601 colorspace - YUV ER 4:2:2 planar. */
+ NVBUF_COLOR_FORMAT_YUYV_ER,
+ /** Specifies BT.601 colorspace - YUV 4:2:2 planar. */
+ NVBUF_COLOR_FORMAT_YVYU,
+ /** Specifies BT.601 colorspace - YUV ER 4:2:2 planar. */
+ NVBUF_COLOR_FORMAT_YVYU_ER,
+ /** Specifies BT.601 colorspace - YUV444 multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV444,
+ /** Specifies RGBA-8-8-8-8 single plane. */
+ NVBUF_COLOR_FORMAT_RGBA,
+ /** Specifies BGRA-8-8-8-8 single plane. */
+ NVBUF_COLOR_FORMAT_BGRA,
+ /** Specifies ARGB-8-8-8-8 single plane. */
+ NVBUF_COLOR_FORMAT_ARGB,
+ /** Specifies ABGR-8-8-8-8 single plane. */
+ NVBUF_COLOR_FORMAT_ABGR,
+ /** Specifies RGBx-8-8-8-8 single plane. */
+ NVBUF_COLOR_FORMAT_RGBx,
+ /** Specifies BGRx-8-8-8-8 single plane. */
+ NVBUF_COLOR_FORMAT_BGRx,
+ /** Specifies xRGB-8-8-8-8 single plane. */
+ NVBUF_COLOR_FORMAT_xRGB,
+ /** Specifies xBGR-8-8-8-8 single plane. */
+ NVBUF_COLOR_FORMAT_xBGR,
+ /** Specifies RGB-8-8-8 single plane. */
+ NVBUF_COLOR_FORMAT_RGB,
+ /** Specifies BGR-8-8-8 single plane. */
+ NVBUF_COLOR_FORMAT_BGR,
+ /** Specifies BT.601 colorspace - Y/CbCr 4:2:0 10-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_NV12_10LE,
+ /** Specifies BT.601 colorspace - Y/CbCr 4:2:0 12-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_NV12_12LE,
+ /** Specifies BT.709 colorspace - YUV420 multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV420_709,
+ /** Specifies BT.709 colorspace - YUV420 ER multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV420_709_ER,
+ /** Specifies BT.709 colorspace - Y/CbCr 4:2:0 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV12_709,
+ /** Specifies BT.709 colorspace - Y/CbCr ER 4:2:0 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV12_709_ER,
+ /** Specifies BT.2020 colorspace - YUV420 multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV420_2020,
+ /** Specifies BT.2020 colorspace - Y/CbCr 4:2:0 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV12_2020,
+ /** Specifies BT.601 colorspace - Y/CbCr ER 4:2:0 10-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_NV12_10LE_ER,
+ /** Specifies BT.709 colorspace - Y/CbCr 4:2:0 10-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_NV12_10LE_709,
+ /** Specifies BT.709 colorspace - Y/CbCr ER 4:2:0 10-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_NV12_10LE_709_ER,
+ /** Specifies BT.2020 colorspace - Y/CbCr 4:2:0 10-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_NV12_10LE_2020,
+ /** Specifies color format for packed 2 signed shorts */
+ NVBUF_COLOR_FORMAT_SIGNED_R16G16,
+ /** Specifies RGB- unsigned 8 bit multiplanar plane. */
+ NVBUF_COLOR_FORMAT_R8_G8_B8,
+ /** Specifies BGR- unsigned 8 bit multiplanar plane. */
+ NVBUF_COLOR_FORMAT_B8_G8_R8,
+ /** Specifies RGB-32bit Floating point multiplanar plane. */
+ NVBUF_COLOR_FORMAT_R32F_G32F_B32F,
+ /** Specifies BGR-32bit Floating point multiplanar plane. */
+ NVBUF_COLOR_FORMAT_B32F_G32F_R32F,
+ /** Specifies BT.601 colorspace - YUV422 multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV422,
+ /** Specifies BT.601 colorspace - Y/CrCb 4:2:0 10-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_NV21_10LE,
+ /** Specifies BT.601 colorspace - Y/CrCb 4:2:0 12-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_NV21_12LE,
+ /** Specifies BT.2020 colorspace - Y/CbCr 4:2:0 12-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_NV12_12LE_2020,
+ /** Specifies BT.601 colorspace - Y/CbCr 4:2:2 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV16,
+ /** Specifies BT.601 colorspace - Y/CbCr 4:2:2 10-bit semi-planar. */
+ NVBUF_COLOR_FORMAT_NV16_10LE,
+ /** Specifies BT.601 colorspace - Y/CbCr 4:4:4 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV24,
+ /** Specifies BT.601 colorspace - Y/CrCb 4:4:4 10-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_NV24_10LE,
+ /** Specifies BT.601_ER colorspace - Y/CbCr 4:2:2 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV16_ER,
+ /** Specifies BT.601_ER colorspace - Y/CbCr 4:4:4 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV24_ER,
+ /** Specifies BT.709 colorspace - Y/CbCr 4:2:2 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV16_709,
+ /** Specifies BT.709 colorspace - Y/CbCr 4:4:4 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV24_709,
+ /** Specifies BT.709_ER colorspace - Y/CbCr 4:2:2 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV16_709_ER,
+ /** Specifies BT.709_ER colorspace - Y/CbCr 4:4:4 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV24_709_ER,
+ /** Specifies BT.709 colorspace - Y/CbCr 10 bit 4:4:4 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV24_10LE_709,
+ /** Specifies BT.709 ER colorspace - Y/CbCr 10 bit 4:4:4 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV24_10LE_709_ER,
+ /** Specifies BT.2020 colorspace - Y/CbCr 10 bit 4:4:4 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV24_10LE_2020,
+ /** Specifies BT.2020 colorspace - Y/CbCr 12 bit 4:4:4 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV24_12LE_2020,
+ /** Specifies Non-linear RGB BT.709 colorspace - RGBA-10-10-10-2 planar. */
+ NVBUF_COLOR_FORMAT_RGBA_10_10_10_2_709,
+ /** Specifies Non-linear RGB BT.2020 colorspace - RGBA-10-10-10-2 planar. */
+ NVBUF_COLOR_FORMAT_RGBA_10_10_10_2_2020,
+ /** Specifies Non-linear RGB BT.709 colorspace - BGRA-10-10-10-2 planar. */
+ NVBUF_COLOR_FORMAT_BGRA_10_10_10_2_709,
+ /** Specifies Non-linear RGB BT.2020 colorspace - BGRA-10-10-10-2 planar. */
+ NVBUF_COLOR_FORMAT_BGRA_10_10_10_2_2020,
+ /** Specifies Optical flow SAD calculation Buffer format */
+ NVBUF_COLOR_FORMAT_A32,
+ /** Specifies BT.601 colorspace - 10 bit YUV 4:2:2 interleaved. */
+ NVBUF_COLOR_FORMAT_UYVP,
+ /** Specifies BT.601 colorspace - 10 bit YUV ER 4:2:2 interleaved. */
+ NVBUF_COLOR_FORMAT_UYVP_ER,
+ /** Specifies BT.601 colorspace - Y/CbCr ER 4:4:4 multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV444_ER,
+ /** Specifies BT.709 colorspace - Y/CbCr 4:4:4 multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV444_709,
+ /** Specifies BT.709 colorspace - Y/CbCr ER 4:4:4 multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV444_709_ER,
+ /** Specifies BT.2020 colorspace - Y/CbCr 4:4:4 multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV444_2020,
+ /** Specifies BT.601 colorspace - Y/CbCr 4:4:4 10-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV444_10LE,
+ /** Specifies BT.601 colorspace - Y/CbCr ER 4:4:4 10-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV444_10LE_ER,
+ /** Specifies BT.709 colorspace - Y/CbCr 4:4:4 10-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV444_10LE_709,
+ /** Specifies BT.709 colorspace - Y/CbCr ER 4:4:4 10-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV444_10LE_709_ER,
+ /** Specifies BT.2020 colorspace - Y/CbCr 4:4:4 10-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV444_10LE_2020,
+ /** Specifies BT.601 colorspace - Y/CbCr 4:4:4 12-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV444_12LE,
+ /** Specifies BT.601 colorspace - Y/CbCr ER 4:4:4 12-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV444_12LE_ER,
+ /** Specifies BT.709 colorspace - Y/CbCr 4:4:4 12-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV444_12LE_709,
+ /** Specifies BT.709 colorspace - Y/CbCr ER 4:4:4 12-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV444_12LE_709_ER,
+ /** Specifies BT.2020 colorspace - Y/CbCr 4:4:4 12-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_YUV444_12LE_2020,
+ /** Specifies BT.601 colorspace - Y/CbCr ER 4:2:0 12-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_NV12_12LE_ER,
+ /** Specifies BT.709 colorspace - Y/CbCr 4:2:0 12-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_NV12_12LE_709,
+ /** Specifies BT.709 colorspace - Y/CbCr ER 4:2:0 12-bit multi-planar. */
+ NVBUF_COLOR_FORMAT_NV12_12LE_709_ER,
+ /** Specifies 8 bit GRAY scale ER - single plane */
+ NVBUF_COLOR_FORMAT_GRAY8_ER,
+ /** Specifies BT.709 colorspace - Y/CbCr 4:2:2 planar */
+ NVBUF_COLOR_FORMAT_UYVY_709,
+ /** Specifies BT.709 colorspace - Y/CbCr ER 4:2:2 planar */
+ NVBUF_COLOR_FORMAT_UYVY_709_ER,
+ /** Specifies BT.2020 colorspace - Y/CbCr 4:2:2 planar */
+ NVBUF_COLOR_FORMAT_UYVY_2020,
+ /** Specifies 16 bit GRAY scale - single plane */
+ NVBUF_COLOR_FORMAT_GRAY16_LE,
+ /** Specifies 64 bit BGRA (B16 G16 R16 A16) interleaved */
+ NVBUF_COLOR_FORMAT_BGRA64_LE,
+ /** Specifies BT.2020 colorspace - Y/CbCr 4:2:2 multi-planar. */
+ NVBUF_COLOR_FORMAT_NV16_2020,
+ /** Specifies BT.601_ER colorspace - Y/CbCr 4:2:2 10-bit semi-planar. */
+ NVBUF_COLOR_FORMAT_NV16_10LE_ER,
+ /** Specifies BT.709 colorspace - Y/CbCr 4:2:2 10-bit semi-planar. */
+ NVBUF_COLOR_FORMAT_NV16_10LE_709,
+ /** Specifies BT.709_ER colorspace - Y/CbCr 4:2:2 10-bit semi-planar. */
+ NVBUF_COLOR_FORMAT_NV16_10LE_709_ER,
+ /** Specifies BT.2020 colorspace - Y/CbCr 4:2:2 10-bit semi-planar. */
+ NVBUF_COLOR_FORMAT_NV16_10LE_2020,
+ /** Specifies BT.601 colorspace - Y/CbCr 4:2:2 12-bit semi-planar. */
+ NVBUF_COLOR_FORMAT_NV16_12LE,
+ /** Specifies BT.601_ER colorspace - Y/CbCr 4:2:2 12-bit semi-planar. */
+ NVBUF_COLOR_FORMAT_NV16_12LE_ER,
+ /** Specifies BT.709 colorspace - Y/CbCr 4:2:2 12-bit semi-planar. */
+ NVBUF_COLOR_FORMAT_NV16_12LE_709,
+ /** Specifies BT.709_ER colorspace - Y/CbCr 4:2:2 12-bit semi-planar. */
+ NVBUF_COLOR_FORMAT_NV16_12LE_709_ER,
+ /** Specifies BT.2020 colorspace - Y/CbCr 4:2:2 12-bit semi-planar. */
+ NVBUF_COLOR_FORMAT_NV16_12LE_2020,
+ NVBUF_COLOR_FORMAT_LAST
+} NvBufSurfaceColorFormat;
+
+/**
+ * Specifies layout formats for \ref NvBufSurface video planes.
+ */
+typedef enum
+{
+ /** Specifies pitch layout. */
+ NVBUF_LAYOUT_PITCH,
+ /** Specifies block linear layout. */
+ NVBUF_LAYOUT_BLOCK_LINEAR,
+} NvBufSurfaceLayout;
+
+/**
+ * Specifies memory types for \ref NvBufSurface.
+ */
+typedef enum
+{
+ /** Specifies the default memory type, i.e. \ref NVBUF_MEM_CUDA_DEVICE
+ for dGPU, \ref NVBUF_MEM_SURFACE_ARRAY for Jetson. Use \ref NVBUF_MEM_DEFAULT
+ to allocate whichever type of memory is appropriate for the platform. */
+ NVBUF_MEM_DEFAULT,
+ /** Specifies CUDA Host memory type. */
+ NVBUF_MEM_CUDA_PINNED,
+ /** Specifies CUDA Device memory type. */
+ NVBUF_MEM_CUDA_DEVICE,
+ /** Specifies CUDA Unified memory type. */
+ NVBUF_MEM_CUDA_UNIFIED,
+ /** Specifies NVRM Surface Array type. Valid only for Jetson. */
+ NVBUF_MEM_SURFACE_ARRAY,
+ /** Specifies NVRM Handle type. Valid only for Jetson. */
+ NVBUF_MEM_HANDLE,
+ /** Specifies memory allocated by malloc(). */
+ NVBUF_MEM_SYSTEM,
+} NvBufSurfaceMemType;
+
+/**
+ * Defines display scan formats for NvBufSurface video planes.
+ */
+typedef enum
+{
+ /** Progessive scan formats. */
+ NVBUF_DISPLAYSCANFORMAT_PROGRESSIVE,
+ /** Interlaced scan formats. */
+ NVBUF_DISPLAYSCANFORMAT_INTERLACED,
+} NvBufSurfaceDisplayScanFormat;
+
+/**
+ * Holds plane wise parameters(extended) of a buffer.
+ */
+typedef struct NvBufSurfacePlaneParamsEx
+{
+ /** display scan format - progressive/interlaced. */
+ NvBufSurfaceDisplayScanFormat scanformat[NVBUF_MAX_PLANES];
+ /** offset of the second field for interlaced buffer. */
+ uint32_t secondfieldoffset[NVBUF_MAX_PLANES];
+ /** block height of the planes for blockLinear layout buffer. */
+ uint32_t blockheightlog2[NVBUF_MAX_PLANES];
+ /** physical address of allocated planes. */
+ uint32_t physicaladdress[NVBUF_MAX_PLANES];
+ /** flags associated with planes */
+ uint64_t flags[NVBUF_MAX_PLANES];
+ /** DRM modifier for plane */
+ uint64_t drmModifier[NVBUF_MAX_PLANES];
+ /** Holds the reserved space for future use. */
+ void * _reserved[STRUCTURE_PADDING * NVBUF_MAX_PLANES];
+} NvBufSurfacePlaneParamsEx;
+
+/**
+ * Holds plane wise parameters of a buffer.
+ */
+typedef struct NvBufSurfacePlaneParams
+{
+ /** Holds the number of planes. */
+ uint32_t num_planes;
+ /** Holds the widths of planes. */
+ uint32_t width[NVBUF_MAX_PLANES];
+ /** Holds the heights of planes. */
+ uint32_t height[NVBUF_MAX_PLANES];
+ /** Holds the pitches of planes in bytes. */
+ uint32_t pitch[NVBUF_MAX_PLANES];
+ /** Holds the offsets of planes in bytes. */
+ uint32_t offset[NVBUF_MAX_PLANES];
+ /** Holds the sizes of planes in bytes. */
+ uint32_t psize[NVBUF_MAX_PLANES];
+ /** Holds the number of bytes occupied by a pixel in each plane. */
+ uint32_t bytesPerPix[NVBUF_MAX_PLANES];
+ /** Holds the reserved space for future use. */
+ void * _reserved[STRUCTURE_PADDING * NVBUF_MAX_PLANES];
+} NvBufSurfacePlaneParams;
+
+
+/**
+ * Holds Chroma Subsampling parameters for NvBufSurface allocation.
+ * The members chromaLocHoriz and chromaLocVert accept these values:
+ * 0: Left horizontal or top vertical position
+ * 1: Center horizontal or center vertical position
+ * 2: Right horizontal or bottom vertical position
+ */
+typedef struct NvBufSurfaceChromaSubsamplingParams
+{
+ /** location settings */
+ uint8_t chromaLocHoriz;
+ uint8_t chromaLocVert;
+ /** Reserved for alignment */
+ uint8_t _reserved[6];
+} NvBufSurfaceChromaSubsamplingParams;
+
+/**
+ * Holds parameters required to allocate an \ref NvBufSurface.
+ */
+typedef struct NvBufSurfaceCreateParams {
+ /** Holds the GPU ID. Valid only for a multi-GPU system. */
+ uint32_t gpuId;
+ /** Holds the width of the buffer. */
+ uint32_t width;
+ /** Holds the height of the buffer. */
+ uint32_t height;
+ /** Holds the amount of memory to be allocated. Optional; if set, all other
+ parameters (width, height, etc.) are ignored. */
+ uint32_t size;
+ /** Holds a "contiguous memory" flag. If set, contiguous memory is allocated
+ for the batch. Valid only for CUDA memory types. */
+ bool isContiguous;
+ /** Holds the color format of the buffer. */
+ NvBufSurfaceColorFormat colorFormat;
+ /** Holds the surface layout. May be Block Linear (BL) or Pitch Linear (PL).
+ For a dGPU, only PL is valid. */
+ NvBufSurfaceLayout layout;
+ /** Holds the type of memory to be allocated. */
+ NvBufSurfaceMemType memType;
+ /** Holds the reserved space for future use. */
+ void * _reserved[STRUCTURE_PADDING];
+} NvBufSurfaceCreateParams;
+
+/**
+ * Hold extended parameters required to allocate NvBufSurface.
+ * (Applicable for NvBufSurfaceAllocate API)
+ */
+typedef struct NvBufSurfaceAllocateParams {
+ /** Hold legacy NvBufSurface creation parameters */
+ NvBufSurfaceCreateParams params;
+ /** Display scan format */
+ NvBufSurfaceDisplayScanFormat displayscanformat;
+ /** Chroma Subsampling parameters */
+ NvBufSurfaceChromaSubsamplingParams chromaSubsampling;
+ /** components tag to be used for memory allocation */
+ NvBufSurfaceTag memtag;
+ /** disable pitch padding allocation only applicable for cuda and system memory allocation
+ pitch would be width times bytes per pixel for the plane, for odd width it would be
+ multiple of 2, also note for some non standard video resolution cuda kernels may fail
+ due to unaligned pitch
+ */
+ bool disablePitchPadding;
+ /** Used void* from custom param for 64 bit machine, using other uint32_t param */
+ uint32_t _reservedParam;
+ /** Holds the reserved space for future use. */
+ void * _reserved[STRUCTURE_PADDING];
+} NvBufSurfaceAllocateParams;
+
+/**
+ * Hold the pointers of mapped buffer.
+ */
+typedef struct NvBufSurfaceMappedAddr {
+ /** Holds planewise pointers to a CPU mapped buffer. */
+ void * addr[NVBUF_MAX_PLANES];
+ /** Holds a pointer to a mapped EGLImage. */
+ void *eglImage;
+ /** Holds a pointer to a mapped NVRM memory */
+ void *nvmmPtr;
+ /** Holds a pointer to a mapped CUDA memory */
+ void *cudaPtr;
+ /** Holds the reserved space for future use. */
+ void * _reserved[STRUCTURE_PADDING];
+} NvBufSurfaceMappedAddr;
+
+/**
+ * Hold the information(extended) of single buffer in the batch.
+ */
+typedef struct NvBufSurfaceParamsEx {
+ /** offset in bytes from the start of the buffer to the first valid byte.
+ (Applicable for NVBUF_MEM_HANDLE) */
+ int32_t startofvaliddata;
+ /** size of the valid data from the first to the last valid byte.
+ (Applicable for NVBUF_MEM_HANDLE) */
+ int32_t sizeofvaliddatainbytes;
+ /** chroma subsampling parameters.
+ (Applicable for NVBUF_MEM_SURFACE_ARRAY) */
+ NvBufSurfaceChromaSubsamplingParams chromaSubsampling;
+ /** get buffer vpr information. */
+ bool is_protected;
+ /** plane wise extended info */
+ NvBufSurfacePlaneParamsEx planeParamsex;
+
+ void * _reserved[STRUCTURE_PADDING];
+} NvBufSurfaceParamsEx;
+
+/**
+ * Holds information of CUDA buffer.
+ * Applicable for tegra OpenRM only.
+ */
+typedef struct NvBufSurfaceCudaBuffer {
+ /**
+ * Holds a base pointer to allocated CUDA memory.
+ * It is different from dataPtr when CUDA allocated
+ * address is not page aligned for image buffers.
+ * It is same as dataPtr for other buffers.
+ */
+ void *basePtr;
+ /**
+ * Holds a page aligned data pointer to CUDA memory for image buffers
+ * if CUDA allocated address is not page aligned.
+ * It is same as basePtr for other buffers.
+ */
+ void *dataPtr;
+ /** Holds a pointer to external CUDA memory for imported CUDA buffers */
+ void *extMem;
+ /** Holds a pointer to external CUDA mipmaped array for imported CUDA buffers */
+ void *mipmap;
+ /** Reserved */
+ uint8_t reserved[64];
+} NvBufSurfaceCudaBuffer;
+
+/**
+ * Hold the information of single buffer in the batch.
+ */
+typedef struct NvBufSurfaceParams {
+ /** Holds the width of the buffer. */
+ uint32_t width;
+ /** Holds the height of the buffer. */
+ uint32_t height;
+ /** Holds the pitch of the buffer. */
+ uint32_t pitch;
+ /** Holds the color format of the buffer. */
+ NvBufSurfaceColorFormat colorFormat;
+ /** Holds BL or PL. For dGPU, only PL is valid. */
+ NvBufSurfaceLayout layout;
+ /** Holds a DMABUF FD. Valid only for \ref NVBUF_MEM_SURFACE_ARRAY and
+ \ref NVBUF_MEM_HANDLE type memory. */
+ uint64_t bufferDesc;
+ /** Holds the amount of allocated memory. */
+ uint32_t dataSize;
+ /** Holds a pointer to allocated memory. Not valid for
+ \ref NVBUF_MEM_SURFACE_ARRAY or \ref NVBUF_MEM_HANDLE. */
+ void * dataPtr;
+ /** Holds planewise information (width, height, pitch, offset, etc.). */
+ NvBufSurfacePlaneParams planeParams;
+ /** Holds pointers to mapped buffers. Initialized to NULL
+ when the structure is created. */
+ NvBufSurfaceMappedAddr mappedAddr;
+ /** pointers of extended parameters of single buffer in the batch.*/
+ NvBufSurfaceParamsEx *paramex;
+ /** Holds a pointer to CUDA buffer. Applicable for only CUDA Device and CUDA Host memory on tegra OpenRM.*/
+ NvBufSurfaceCudaBuffer *cudaBuffer;
+
+ void * _reserved[STRUCTURE_PADDING];
+} NvBufSurfaceParams;
+
+/**
+ * Holds information about batched buffers.
+ */
+typedef struct NvBufSurface {
+ /** Holds a GPU ID. Valid only for a multi-GPU system. */
+ uint32_t gpuId;
+ /** Holds the batch size. */
+ uint32_t batchSize;
+ /** Holds the number valid and filled buffers. Initialized to zero when
+ an instance of the structure is created. */
+ uint32_t numFilled;
+ /** Holds an "is contiguous" flag. If set, memory allocated for the batch
+ is contiguous. */
+ bool isContiguous;
+ /** Holds type of memory for buffers in the batch. */
+ NvBufSurfaceMemType memType;
+ /** Holds a pointer to an array of batched buffers. */
+ NvBufSurfaceParams *surfaceList;
+ /** Holds a flag for Imported buffer. */
+ bool isImportedBuf;
+
+ void * _reserved[STRUCTURE_PADDING];
+} NvBufSurface;
+
+/**
+ * Holds plane parameters to map the buffer received from another process.
+ */
+typedef struct NvBufSurfaceMapPlaneParams
+{
+ /** Holds the widths of planes */
+ uint32_t width;
+ /** Holds the heights of planes */
+ uint32_t height;
+ /** Holds the pitches of planes in bytes */
+ uint32_t pitch;
+ /** Holds the offsets of planes in bytes */
+ uint32_t offset;
+ /** Holds the sizes of planes in bytes */
+ uint32_t psize;
+ /** Holds offset of the second field for interlaced buffer */
+ uint32_t secondfieldoffset;
+ /** Holds block height of the planes for blockLinear layout buffer */
+ uint32_t blockheightlog2;
+ /** Holds flags associated with the planes */
+ uint64_t flags;
+ /** Reserved */
+ uint8_t reserved[64];
+} NvBufSurfaceMapPlaneParams;
+
+/**
+ * CUDA IPC memory handle for NvBufSurface
+ */
+typedef struct NvBufSurfaceCudaIpcMemHandle_t
+{
+ char reserved[64];
+} NvBufSurfaceCudaIpcMemHandle;
+
+/**
+ * The extended map parameters NvBufSurface
+ */
+typedef struct NvBufSurfaceExtendedMapParams_t
+{
+ NvBufSurfaceCudaIpcMemHandle memHandle;
+ void *reserved[64];
+} NvBufSurfaceExtendedMapParams;
+
+/**
+ * Holds buffer parameters to map the buffer received from another process.
+ */
+typedef struct NvBufSurfaceMapParams {
+ /** Holds the number of planes. */
+ uint32_t num_planes;
+ /** Holds a GPU ID */
+ uint32_t gpuId;
+ /** Holds a DMABUF FD */
+ uint64_t fd;
+ /** Holds the total size of allocated memory */
+ uint32_t totalSize;
+ /** Holds type of memory */
+ NvBufSurfaceMemType memType;
+ /** Holds BL or PL layout */
+ NvBufSurfaceLayout layout;
+ /** Holds display scan format */
+ NvBufSurfaceDisplayScanFormat scanformat;
+ /** Holds the color format */
+ NvBufSurfaceColorFormat colorFormat;
+ /** Holds chroma subsampling parameters */
+ NvBufSurfaceChromaSubsamplingParams chromaSubsampling;
+ /** Holds plane parameters */
+ NvBufSurfaceMapPlaneParams planes[NVBUF_MAX_PLANES];
+ /** Holds the extended Map parameters */
+ void *extendedMapParams;
+ /** Holds the reserved space for future use. */
+ void *_reserved[STRUCTURE_PADDING];
+} NvBufSurfaceMapParams;
+
+/**
+ * Holds information about mapped CUDA buffer
+ */
+typedef struct NvBufSurfaceNvmmBuffer {
+ /** Holds a pointer to mapped nvmm memory */
+ void *dataPtr;
+ /** Holds a DMABUF FD */
+ uint64_t bufferDesc;
+ /** Reserved */
+ uint8_t reserved[64];
+} NvBufSurfaceNvmmBuffer;
+
+/**
+ * Defines the type of underlying kernel driver detected for GPU access.
+ */
+typedef enum {
+ NVBUF_DRIVER_TYPE_UNKNOWN = 0,
+ NVBUF_DRIVER_TYPE_NVGPU,
+ NVBUF_DRIVER_TYPE_RM
+} NvBufSurfaceDriverType;
+
+/**
+ * Holds information about the underlying device.
+ */
+typedef struct NvBufSurfaceDeviceInfo {
+ /** The detected device type (nvgpu, OpenRM, etc.). */
+ NvBufSurfaceDriverType driverType;
+ /** Indicates if VIC is present on the platform. */
+ bool isVicPresent;
+ /** Reserved for future use. */
+ uint8_t reserved[64];
+} NvBufSurfaceDeviceInfo;
+
+/**
+ * \brief Allocates a batch of buffers.
+ *
+ * Allocates memory for \a batchSize buffers and returns a pointer to an
+ * allocated \ref NvBufSurface. The \a params structure must have
+ * the allocation parameters of a single buffer. If \a params.size
+ * is set, a buffer of that size is allocated, and all other
+ * parameters (width, height, color format, etc.) are ignored.
+ *
+ * Call NvBufSurfaceDestroy() to free resources allocated by this function.
+ *
+ * @param[out] surf An indirect pointer to the allocated batched
+ * buffers.
+ * @param[in] batchSize Batch size of buffers.
+ * @param[in] params A pointer to an \ref NvBufSurfaceCreateParams
+ * structure.
+ *
+ * @return 0 if successful, or -1 otherwise.
+ */
+int NvBufSurfaceCreate (NvBufSurface **surf, uint32_t batchSize,
+ NvBufSurfaceCreateParams *params);
+
+/**
+ * \brief Allocate batch of buffers. (Using extended buffer allocation parameters)
+ *
+ * Allocates memory for batchSize buffers and returns in *surf a pointer to allocated NvBufSurface.
+ * params structure should have allocation parameters of single buffer. If size field in
+ * params is set, buffer of that size will be allocated and all other
+ * parameters (w, h, color format etc.) will be ignored.
+ *
+ * Use NvBufSurfaceDestroy to free all the resources.
+ *
+ * @param[out] surf pointer to allocated batched buffers.
+ * @param[in] batchSize batch size of buffers.
+ * @param[in] paramsext pointer to NvBufSurfaceAllocateParams structure.
+ *
+ * @return 0 for success, -1 for failure.
+ */
+int NvBufSurfaceAllocate (NvBufSurface **surf, uint32_t batchSize,
+ NvBufSurfaceAllocateParams *paramsext);
+
+/**
+ * Free the batched buffers previously allocated through NvBufSurfaceCreate.
+ *
+ * @param[in] surf A pointer to an \ref NvBufSurface to be freed.
+ *
+ * @return 0 if successful, or -1 otherwise.
+ */
+int NvBufSurfaceDestroy (NvBufSurface *surf);
+
+/**
+ * \brief Maps hardware batched buffers to the HOST or CPU address space.
+ *
+ * Valid for \ref NVBUF_MEM_CUDA_UNIFIED type memory for dGPU and
+ * \ref NVBUF_MEM_SURFACE_ARRAY and \ref NVBUF_MEM_HANDLE type memory for
+ * Jetson.
+ *
+ * This function fills an array of pointers at
+ * \a surf->surfaceList->mappedAddr->addr.
+ * \a surf is a pointer to an \ref NvBufSurface.
+ * \a surfaceList is a pointer to an \ref NvBufSurfaceParams.
+ * \a mappedAddr is a pointer to an \ref NvBufSurfaceMappedAddr.
+ * \a addr is declared as an array of pointers to void, and holds pointers
+ * to the buffers.
+ *
+ * The client must call NvBufSurfaceSyncForCpu() with the virtual address
+ * populated by this function before accessing mapped memory in the CPU.
+ *
+ * After memory mapping is complete, mapped memory modification
+ * must be coordinated between the CPU and the hardware device as
+ * follows:
+ * - CPU: If the CPU modifies mapped memory, the client must call
+ * NvBufSurfaceSyncForDevice() before any hardware device accesses the memory.
+ * - Hardware device: If a hardware device modifies mapped memory, the client
+ * must call NvBufSurfaceSyncForCpu() before the CPU accesses the memory.
+ *
+ * Use NvBufSurfaceUnMap() to unmap buffer(s) and release any resource.
+ *
+ * @param[in,out] surf A pointer to an NvBufSurface structure. The function
+ * stores pointers to the buffers in a descendant of this
+ * structure; see the notes above.
+ * @param[in] index Index of a buffer in the batch. -1 refers to all buffers
+ * in the batch.
+ * @param[in] plane Index of a plane in buffer. -1 refers to all planes
+ * in the buffer.
+ * @param[in] type A flag for mapping type.
+ *
+ * @return 0 if successful, or -1 otherwise.
+ */
+int NvBufSurfaceMap (NvBufSurface *surf, int index, int plane, NvBufSurfaceMemMapFlags type);
+
+/**
+ * \brief Unmaps previously mapped buffer(s).
+ *
+ * @param[in] surf A pointer to an \ref NvBufSurface structure.
+ * @param[in] index Index of a buffer in the batch. -1 indicates
+ * all buffers in the batch.
+ * @param[in] plane Index of a plane in the buffer. -1 indicates
+ * all planes in the buffer.
+ *
+ * @return 0 if successful, or -1 otherwise.
+ */
+int NvBufSurfaceUnMap (NvBufSurface *surf, int index, int plane);
+
+/**
+ * \brief Copies the content of source batched buffer(s) to destination
+ * batched buffer(s).
+ *
+ * You can use this function to copy source buffer(s) of one memory type
+ * to destination buffer(s) of another memory type,
+ * e.g. CUDA host to CUDA device, malloc'ed memory to CUDA device, etc.
+ *
+ * The source and destination \ref NvBufSurface objects must have same
+ * buffer and batch size.
+ *
+ * @param[in] srcSurf A pointer to the source NvBufSurface structure.
+ * @param[in] dstSurf A pointer to the destination NvBufSurface structure.
+ *
+ * @return 0 if successful, or -1 otherwise.
+ */
+int NvBufSurfaceCopy (NvBufSurface *srcSurf, NvBufSurface *dstSurf);
+
+/**
+ * \brief Copies the NvBufSurface plane memory content to a raw buffer plane for a specific
+ * batched buffer.
+ *
+ * This function can be used to copy plane memory content from source raw buffer pointer
+ * to specific destination batch buffer of supported memory type.
+ *
+ * @param[in] Surf pointer to NvBufSurface structure.
+ * @param[in] index index of buffer in the batch.
+ * @param[in] plane index of plane in buffer.
+ * @param[in] out_width aligned width of the raw data plane.
+ * @param[in] out_height aligned height of the raw data plane.
+ * @param[in] ptr pointer to the output raw plane data.
+ *
+ * @return 0 for success, -1 for failure.
+ */
+int NvBufSurface2Raw (NvBufSurface *Surf, unsigned int index, unsigned int plane, unsigned int out_width, unsigned int out_height, unsigned char *ptr);
+
+/**
+ * \brief Copies the raw buffer plane memory content to the NvBufSurface plane memory of a specific
+ * batched buffer.
+ *
+ * This function can be used to copy plane memory content from batch buffer
+ * to specific destination raw buffer pointer.
+ *
+ * @param[in] ptr pointer to the input raw plane data.
+ * @param[in] index index of buffer in the batch.
+ * @param[in] plane index of plane in buffer.
+ * @param[in] in_width aligned width of the raw data plane.
+ * @param[in] in_height aligned height of the raw data plane.
+ * @param[in] Surf pointer to NvBufSurface structure.
+ *
+ * @return 0 for success, -1 for failure.
+ */
+int Raw2NvBufSurface (unsigned char *ptr, unsigned int index, unsigned int plane, unsigned int in_width, unsigned int in_height, NvBufSurface *Surf);
+
+/**
+ * Syncs the HW memory cache for the CPU.
+ *
+ * Valid only for memory types \ref NVBUF_MEM_SURFACE_ARRAY and
+ * \ref NVBUF_MEM_HANDLE.
+ *
+ * @param[in] surf A pointer to an \ref NvBufSurface structure.
+ * @param[in] index Index of the buffer in the batch. -1 refers to
+ * all buffers in the batch.
+ * @param[in] plane Index of a plane in the buffer. -1 refers to all planes
+ * in the buffer.
+ *
+ * @return 0 if successful, or -1 otherwise.
+ */
+int NvBufSurfaceSyncForCpu (NvBufSurface *surf, int index, int plane);
+
+/**
+ * \brief Syncs the hardware memory cache for the device.
+ *
+ * Valid only for memory types \ref NVBUF_MEM_SURFACE_ARRAY and
+ * \ref NVBUF_MEM_HANDLE.
+ *
+ * @param[in] surf A pointer to an \ref NvBufSurface structure.
+ * @param[in] index Index of a buffer in the batch. -1 refers to all buffers
+ * in the batch.
+ * @param[in] plane Index of a plane in the buffer. -1 refers to all planes
+ * in the buffer.
+ *
+ * @return 0 if successful, or -1 otherwise.
+ */
+int NvBufSurfaceSyncForDevice (NvBufSurface *surf, int index, int plane);
+
+/**
+ * \brief Gets the \ref NvBufSurface from the DMABUF FD.
+ *
+ * @param[in] dmabuf_fd DMABUF FD of the buffer.
+ * @param[out] buffer A pointer to the NvBufSurface.
+ *
+ * @return 0 for success, or -1 otherwise.
+ */
+int NvBufSurfaceFromFd (int dmabuf_fd, void **buffer);
+
+/**
+ * \brief Fills each byte of the buffer(s) in an \ref NvBufSurface with a
+ * provided value.
+ *
+ * You can also use this function to reset the buffer(s) in the batch.
+ *
+ * @param[in] surf A pointer to the NvBufSurface structure.
+ * @param[in] index Index of a buffer in the batch. -1 refers to all buffers
+ * in the batch.
+ * @param[in] plane Index of a plane in the buffer. -1 refers to all planes
+ * in the buffer.
+ * @param[in] value The value to be used as fill.
+ *
+ * @return 0 if successful, or -1 otherwise.
+ */
+int NvBufSurfaceMemSet (NvBufSurface *surf, int index, int plane, uint8_t value);
+
+/**
+ * \brief Creates an EGLImage from the memory of one or more
+ * \ref NvBufSurface buffers.
+ *
+ * Only memory type \ref NVBUF_MEM_SURFACE_ARRAY is supported.
+ *
+ * This function returns the created EGLImage by storing its address at
+ * \a surf->surfaceList->mappedAddr->eglImage. (\a surf is a pointer to
+ * an NvBufSurface. \a surfaceList is a pointer to an \ref NvBufSurfaceParams.
+ * \a mappedAddr is a pointer to an \ref NvBufSurfaceMappedAddr.
+ * \a eglImage is declared as a pointer to void, and holds an
+ * EGLImageKHR.)
+ *
+ * You can use this function in scenarios where a CUDA operation on Jetson
+ * hardware memory (identified by \ref NVBUF_MEM_SURFACE_ARRAY) is required.
+ * The EGLImageKHR struct provided by this function can then be registered
+ * with CUDA for further CUDA operations.
+ *
+ * @param[in,out] surf A pointer to an NvBufSurface structure. The function
+ * stores a pointer to the created EGLImage in
+ * a descendant of this structure; see the notes above.
+ * @param[in] index Index of a buffer in the batch. -1 specifies all buffers
+ * in the batch.
+ *
+ * @return 0 for success, or -1 otherwise.
+ */
+int NvBufSurfaceMapEglImage (NvBufSurface *surf, int index);
+
+/**
+ * \brief Destroys the previously created EGLImage object(s).
+ *
+ * @param[in] surf A pointer to an \ref NvBufSurface structure.
+ * @param[in] index The index of a buffer in the batch. -1 specifies all
+ * buffers in the batch.
+ *
+ * @return 0 if successful, or -1 otherwise.
+ */
+int NvBufSurfaceUnMapEglImage (NvBufSurface *surf, int index);
+
+/**
+ * \brief Import parameters received from another process and create hardware buffer.
+ *
+ * Calling process must need to call NvBufferDestroy() to remove reference count for
+ * hardware buffer handle of the imported DMA buffer.
+ *
+ * @param[out] out_nvbuf_surf Pointer to hardware buffer.
+ * @param[in] in_params Parameters to create hardware buffer.
+ *
+ * @return 0 for success, -1 for failure.
+ */
+int NvBufSurfaceImport (NvBufSurface **out_nvbuf_surf, const NvBufSurfaceMapParams *in_params);
+
+/**
+ * \brief Get buffer information to map the buffer in another process.
+ *
+ * @param[in] surf Pointer to NvBufSurface structure.
+ * @param[in] index Index of a buffer in the batch.
+ * @param[out] params Pointer to NvBufSurfaceMapParams information of the buffer.
+ *
+ * @return 0 for success, -1 for failure.
+ */
+int NvBufSurfaceGetMapParams (const NvBufSurface *surf, int index, NvBufSurfaceMapParams *params);
+
+/**
+ * \brief Creates an CUDA buffer from the memory of one or more
+ * \ref NvBufSurface buffers.
+ *
+ * Only memory type \ref NVBUF_MEM_SURFACE_ARRAY is supported.
+ *
+ * This function returns the created CUDA buffer by storing its address at
+ * \a surf->surfaceList->mappedAddr->cudaPtr. (\a surf is a pointer to
+ * an NvBufSurface. \a surfaceList is a pointer to an \ref NvBufSurfaceParams.
+ * \a mappedAddr is a pointer to an \ref NvBufSurfaceMappedAddr.
+ * \a cudaPtr is a pointer to an \ref NvBufSurfaceCudaBuffer.
+ *
+ * You can use this function in scenarios where a CUDA operation on Jetson
+ * hardware memory (identified by \ref NVBUF_MEM_SURFACE_ARRAY) is required.
+ * The NvBufSurfaceCudaBuffer struct provided by this function can be used
+ * to get dataPtr of CUDA memory.
+ *
+ * @param[in,out] surf A pointer to an NvBufSurface structure. The function
+ * stores a pointer to the created CUDA buffer in
+ * a descendant of this structure; see the notes above.
+ * @param[in] index Index of a buffer in the batch. -1 specifies all buffers
+ * in the batch.
+ *
+ * @return 0 for success, or -1 otherwise.
+ */
+int NvBufSurfaceMapCudaBuffer (NvBufSurface *surf, int index);
+
+/**
+ * \brief Destroys the previously created CUDA buffer.
+ *
+ * @param[in] surf A pointer to an \ref NvBufSurface structure.
+ * @param[in] index The index of a buffer in the batch. -1 specifies all
+ * buffers in the batch.
+ *
+ * @return 0 if successful, or -1 otherwise.
+ */
+int NvBufSurfaceUnMapCudaBuffer (NvBufSurface *surf, int index);
+
+/**
+ * \brief Creates an NVMM buffer from the memory of one or more
+ * \ref NvBufSurface buffers.
+ *
+ * Only memory type \ref NVBUF_MEM_CUDA_DEVICE and \ref NVBUF_MEM_CUDA_PINNED
+ * are supported.
+ *
+ * This function returns the created NVMM buffer by storing its address at
+ * \a surf->surfaceList->mappedAddr->nvmmPtr. (\a surf is a pointer to
+ * an NvBufSurface. \a surfaceList is a pointer to an \ref NvBufSurfaceParams.
+ * \a mappedAddr is a pointer to an \ref NvBufSurfaceMappedAddr.
+ * \a nvmmPtr is a pointer to NVMM buffer of memory type \ref NVBUF_MEM_SURFACE_ARRAY.
+ *
+ * You can use this function in scenarios where a NVBUF_MEM_SURFACE_ARRAY operation
+ * on Jetson hardware memory identified by \ref NVBUF_MEM_CUDA_DEVICE and
+ * \ref NVBUF_MEM_CUDA_PINNED are required.
+ *
+ * @param[in,out] surf A pointer to an NvBufSurface structure. The function
+ * stores a pointer to the created NVMM buffer in
+ * a descendant of this structure; see the notes above.
+ * @param[in] index Index of a buffer in the batch. -1 specifies all buffers
+ * in the batch.
+ *
+ * @return 0 for success, or -1 otherwise.
+ */
+int NvBufSurfaceMapNvmmBuffer (NvBufSurface *surf, int index);
+
+/**
+ * \brief Destroys the previously created NVMM buffer.
+ *
+ * @param[in] surf A pointer to an \ref NvBufSurface structure.
+ * @param[in] index The index of a buffer in the batch. -1 specifies all
+ * buffers in the batch.
+ *
+ * @return 0 if successful, or -1 otherwise.
+ */
+int NvBufSurfaceUnMapNvmmBuffer (NvBufSurface *surf, int index);
+
+/**
+ * \brief Retrieves information about the underlying GPU device driver.
+ *
+ * @param[out] info Pointer to NvBufSurfaceDeviceInfo structure.
+ *
+ * @return 0 if successful, or -1 otherwise.
+ *
+ * This function attempts to determine if the system is using 'nvgpu' or
+ * an OpenRM-based driver by checking loaded kernel modules. Also it checks
+ * if VIC is present on the platform.
+ */
+int NvBufSurfaceGetDeviceInfo (NvBufSurfaceDeviceInfo *info);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* NVBUFSURFACE_H_ */
diff --git a/push_info.txt b/push_info.txt
new file mode 100644
index 0000000..6be9858
--- /dev/null
+++ b/push_info.txt
@@ -0,0 +1 @@
+jetson_38.2