diff --git a/commitFile.txt b/commitFile.txt new file mode 100644 index 0000000..6ad3215 --- /dev/null +++ b/commitFile.txt @@ -0,0 +1,8 @@ +Updating prebuilts and/or headers + +290e58e7e6e6663d811a5222d7781b70fec79272 - gst-nvvidconv/gstnvvconv.c +28d38d98f14debda660f7ba7813ba3466e0e7598 - gst-nvvidconv/nvbufsurface.h +c3f21bd4363243ad1bca5b1d434b5896402eec14 - gst-nvvidconv/nvbuf_utils.h +444b666f460d87e0278892a2d7520d65e68679ec - gst-nvvidconv/Makefile +be709a89089ce6b51857e35f0440859188b3ed87 - gst-nvvidconv/gstnvvconv.h +56e1e36e7b4fc38bc3ca3707d265fe22541686b2 - gst-nvvidconv/3rdpartyheaders.tbz2 diff --git a/gst-nvvidconv/3rdpartyheaders.tbz2 b/gst-nvvidconv/3rdpartyheaders.tbz2 new file mode 100644 index 0000000..3879a38 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..6d56c83 --- /dev/null +++ b/gst-nvvidconv/gstnvvconv.c @@ -0,0 +1,3389 @@ +/* + * Copyright (c) 2014-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. + */ + +/* + * 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" + + +#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 }") ";" GST_VIDEO_CAPS_MAKE ("{ " + "I420, UYVY, YUY2, YVYU, NV12, NV16, NV24, P010_10LE, GRAY8, BGRx, RGBA, Y42B }"))); + +/* 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 }") ";" GST_VIDEO_CAPS_MAKE ("{ " + "I420, UYVY, YUY2, YVYU, NV12, NV16, NV24, GRAY8, BGRx, RGBA, Y42B }"))); + +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_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; + + 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; + + /* 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; + 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; + 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; + 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; + filter->enable_blocklinear_output = TRUE; + + 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)); + + 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", + TRUE, 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->sinkcaps = 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, from_dar_d, to_dar_n, to_dar_d; + GstVideoInfo in_info, out_info; + GstBufferPool *newpool, *oldpool; + GstStructure *config; + gint min, surf_count = 0; + GstCapsFeatures *ift = NULL; + GstCapsFeatures *oft = NULL; + + 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; + + space->from_width = GST_VIDEO_INFO_WIDTH (&in_info); + space->from_height = GST_VIDEO_INFO_HEIGHT (&in_info); + + 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) && + (space->enable_blocklinear_output)) { + /* 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: + 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: + 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: + 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: + 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: + space->tsurf_count = 2; + break; + case NVBUF_COLOR_FORMAT_UYVY: + case NVBUF_COLOR_FORMAT_YUYV: + case NVBUF_COLOR_FORMAT_YVYU: + 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) || + (!gst_caps_features_is_equal (ift, oft)) || + (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) { + gst_object_unref (space->pool); + space->pool = NULL; + } + + 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; + + /* 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; +} + +/** + * 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; + + 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, f_height, f_par_n, f_par_d, t_par_n, t_par_d; + gint t_width = 0, t_height = 0; + gint f_dar_n, f_dar_d; + gint numerator, denominator; + + /* 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; + gint set_par_n; + gint set_par_d; + 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; + } + } + + GST_DEBUG_OBJECT (space, "fixated othercaps to %" GST_PTR_FORMAT, othercaps); + + if (from_pix_ar == &from_par) + g_value_unset (&from_par); + if (to_pix_ar == &to_par) + g_value_unset (&to_par); + + 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); + 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)); + + 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_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_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] = + GST_ROUND_UP_4 (space->from_width * bytesPerPixel) / bytesPerPixel; + 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] = + GST_ROUND_UP_4 (space->to_width * bytesPerPixel) / bytesPerPixel; + 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] = + GST_ROUND_UP_4 (comp_width * bytesPerPixel) / bytesPerPixel; + 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; + } + } + + 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; + memset (&surfaceList, 0, sizeof (surfaceList)); + op_surf.surfaceList = &surfaceList; + surface_list_init (space, &op_surf, &outmap, 0); + + if (space->need_intersurf || space->do_scaling || space->flip_method) { + if (space->isurf_flag == TRUE && space->ibuf_count < 1) { + input_params.params.width = GST_ROUND_UP_2 (space->to_width);; + input_params.params.height = GST_ROUND_UP_2 (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 = NVBUF_MEM_CUDA_DEVICE; + } 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; + memset (&surfaceList, 0, sizeof (surfaceList)); + ip_surf.surfaceList = &surfaceList; + surface_list_init (space, &ip_surf, &inmap, 1); + + if (space->need_intersurf || space->do_scaling || space->flip_method) { + if (space->isurf_flag == TRUE && space->ibuf_count < 1) { + /* TODO : Check for PayloadInfo.TimeStamp = gst_util_uint64_scale (GST_BUFFER_PTS (inbuf), GST_MSECOND * 10, GST_SECOND); */ + input_params.params.width = GST_ROUND_UP_2 (space->from_width);; + input_params.params.height = GST_ROUND_UP_2 (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 = NVBUF_MEM_CUDA_DEVICE; + } 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); + /* TODO : Check for PayloadInfo.TimeStamp = gst_util_uint64_scale (GST_BUFFER_PTS (inbuf), GST_MSECOND * 10, GST_SECOND); */ + if (space->need_intersurf || space->do_scaling || space->flip_method) { + 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 (space->need_intersurf || space->do_scaling || space->flip_method) { + if (space->isurf_flag == TRUE) { + + NvBufSurfaceAllocateParams input_params = { 0 }; + + if (space->ibuf_count < 1) { + input_params.params.width = GST_ROUND_UP_2 (space->from_width);; + input_params.params.height = GST_ROUND_UP_2 (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 = NVBUF_MEM_CUDA_DEVICE; + } 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) { + input_params.params.width = GST_ROUND_UP_2 (space->to_width);; + input_params.params.height = GST_ROUND_UP_2 (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 = NVBUF_MEM_CUDA_DEVICE; + } 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); + + 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) +{ + 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..f40a736 --- /dev/null +++ b/gst-nvvidconv/gstnvvconv.h @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2014-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. + */ + +#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; + + 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/nvbuf_utils.h b/gst-nvvidconv/nvbuf_utils.h new file mode 100644 index 0000000..6a8c7fa --- /dev/null +++ b/gst-nvvidconv/nvbuf_utils.h @@ -0,0 +1,897 @@ +/* + * Copyright (c) 2016-2021, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** + * @file + * NVIDIA Multimedia Utilities: Buffering and Transform/Composition/Blending + * + */ + +/** + * @defgroup ee_nvbuffering_group Buffer Manager + * @ingroup common_utility_group + * NVIDIA buffering utility library for use by applications. + * The utility also transforms, composits, and blends. + * @{ + */ + +#ifndef _NVBUF_UTILS_H_ +#define _NVBUF_UTILS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include +#include + +/** + * Defines the maximum number of planes for a video frame. + */ +#define MAX_NUM_PLANES 4 + +/** + * Defines the maximum number of input video frames that can be used for composition. + */ +#define MAX_COMPOSITE_FRAME 16 + +/** + * Defines the default values for chroma subsampling. + * The default value matches JPEG/MPEG use cases. + */ +#define NVBUF_CHROMA_SUBSAMPLING_HORIZ_DEFAULT 0 +#define NVBUF_CHROMA_SUBSAMPLING_VERT_DEFAULT 1 + +/** + * Defines the maximum number of sync object parameters. + */ +#define NVBUF_MAX_SYNCOBJ_PARAMS 5 + +/** + * Use this value to represent an infinite wait interval. + * A value of zero should not be interpreted as infinite, + * it should be interpreted as "time out immediately" and + * simply check whether the event has already happened. + */ +#define NVBUFFER_SYNCPOINT_WAIT_INFINITE 0xFFFFFFFF + +/** + * Defines Payload types for NvBuffer. + */ +typedef enum +{ + /** buffer payload with hardware memory handle for set of planes. */ + NvBufferPayload_SurfArray, + /** buffer payload with hardware memory handle for specific memory size. */ + NvBufferPayload_MemHandle, +} NvBufferPayloadType; + +/** + * Defines display scan formats for NvBuffer video planes. + */ +typedef enum +{ + /** Progessive scan formats. */ + NvBufferDisplayScanFormat_Progressive = 0, + /** Interlaced scan formats. */ + NvBufferDisplayScanFormat_Interlaced, +} NvBufferDisplayScanFormat; + +/** + * Defines Layout formats for NvBuffer video planes. + */ +typedef enum +{ + /** Pitch Layout. */ + NvBufferLayout_Pitch, + /** BlockLinear Layout. */ + NvBufferLayout_BlockLinear, +} NvBufferLayout; + +/** + * Defines memory access flags for NvBuffer. + */ +typedef enum +{ + /** Memory read. */ + NvBufferMem_Read, + /** Memory write. */ + NvBufferMem_Write, + /** Memory read & write. */ + NvBufferMem_Read_Write, +} NvBufferMemFlags; + +/** + * 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. + */ +typedef enum +{ + /** tag None. */ + NvBufferTag_NONE = 0x0, + /** tag for Camera. */ + NvBufferTag_CAMERA = 0x200, + /** tag for Jpeg Encoder/Decoder. */ + NvBufferTag_JPEG = 0x1500, + /** tag for VPR Buffers. */ + NvBufferTag_PROTECTED = 0x1504, + /** tag for H264/H265 Video Encoder. */ + NvBufferTag_VIDEO_ENC = 0x1200, + /** tag for H264/H265/VP9 Video Decoder. */ + NvBufferTag_VIDEO_DEC = 0x1400, + /** tag for Video Transform/Composite. */ + NvBufferTag_VIDEO_CONVERT = 0xf01, +} NvBufferTag; + +/** + * Defines color formats for NvBuffer. + */ +typedef enum +{ + /** BT.601 colorspace - YUV420 multi-planar. */ + NvBufferColorFormat_YUV420, + /** BT.601 colorspace - YUV420 multi-planar. */ + NvBufferColorFormat_YVU420, + /** BT.601 colorspace - YUV422 multi-planar. */ + NvBufferColorFormat_YUV422, + /** BT.601 colorspace - YUV420 ER multi-planar. */ + NvBufferColorFormat_YUV420_ER, + /** BT.601 colorspace - YVU420 ER multi-planar. */ + NvBufferColorFormat_YVU420_ER, + /** BT.601 colorspace - Y/CbCr 4:2:0 multi-planar. */ + NvBufferColorFormat_NV12, + /** BT.601 colorspace - Y/CbCr ER 4:2:0 multi-planar. */ + NvBufferColorFormat_NV12_ER, + /** BT.601 colorspace - Y/CbCr 4:2:0 multi-planar. */ + NvBufferColorFormat_NV21, + /** BT.601 colorspace - Y/CbCr ER 4:2:0 multi-planar. */ + NvBufferColorFormat_NV21_ER, + /** BT.601 colorspace - YUV 4:2:2 planar. */ + NvBufferColorFormat_UYVY, + /** BT.601 colorspace - YUV ER 4:2:2 planar. */ + NvBufferColorFormat_UYVY_ER, + /** BT.601 colorspace - YUV 4:2:2 planar. */ + NvBufferColorFormat_VYUY, + /** BT.601 colorspace - YUV ER 4:2:2 planar. */ + NvBufferColorFormat_VYUY_ER, + /** BT.601 colorspace - YUV 4:2:2 planar. */ + NvBufferColorFormat_YUYV, + /** BT.601 colorspace - YUV ER 4:2:2 planar. */ + NvBufferColorFormat_YUYV_ER, + /** BT.601 colorspace - YUV 4:2:2 planar. */ + NvBufferColorFormat_YVYU, + /** BT.601 colorspace - YUV ER 4:2:2 planar. */ + NvBufferColorFormat_YVYU_ER, + /** LegacyRGBA colorspace - BGRA-8-8-8-8 planar. */ + NvBufferColorFormat_ABGR32, + /** LegacyRGBA colorspace - XRGB-8-8-8-8 planar. */ + NvBufferColorFormat_XRGB32, + /** LegacyRGBA colorspace - ARGB-8-8-8-8 planar. */ + NvBufferColorFormat_ARGB32, + /** BT.601 colorspace - Y/CbCr 4:2:0 10-bit multi-planar. */ + NvBufferColorFormat_NV12_10LE, + /** BT.709 colorspace - Y/CbCr 4:2:0 10-bit multi-planar. */ + NvBufferColorFormat_NV12_10LE_709, + /** BT.709_ER colorspace - Y/CbCr 4:2:0 10-bit multi-planar. */ + NvBufferColorFormat_NV12_10LE_709_ER, + /** BT.2020 colorspace - Y/CbCr 4:2:0 10-bit multi-planar. */ + NvBufferColorFormat_NV12_10LE_2020, + /** BT.601 colorspace - Y/CrCb 4:2:0 10-bit multi-planar. */ + NvBufferColorFormat_NV21_10LE, + /** BT.601 colorspace - Y/CbCr 4:2:0 12-bit multi-planar. */ + NvBufferColorFormat_NV12_12LE, + /** BT.2020 colorspace - Y/CbCr 4:2:0 12-bit multi-planar. */ + NvBufferColorFormat_NV12_12LE_2020, + /** BT.601 colorspace - Y/CrCb 4:2:0 12-bit multi-planar. */ + NvBufferColorFormat_NV21_12LE, + /** BT.709 colorspace - YUV420 multi-planar. */ + NvBufferColorFormat_YUV420_709, + /** BT.709 colorspace - YUV420 ER multi-planar. */ + NvBufferColorFormat_YUV420_709_ER, + /** BT.709 colorspace - Y/CbCr 4:2:0 multi-planar. */ + NvBufferColorFormat_NV12_709, + /** BT.709 colorspace - Y/CbCr ER 4:2:0 multi-planar. */ + NvBufferColorFormat_NV12_709_ER, + /** BT.2020 colorspace - YUV420 multi-planar. */ + NvBufferColorFormat_YUV420_2020, + /** BT.2020 colorspace - Y/CbCr 4:2:0 multi-planar. */ + NvBufferColorFormat_NV12_2020, + /** BT.601 colorspace - YUV444 multi-planar. */ + NvBufferColorFormat_YUV444, + /** Optical flow */ + NvBufferColorFormat_SignedR16G16, + /** Optical flow SAD calculation Buffer format */ + NvBufferColorFormat_A32, + /** 8-bit grayscale. */ + NvBufferColorFormat_GRAY8, + /** BT.601 colorspace - Y/CbCr 4:2:2 multi-planar. */ + NvBufferColorFormat_NV16, + /** BT.601 colorspace - Y/CbCr 4:2:2 10-bit semi-planar. */ + NvBufferColorFormat_NV16_10LE, + /** BT.601 colorspace - Y/CbCr 4:4:4 multi-planar. */ + NvBufferColorFormat_NV24, + /** BT.601 colorspace - Y/CrCb 4:4:4 10-bit multi-planar. */ + NvBufferColorFormat_NV24_10LE, + /** BT.601_ER colorspace - Y/CbCr 4:2:2 multi-planar. */ + NvBufferColorFormat_NV16_ER, + /** BT.601_ER colorspace - Y/CbCr 4:4:4 multi-planar. */ + NvBufferColorFormat_NV24_ER, + /** BT.709 colorspace - Y/CbCr 4:2:2 multi-planar. */ + NvBufferColorFormat_NV16_709, + /** BT.709 colorspace - Y/CbCr 4:4:4 multi-planar. */ + NvBufferColorFormat_NV24_709, + /** BT.709_ER colorspace - Y/CbCr 4:2:2 multi-planar. */ + NvBufferColorFormat_NV16_709_ER, + /** BT.709_ER colorspace - Y/CbCr 4:4:4 multi-planar. */ + NvBufferColorFormat_NV24_709_ER, + /** BT.709 colorspace - Y/CbCr 10 bit 4:4:4 multi-planar. */ + NvBufferColorFormat_NV24_10LE_709, + /** BT.709 ER colorspace - Y/CbCr 10 bit 4:4:4 multi-planar. */ + NvBufferColorFormat_NV24_10LE_709_ER, + /** BT.2020 colorspace - Y/CbCr 10 bit 4:4:4 multi-planar. */ + NvBufferColorFormat_NV24_10LE_2020, + /** BT.2020 colorspace - Y/CbCr 12 bit 4:4:4 multi-planar. */ + NvBufferColorFormat_NV24_12LE_2020, + /** Non-linear RGB BT.709 colorspace - RGBA-10-10-10-2 planar. */ + NvBufferColorFormat_RGBA_10_10_10_2_709, + /** Non-linear RGB BT.2020 colorspace - RGBA-10-10-10-2 planar. */ + NvBufferColorFormat_RGBA_10_10_10_2_2020, + /** Non-linear RGB BT.709 colorspace - BGRA-10-10-10-2 planar. */ + NvBufferColorFormat_BGRA_10_10_10_2_709, + /** Non-linear RGB BT.2020 colorspace - BGRA-10-10-10-2 planar. */ + NvBufferColorFormat_BGRA_10_10_10_2_2020, + /** Invalid color format. */ + NvBufferColorFormat_Invalid, +} NvBufferColorFormat; + +/** + * Defines video flip methods. + */ +typedef enum +{ + /** Video flip none. */ + NvBufferTransform_None, + /** Video flip rotate 90 degree counter-clockwise. */ + NvBufferTransform_Rotate90, + /** Video flip rotate 180 degree. */ + NvBufferTransform_Rotate180, + /** Video flip rotate 270 degree counter-clockwise. */ + NvBufferTransform_Rotate270, + /** Video flip with respect to X-axis. */ + NvBufferTransform_FlipX, + /** Video flip with respect to Y-axis. */ + NvBufferTransform_FlipY, + /** Video flip transpose. */ + NvBufferTransform_Transpose, + /** Video flip inverse transpode. */ + NvBufferTransform_InvTranspose, +} NvBufferTransform_Flip; + +/** + * Defines transform video filter types. + */ +typedef enum +{ + /** transform filter nearest. */ + NvBufferTransform_Filter_Nearest, + /** transform filter bilinear. */ + NvBufferTransform_Filter_Bilinear, + /** transform filter 5 tap. */ + NvBufferTransform_Filter_5_Tap, + /** transform filter 10 tap. */ + NvBufferTransform_Filter_10_Tap, + /** transform filter smart. */ + NvBufferTransform_Filter_Smart, + /** transform filter nicest. */ + NvBufferTransform_Filter_Nicest, +} NvBufferTransform_Filter; + +/** + * Defines flags to indicate for valid transform. + */ +typedef enum { + /** transform flag to crop source rectangle. */ + NVBUFFER_TRANSFORM_CROP_SRC = 1, + /** transform flag to crop destination rectangle. */ + NVBUFFER_TRANSFORM_CROP_DST = 1 << 1, + /** transform flag to set filter type. */ + NVBUFFER_TRANSFORM_FILTER = 1 << 2, + /** transform flag to set flip method. */ + NVBUFFER_TRANSFORM_FLIP = 1 << 3, +} NvBufferTransform_Flag; + +/** + * Defines flags that specify valid composition/blending operations. + */ +typedef enum { + /** flag to set for composition. */ + NVBUFFER_COMPOSITE = 1, + /** flag to set for blending. */ + NVBUFFER_BLEND = 1 << 1, + /** composition flag to set filter type. */ + NVBUFFER_COMPOSITE_FILTER = 1 << 2, +} NvBufferComposite_Flag; + +/** + * Holds parameters for buffer sync point object. + * sync object params is simply a data structure containing [sync point ID,value] pair. + * This can be used by clients to describe an event that might want to wait for. + */ +typedef struct _NvBufferSyncObjParams +{ + uint32_t syncpointID; + uint32_t value; +}NvBufferSyncObjParams; + +/** + * buffer sync point object. + */ +typedef struct _NvBufferSyncObjRec +{ + NvBufferSyncObjParams insyncobj[NVBUF_MAX_SYNCOBJ_PARAMS]; + uint32_t num_insyncobj; + NvBufferSyncObjParams outsyncobj; + uint32_t use_outsyncobj; +}NvBufferSyncObj; + +/** + * Holds composition background r,g,b colors. + */ +typedef struct +{ + /** background color value for r. */ + float r; + /** background color value for g. */ + float g; + /** background color value for b. */ + float b; +}NvBufferCompositeBackground; + +/** + * Holds coordinates for a rectangle. + */ +typedef struct +{ + /** rectangle top. */ + uint32_t top; + /** rectangle left. */ + uint32_t left; + /** rectangle width. */ + uint32_t width; + /** rectangle height. */ + uint32_t height; +}NvBufferRect; + +/** + * Holds an opaque NvBuffer session type required for parallel buffer + * tranformations and compositions. Operations using a single session are + * scheduled sequentially, after the previous operation finishes. Operations for + * multiple sessions are scheduled in parallel. + */ +typedef struct _NvBufferSession * NvBufferSession; + +/** + * Holds Chroma Subsampling parameters. + */ +typedef struct _NvBufferChromaSubSamplingParams +{ + /** location settings */ + uint8_t chromaLocHoriz; + uint8_t chromaLocVert; +}NvBufferChromaSubsamplingParams; + +#define NVBUF_CHROMA_SUBSAMPLING_PARAMS_DEFAULT \ + { \ + NVBUF_CHROMA_SUBSAMPLING_HORIZ_DEFAULT, \ + NVBUF_CHROMA_SUBSAMPLING_VERT_DEFAULT \ + } + +/** + * Holds the input parameters for hardware buffer creation. + */ +typedef struct _NvBufferCreateParams +{ + /** width of the buffer. */ + int32_t width; + /** height of the buffer. */ + int32_t height; + /** payload type of the buffer. */ + NvBufferPayloadType payloadType; + /** size of the memory.(Applicale for NvBufferPayload_MemHandle) */ + int32_t memsize; + /** layout of the buffer. */ + NvBufferLayout layout; + /** colorformat of the buffer. */ + NvBufferColorFormat colorFormat; + /** tag to associate with the buffer. */ + NvBufferTag nvbuf_tag; +}NvBufferCreateParams; + +/** + * Holds parameters for a hardware buffer. + */ +typedef struct _NvBufferParams +{ + /** Holds the DMABUF FD of the hardware buffer. */ + uint32_t dmabuf_fd; + /** pointer to hardware buffer memory. */ + void *nv_buffer; + /** payload type of the buffer. */ + NvBufferPayloadType payloadType; + /** size of the memory.(Applicale for NvBufferPayload_MemHandle) */ + int32_t memsize; + /** size of hardware buffer. */ + uint32_t nv_buffer_size; + /** video format type of hardware buffer. */ + NvBufferColorFormat pixel_format; + /** number of planes of hardware buffer. */ + uint32_t num_planes; + /** width of each planes of hardware buffer. */ + uint32_t width[MAX_NUM_PLANES]; + /** height of each planes of hardware buffer. */ + uint32_t height[MAX_NUM_PLANES]; + /** pitch of each planes of hardware buffer. */ + uint32_t pitch[MAX_NUM_PLANES]; + /** memory offset values of each video planes of hardware buffer. */ + uint32_t offset[MAX_NUM_PLANES]; + /** size of each vodeo planes of hardware buffer. */ + uint32_t psize[MAX_NUM_PLANES]; + /** layout type of each planes of hardware buffer. */ + uint32_t layout[MAX_NUM_PLANES]; +}NvBufferParams; + +/** + * Holds extended parameters for a hardware buffer. + */ +typedef struct _NvBufferParamsEx +{ + /** nvbuffer basic parameters. */ + NvBufferParams params; + /** offset in bytes from the start of the buffer to the first valid byte. + (Applicale for NvBufferPayload_MemHandle) */ + int32_t startofvaliddata; + /** size of the valid data from the first to the last valid byte. + (Applicale for NvBufferPayload_MemHandle) */ + int32_t sizeofvaliddatainbytes; + /** display scan format - progressive/interlaced. */ + NvBufferDisplayScanFormat scanformat[MAX_NUM_PLANES]; + /** offset of the second field for interlaced buffer. */ + uint32_t secondfieldoffset[MAX_NUM_PLANES]; + /** block height of the planes for blockLinear layout hardware buffer. */ + uint32_t blockheightlog2[MAX_NUM_PLANES]; + /** physical address of allocated planes. */ + uint32_t physicaladdress[MAX_NUM_PLANES]; + /** flags associated with planes */ + uint64_t flags[MAX_NUM_PLANES]; + /** metadata associated with the hardware buffer. */ + void *payloadmetaInfo; + /** chroma subsampling parameters */ + NvBufferChromaSubsamplingParams chromaSubsampling; + /** get buffer vpr information. */ + bool is_protected; + /** buffer sync point object parameters */ + NvBufferSyncObj syncobj; + /** reserved field. */ + void *reserved; +}NvBufferParamsEx; + +/** + * Holds parameters related to compositing/blending. + */ +typedef struct _NvBufferCompositeParams +{ + /** flag to indicate which of the composition/blending parameters are valid. */ + uint32_t composite_flag; + /** number of the input buffers to be composited. */ + uint32_t input_buf_count; + /** filters to use for composition. */ + NvBufferTransform_Filter composite_filter[MAX_COMPOSITE_FRAME]; + /** alpha values of input buffers for the blending. */ + float dst_comp_rect_alpha[MAX_COMPOSITE_FRAME]; + /** source rectangle coordinates of input buffers for composition. */ + NvBufferRect src_comp_rect[MAX_COMPOSITE_FRAME]; + /** destination rectangle coordinates of input buffers for composition. */ + NvBufferRect dst_comp_rect[MAX_COMPOSITE_FRAME]; + /** background color values for composition. */ + NvBufferCompositeBackground composite_bgcolor; + /** NvBufferSession to be used for composition. If NULL, the default session + * is used. */ + NvBufferSession session; +}NvBufferCompositeParams; + +/** + * Holds parameters for buffer transform functions. + */ +typedef struct _NvBufferTransformParams +{ + /** flag to indicate which of the transform parameters are valid. */ + uint32_t transform_flag; + /** flip method. */ + NvBufferTransform_Flip transform_flip; + /** transform filter. */ + NvBufferTransform_Filter transform_filter; + /** source rectangle coordinates for crop opeartion. */ + NvBufferRect src_rect; + /** destination rectangle coordinates for crop opeartion. */ + NvBufferRect dst_rect; + /** NvBufferSession to be used for transform. If NULL, the default session + * is used. */ + NvBufferSession session; +}NvBufferTransformParams; + + +/** +* This method can be used to wait on sync point ID. +* +* @param[in] syncobj_params sync point object parameters. +* @param[in] timeout sync point wait timeout value. +* +* @returns 0 for success, -1 for failure +*/ +int NvBufferSyncObjWait (NvBufferSyncObjParams *syncobj_params, unsigned int timeout); + +/** +* This method can be used to get hardware Buffer struct size. +* +* @returns hardware Buffer struct size. +*/ +int NvBufferGetSize (void); + +/** +* Creates an instance of EGLImage from a DMABUF FD. +* +* @param[in] display An EGLDisplay object used during the creation +* of the EGLImage. If NULL, nvbuf_utils() uses +* its own instance of EGLDisplay. +* @param[in] dmabuf_fd DMABUF FD of the buffer from which the EGLImage +* is to be created. +* +* @returns `EGLImageKHR` for success, `NULL` for failure +*/ +EGLImageKHR NvEGLImageFromFd (EGLDisplay display, int dmabuf_fd); + +/** +* Destroys an EGLImage object. +* +* @param[in] display An EGLDisplay object used to destroy the EGLImage. +* If NULL, nvbuf_utils() uses its own instance of +* EGLDisplay. +* @param[in] eglImage The EGLImageKHR object to be destroyed. +* +* @returns 0 for success, -1 for failure +*/ +int NvDestroyEGLImage (EGLDisplay display, EGLImageKHR eglImage); + +/** + * Allocates a hardware buffer (deprecated). + * + * @deprecated Use NvBufferCreateEx() instead. + * @param[out] dmabuf_fd Returns the DMABUF FD of the hardware buffer. + * @param[in] width Buffer width, in bytes. + * @param[in] height Buffer height, in bytes. + * @param[in] layout Layout of the buffer. + * @param[in] colorFormat Color format of the buffer. + * + * @return 0 if successful, or -1 otherwise. + */ +int NvBufferCreate (int *dmabuf_fd, int width, int height, + NvBufferLayout layout, NvBufferColorFormat colorFormat); + +/** + * Allocates a hardware buffer. + * + * @param[out] dmabuf_fd Returns the DMABUF FD of the hardware buffer. + * @param[in] input_params Input parameters for hardware buffer creation. + * + * @returns 0 for success, -1 for failure + */ +int NvBufferCreateEx (int *dmabuf_fd, NvBufferCreateParams *input_params); + +/** + * Allocates a hardware buffer for interlace scan format. + * + * @param[out] dmabuf_fd Returns the DMABUF FD of the hardware buffer. + * @param[in] input_params Input parameters for hardware buffer creation. + * + * @returns 0 for success, -1 for failure + */ +int NvBufferCreateInterlace (int *dmabuf_fd, NvBufferCreateParams *input_params); + +/** + * Allocates a hardware buffer with a given chroma subsampling location. + * + * @param[in] dmabuf_fd DMABUF FD of the buffer. + * @param[in] input_params Input parameters for hardware buffer creation. + * @param[in] chromaSubsampling Chroma location parameters. + * + * @returns 0 for success, -1 for failure + */ +int NvBufferCreateWithChromaLoc (int *dmabuf_fd, NvBufferCreateParams *input_params, NvBufferChromaSubsamplingParams *chromaSubsampling); + +/** + * Gets buffer parameters. + * @param[in] dmabuf_fd `DMABUF FD` of buffer. + * @param[out] params A pointer to the structure to fill with parameters. + * + * @returns 0 for success, -1 for failure. + */ +int NvBufferGetParams (int dmabuf_fd, NvBufferParams *params); + +/** + * Gets buffer extended parameters. + * @param[in] dmabuf_fd `DMABUF FD` of buffer. + * @param[out] exparams A pointer to the structure to fill with extended parameters. + * + * @returns 0 for success, -1 for failure. + */ +int NvBufferGetParamsEx (int dmabuf_fd, NvBufferParamsEx *exparams); + +/** +* Destroys a hardware buffer. +* @param[in] dmabuf_fd Specifies the `dmabuf_fd` `hw_buffer` to destroy. +* +* @returns 0 for success, -1 for failure. +*/ +int NvBufferDestroy (int dmabuf_fd); + +/** +* Extracts the `dmabuf_fd` from the hardware buffer. +* @param[in] nvbuf Specifies the `hw_buffer`. +* @param[out] dmabuf_fd Returns DMABUF FD of `hw_buffer`. +* +* @returns 0 for success, -1 for failure. +*/ +int ExtractFdFromNvBuffer (void *nvbuf, int *dmabuf_fd); + +/** +* Releases the `dmabuf_fd` buffer. +* @see ExtractfdFromNvBuffer() +* @param[in] dmabuf_fd Specifies the `dmabuf_fd` to release. +* +* @returns 0 for success, -1 for failure. +*/ +int NvReleaseFd (int dmabuf_fd); + +/** +* Syncs the hardware memory cache for the CPU. +* +* \sa NvBufferMemMap for the purpose of the function +* +* @param[in] dmabuf_fd DMABUF FD of buffer. +* @param[in] plane video frame plane. +* @param[in] pVirtAddr Virtual Address pointer of the memory-mapped plane. +* +* @returns 0 for success, -1 for failure. +*/ +int NvBufferMemSyncForCpu (int dmabuf_fd, unsigned int plane, void **pVirtAddr); + +/** +* Syncs the hardware memory cache for the CPU, API to be used for another process. +* +* \sa NvBufferMemMapEx for the purpose of the function +* +* @param[in] dmabuf_fd DMABUF FD of buffer. +* @param[in] exparams extended parameters for a hardware buffer. +* @param[in] plane video frame plane. +* @param[in] pVirtAddr Virtual Address pointer of the memory-mapped plane. +* +* @returns 0 for success, -1 for failure. +*/ +int NvBufferMemSyncForCpuEx (int dmabuf_fd, NvBufferParamsEx *exparams, unsigned int plane, void **pVirtAddr); + +/** +* Syncs the hardware memory cache for the device. +* +* \sa NvBufferMemMap for the purpose of the function +* +* @param[in] dmabuf_fd DMABUF FD of buffer. +* @param[in] plane video frame plane. +* @param[in] pVirtAddr Virtual Address pointer of the memory-mapped plane. +* +* @returns 0 for success, -1 for failure. +*/ +int NvBufferMemSyncForDevice (int dmabuf_fd, unsigned int plane, void **pVirtAddr); + +/** +* Syncs the hardware memory cache for the device, API to be used for another process. +* +* \sa NvBufferMemMapEx for the purpose of the function +* +* @param[in] dmabuf_fd DMABUF FD of buffer. +* @param[in] exparams extended parameters for a hardware buffer. +* @param[in] plane video frame plane. +* @param[in] pVirtAddr Virtual Address pointer of the memory-mapped plane. +* +* @returns 0 for success, -1 for failure. +*/ +int NvBufferMemSyncForDeviceEx (int dmabuf_fd, NvBufferParamsEx *exparams, unsigned int plane, void **pVirtAddr); + +/** +* Gets the memory-mapped virtual address of the plane. +* +* The client must call NvBufferMemSyncForCpu() with the virtual address returned +* by this function before accessing the mapped memory in CPU. +* +* After memory mapping is complete, mapped memory modification +* must be coordinated between the CPU and hardware device as +* follows: +* - CPU: If the CPU modifies any mapped memory, the client must call +* NvBufferMemSyncForDevice() before any hardware device accesses the memory. +* - Hardware device: If the mapped memory is modified by any hardware device, +* the client must call NvBufferMemSyncForCpu() before CPU accesses the memory. +* +* @param[in] dmabuf_fd DMABUF FD of buffer. +* @param[in] plane video frame plane.(Applies to @ref NvBufferPayload_SurfArray.) +* @param[in] memflag NvBuffer memory flag. +* @param[out] pVirtAddr Virtual Address pointer of the memory-mapped plane. +* +* @returns 0 for success, -1 for failure. +*/ +int NvBufferMemMap (int dmabuf_fd, unsigned int plane, NvBufferMemFlags memflag, void **pVirtAddr); + +/** +* Gets the memory-mapped virtual address of the plane, API to be used for another process. +* +* The client must call NvBufferMemSyncForCpuEx() with the virtual address returned +* by this function before accessing the mapped memory in CPU in another process. +* +* After memory mapping is complete, mapped memory modification +* must be coordinated between the CPU and hardware device as +* follows: +* - CPU: If the CPU modifies any mapped memory, the client must call +* NvBufferMemSyncForDeviceEx() before any hardware device accesses the memory. +* - Hardware device: If the mapped memory is modified by any hardware device, +* the client must call NvBufferMemSyncForCpuEx() before CPU accesses the memory. +* +* @param[in] dmabuf_fd DMABUF FD of buffer. +* @param[in] exparams extended parameters for a hardware buffer. +* @param[in] plane video frame plane.(Applies to @ref NvBufferPayload_SurfArray.) +* @param[in] memflag NvBuffer memory flag. +* @param[out] pVirtAddr Virtual Address pointer of the memory-mapped plane. +* +* @returns 0 for success, -1 for failure. +*/ +int NvBufferMemMapEx (int dmabuf_fd, NvBufferParamsEx *exparams, unsigned int plane, NvBufferMemFlags memflag, void **pVirtAddr); + +/** +* Unmaps the mapped virtual address of the plane. +* +* If the following conditions are both true, the client must call +* NvBufferMemSyncForDevice() before unmapping the memory: +* - Mapped memory was modified by the CPU. +* - Mapped memory will be accessed by a hardware device. +* +* @param[in] dmabuf_fd DMABUF FD of the buffer. +* @param[in] plane Video frame plane. Applies to +* @ref NvBufferPayload_SurfArray. +* @param[in] pVirtAddr Virtual address pointer to the memory-mapped plane. +* +* @returns 0 for success, -1 for failure. +*/ +int NvBufferMemUnMap (int dmabuf_fd, unsigned int plane, void **pVirtAddr); + +/** +* Unmaps the mapped virtual address of the plane, API to be used for another process. +* +* If the following conditions are both true, the client must call +* NvBufferMemSyncForDeviceEx() before unmapping the memory in another process: +* - Mapped memory was modified by the CPU. +* - Mapped memory will be accessed by a hardware device. +* +* @param[in] dmabuf_fd DMABUF FD of the buffer. +* @param[in] exparams extended parameters for a hardware buffer. +* @param[in] plane Video frame plane. Applies to +* @ref NvBufferPayload_SurfArray. +* @param[in] pVirtAddr Virtual address pointer to the memory-mapped plane. +* +* @returns 0 for success, -1 for failure. +*/ +int NvBufferMemUnMapEx (int dmabuf_fd, NvBufferParamsEx *exparams, unsigned int plane, void **pVirtAddr); + +/** +* Copies the NvBuffer plane contents to a raw buffer plane. +* @param[in] dmabuf_fd DMABUF FD of NvBuffer. +* @param[in] plane video frame plane. +* @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. +* +* @returns 0 for success, -1 for failure. +*/ +int NvBuffer2Raw (int dmabuf_fd, unsigned int plane, unsigned int out_width, unsigned int out_height, unsigned char *ptr); + +/** +* Copies raw buffer plane contents to an NvBuffer plane. +* @param[in] ptr pointer to the input raw plane data. +* @param[in] plane video frame plane. +* @param[in] in_width aligned width of the raw data plane. +* @param[in] in_height aligned height of the raw data plane. +* @param[in] dmabuf_fd DMABUF FD of NvBuffer. +* +* @returns 0 for success, -1 for failure. +*/ +int Raw2NvBuffer (unsigned char *ptr, unsigned int plane, unsigned int in_width, unsigned int in_height, int dmabuf_fd); + +/** +* Creates a new NvBufferSession for parallel scheduling of +* buffer transformations and compositions. +* +* @returns A session pointer, NULL for failure. +*/ +NvBufferSession NvBufferSessionCreate(void); + +/** +* Destroys an existing \ref NvBufferSession. +* @param[in] session An existing NvBufferSession. +*/ +void NvBufferSessionDestroy(NvBufferSession session); + +/** + * Transforms one DMA buffer to another DMA buffer. + * This function can support transforms for copying, scaling, fliping, rotating, and cropping. + * @param[in] src_dmabuf_fd DMABUF FD of source buffer + * @param[in] dst_dmabuf_fd DMABUF FD of destination buffer + * @param[in] transform_params transform parameters + * + * @return 0 for sucess, -1 for failure. + */ +int NvBufferTransform (int src_dmabuf_fd, int dst_dmabuf_fd, NvBufferTransformParams *transform_params); + +/** + * Transforms one DMA buffer to another DMA buffer, API to be used for another process. + * This function can support transforms for copying, scaling, fliping, rotating, and cropping. + * @param[in] src_dmabuf_fd DMABUF FD of source buffer + * @param[in] input_params extended input parameters for a hardware buffer. + * @param[in] dst_dmabuf_fd DMABUF FD of destination buffer + * @param[in] output_params extended output parameters for a hardware buffer. + * @param[in] transform_params transform parameters + * + * @return 0 for sucess, -1 for failure. + */ +int NvBufferTransformEx (int src_dmabuf_fd, NvBufferParamsEx *input_params, int dst_dmabuf_fd, NvBufferParamsEx *output_params, NvBufferTransformParams *transform_params); + +/** + * Transforms one DMA buffer to another DMA buffer asyncroniously (non-blocking). + * This function can support transforms for copying, scaling, fliping, rotating, and cropping. + * @param[in] src_dmabuf_fd DMABUF FD of source buffer + * @param[in] dst_dmabuf_fd DMABUF FD of destination buffer + * @param[in] transform_params transform parameters + * @param[in] syncobj nvbuffer sync point object + * + * @return 0 for sucess, -1 for failure. + */ +int NvBufferTransformAsync (int src_dmabuf_fd, int dst_dmabuf_fd, NvBufferTransformParams *transform_params, NvBufferSyncObj *syncobj); + + +/** + * \brief Composites multiple input DMA buffers to one output DMA buffer. + * + * This function can composite multiple input frames to one output. + * + * @param[in] src_dmabuf_fds An array of DMABUF FDs of source buffers. + * These buffers are composited together. Output + * is copied to the output buffer referenced by + * @a dst_dmabuf_fd. + * @param[in] dst_dmabuf_fd DMABUF FD of the compositing destination buffer. + * @param[in] composite_params Compositing parameters. + */ +int NvBufferComposite (int *src_dmabuf_fds, int dst_dmabuf_fd, NvBufferCompositeParams *composite_params); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif diff --git a/gst-nvvidconv/nvbufsurface.h b/gst-nvvidconv/nvbufsurface.h new file mode 100644 index 0000000..14d473e --- /dev/null +++ b/gst-nvvidconv/nvbufsurface.h @@ -0,0 +1,740 @@ +/* + * Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** + * @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, + + 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]; + + 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]; + + void * _reserved[STRUCTURE_PADDING * NVBUF_MAX_PLANES]; +} NvBufSurfacePlaneParams; + + +/** + * Holds Chroma Subsampling parameters for NvBufSurface allocation. + */ +typedef struct NvBufSurfaceChromaSubsamplingParams +{ + /** location settings */ + uint8_t chromaLocHoriz; + uint8_t chromaLocVert; +} 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; +} 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; + + 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; + + 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; + +/** + * 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; + + void * _reserved[STRUCTURE_PADDING - 1]; +} 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; + + void * _reserved[STRUCTURE_PADDING]; +} NvBufSurface; + +/** + * \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 outwidth, unsigned int outheight, 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 inwidth, unsigned int inheight, 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); + +/** @} */ + +#ifdef __cplusplus +} +#endif +#endif /* NVBUFSURFACE_H_ */ diff --git a/push_info.txt b/push_info.txt new file mode 100644 index 0000000..5bdfccf --- /dev/null +++ b/push_info.txt @@ -0,0 +1 @@ +jetson_35.2.1