diff --git a/commitFile.txt b/commitFile.txt
new file mode 100644
index 0000000..5d0c461
--- /dev/null
+++ b/commitFile.txt
@@ -0,0 +1,7 @@
+Updating prebuilts and/or headers
+
+e114dc3572c1d3ff56f1a5ad3114b94252fb6966 - gst-nvv4l2camera/Makefile
+85aa07275306e93b61dc11f05d3733ba6a79d17c - gst-nvv4l2camera/3rdpartyheaders.tbz2
+6e6ebff3d31c6038d6f6611c014f45f24377ca18 - gst-nvv4l2camera/gstnvv4l2camerasrc.cpp
+6861c1f1059a2771ef0501014722328bbea6694a - gst-nvv4l2camera/gstnvv4l2camerasrc.hpp
+88370b0b6feb1d5bce7a3de19b31a29334e21dfc - gst-nvv4l2camera/gstnvv4l2camerabufferpool.h
diff --git a/gst-nvv4l2camera/3rdpartyheaders.tbz2 b/gst-nvv4l2camera/3rdpartyheaders.tbz2
new file mode 100644
index 0000000..9a69cc7
Binary files /dev/null and b/gst-nvv4l2camera/3rdpartyheaders.tbz2 differ
diff --git a/gst-nvv4l2camera/Makefile b/gst-nvv4l2camera/Makefile
new file mode 100644
index 0000000..3dab045
--- /dev/null
+++ b/gst-nvv4l2camera/Makefile
@@ -0,0 +1,78 @@
+# Copyright (c) 2019-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:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of NVIDIA CORPORATION 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 ``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 OWNER 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 := libgstnvv4l2camerasrc.so
+
+CC := g++
+
+TARGET_DEVICE = $(shell gcc -dumpmachine | cut -f1 -d -)
+
+GST_INSTALL_DIR?=/usr/lib/aarch64-linux-gnu/gstreamer-1.0/
+LIB_INSTALL_DIR?=/usr/lib/aarch64-linux-gnu/tegra/
+CFLAGS:=
+LIBS:= -lnvbufsurface -lnvbufsurftransform
+
+
+SRCS := $(wildcard *.cpp)
+
+INCLUDES += -I./ -I../
+
+PKGS := gstreamer-1.0 \
+ gstreamer-base-1.0 \
+ gstreamer-video-1.0 \
+ gstreamer-allocators-1.0 \
+ glib-2.0 \
+ libv4l2
+
+OBJS := $(SRCS:.cpp=.o)
+
+CFLAGS += -fPIC \
+ -DEXPLICITLY_ADDED=1 \
+ -DGETTEXT_PACKAGE=1 \
+ -DHAVE_LIBV4L2=1 \
+ -DUSE_V4L2_TARGET_NV=1
+
+CFLAGS += `pkg-config --cflags $(PKGS)`
+
+LDFLAGS = -Wl,--no-undefined -L$(LIB_INSTALL_DIR) -Wl,-rpath,$(LIB_INSTALL_DIR)
+
+LIBS += `pkg-config --libs $(PKGS)`
+
+all: $(SO_NAME)
+
+%.o: %.cpp
+ $(CC) -c $< $(CFLAGS) $(INCLUDES) -o $@
+
+$(SO_NAME): $(OBJS)
+ $(CC) -shared -o $(SO_NAME) $(OBJS) $(LIBS) $(LDFLAGS)
+
+.PHONY: install
+install: $(SO_NAME)
+ cp -vp $(SO_NAME) $(GST_INSTALL_DIR)
+
+.PHONY: clean
+clean:
+ rm -rf $(OBJS) $(SO_NAME)
diff --git a/gst-nvv4l2camera/README.txt b/gst-nvv4l2camera/README.txt
new file mode 100644
index 0000000..01bdbe0
--- /dev/null
+++ b/gst-nvv4l2camera/README.txt
@@ -0,0 +1,49 @@
+# Copyright (c) 2019-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:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of NVIDIA CORPORATION 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 ``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 OWNER 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-nvv4l2camera" 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 \
+ libv4l-dev \
+ libegl1-mesa-dev
+
+2) Download and extract the package "gst-nvv4l2camera_src.tbz2" as follow:
+
+ tar -I lbzip2 -xvf gst-nvv4l2camera_src.tbz2
+
+3) Run the following commands to build and install "libgstnvv4l2camerasrc.so":
+ make
+ make install
+ or
+ DEST_DIR=
make install
+
+ Note: "make install" will copy library "libgstnvv4l2camerasrc.so"
+ into "/usr/lib/aarch64-linux-gnu/gstreamer-1.0" directory.
diff --git a/gst-nvv4l2camera/gstnvv4l2camerabufferpool.h b/gst-nvv4l2camera/gstnvv4l2camerabufferpool.h
new file mode 100644
index 0000000..25cd02b
--- /dev/null
+++ b/gst-nvv4l2camera/gstnvv4l2camerabufferpool.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019-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:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of NVIDIA CORPORATION 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 ``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 OWNER 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 GSTNVV4L2CAMERABUFFERPOOL_H_
+#define GSTNVV4L2CAMERABUFFERPOOL_H_
+
+#include
+
+G_BEGIN_DECLS
+
+typedef struct _GstNvV4l2CameraBufferPool GstNvV4l2CameraBufferPool;
+typedef struct _GstNvV4l2CameraBufferPoolClass GstNvV4l2CameraBufferPoolClass;
+typedef struct _GstNvV4l2CameraBufferPoolPrivate GstNvV4l2CameraBufferPoolPrivate;
+
+#define GST_TYPE_NVV4L2CAMERA_BUFFER_POOL (gst_nvv4l2camera_buffer_pool_get_type())
+#define GST_IS_NVV4L2CAMERA_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_NVV4L2CAMERA_BUFFER_POOL))
+#define GST_NVV4L2CAMERA_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_NVV4L2CAMERA_BUFFER_POOL, GstNvV4l2CameraBufferPool))
+#define GST_NVV4L2CAMERA_BUFFER_POOL_CAST(obj) ((GstNvV4l2CameraBufferPool*)(obj))
+
+#define GST_NVV4L2_MEMORY_TYPE "nvV4l2Memory"
+
+struct _GstNvV4l2CameraBufferPool
+{
+ GstBufferPool bufferpool;
+ GstNvV4l2CameraBufferPoolPrivate *priv;
+ int video_fd;
+};
+
+struct _GstNvV4l2CameraBufferPoolClass
+{
+ GstBufferPoolClass parent_class;
+};
+
+GType gst_nvv4l2camera_buffer_pool_get_type (void);
+
+GstBufferPool* gst_nvv4l2camera_buffer_pool_new (void);
+
+G_END_DECLS
+
+#endif /* GSTNVV4L2CAMERABUFFERPOOL_H_ */
diff --git a/gst-nvv4l2camera/gstnvv4l2camerasrc.cpp b/gst-nvv4l2camera/gstnvv4l2camerasrc.cpp
new file mode 100644
index 0000000..66bd843
--- /dev/null
+++ b/gst-nvv4l2camera/gstnvv4l2camerasrc.cpp
@@ -0,0 +1,1241 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2019-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ * SPDX-License-Identifier: LicenseRef-NvidiaProprietary
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of NVIDIA CORPORATION 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 ``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 OWNER 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.
+ */
+
+/**
+ * Sample pipeline
+ *
+ * gst-launch-1.0 nvv4l2camerasrc device=/dev/video3 !
+ * 'video/x-raw(memory:NVMM), format=(string)UYVY, width=(int)1920, height=(int)576, interlace-mode=interlaced, framerate=(fraction)25/1' !
+ * nvdeinterlace mode=3 !
+ * 'video/x-raw(memory:NVMM), format=(string)NV12' !
+ * nv3dsink
+ */
+
+/* Gstreamer includes */
+#include
+#include
+#include
+
+/* Basic I/O includes */
+#include
+#include
+#include
+
+/* Library header include */
+#include "nvbufsurface.h"
+#include "gstnvv4l2camerasrc.hpp"
+#include "gstnvv4l2camerabufferpool.h"
+
+/* v4l2 specific includes */
+#include
+#include
+#include
+
+/* Capture caps of plugin */
+#define CAPTURE_CAPS \
+ "video/x-raw(memory:NVMM), " \
+ "width = (int) [ 1, MAX ], " \
+ "height = (int) [ 1, MAX ], " \
+ "format = (string) { UYVY }, " \
+ "interlace-mode = (string) { progressive, interlaced }, " \
+ "framerate = (fraction) [ 0, MAX ];"
+
+GST_DEBUG_CATEGORY_STATIC (gst_nv_v4l2_camera_src_debug);
+#define GST_CAT_DEFAULT gst_nv_v4l2_camera_src_debug
+
+#define MAX_SEARCH_COUNT 32
+
+enum
+{
+ PROP_0,
+ PROP_DEVICE,
+ PROP_CAPTURE_BUFFERS
+};
+
+struct _GstNVV4l2Memory
+{
+ GstMemory mem;
+ GstNvV4l2CameraSrcBuffer *nvcam_buf;
+};
+
+struct _GstNVV4l2MemoryAllocator
+{
+ GstAllocator parent;
+ GstNvV4l2CameraSrc *owner;
+};
+
+struct _GstNVV4l2MemoryAllocatorClass
+{
+ GstAllocatorClass parent_class;
+};
+
+static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (CAPTURE_CAPS)
+ );
+
+struct _GstNvV4l2CameraBufferPoolPrivate
+{
+ GstCaps *caps;
+ GstVideoInfo info;
+ GstAllocator *allocator;
+ GstAllocationParams params;
+ guint size;
+};
+
+typedef struct _GstNVV4l2Memory GstNVV4l2Memory;
+typedef struct _GstNVV4l2MemoryAllocator GstNVV4l2MemoryAllocator;
+typedef struct _GstNVV4l2MemoryAllocatorClass GstNVV4l2MemoryAllocatorClass;
+
+GType gst_nv_memory_allocator_get_type (void);
+#define GST_TYPE_NV_MEMORY_ALLOCATOR (gst_nv_memory_allocator_get_type())
+
+#define gst_nvv4l2camera_buffer_pool_parent_class bpool_parent_class
+G_DEFINE_TYPE_WITH_CODE (GstNvV4l2CameraBufferPool, gst_nvv4l2camera_buffer_pool, GST_TYPE_BUFFER_POOL, G_ADD_PRIVATE(GstNvV4l2CameraBufferPool));
+
+#define gst_nv_v4l2_camera_src_parent_class parent_class
+G_DEFINE_TYPE (GstNvV4l2CameraSrc, gst_nv_v4l2_camera_src, GST_TYPE_BASE_SRC);
+G_DEFINE_TYPE (GstNVV4l2MemoryAllocator, gst_nv_memory_allocator, GST_TYPE_ALLOCATOR);
+
+#define GST_NVMEMORY_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NV_MEMORY_ALLOCATOR,GstNVV4l2MemoryAllocator))
+
+static gpointer
+gst_nv_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
+{
+ GstNVV4l2Memory *nvmm_mem = (GstNVV4l2Memory *) mem;
+ if (nvmm_mem == NULL) {
+ GST_ERROR("%s: NULL GstNVV4l2Memory\n", __func__);
+ goto error;
+ }
+
+ return (gpointer)(nvmm_mem->nvcam_buf->surface);
+
+error:
+ return NULL;
+}
+
+static void
+gst_nv_memory_unmap (GstMemory * mem)
+{
+ /* Nothing needs to be done */
+}
+
+static GstMemory *
+gst_nv_memory_share (GstMemory * mem, gssize offset, gssize size)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
+/* In this function, plugin will allocate interlaced or progressive buffers
+ * depending upon the interlaced_flag.
+ * */
+static GstMemory *
+gst_nv_memory_allocator_alloc (GstAllocator * allocator,
+ gsize size, GstAllocationParams * params)
+{
+ gint ret = 0;
+ GstNVV4l2Memory *mem = NULL;
+ GstNvV4l2CameraSrcBuffer *nvbuf = NULL;
+ GstMemoryFlags flags = GST_MEMORY_FLAG_NO_SHARE;
+
+ GST_DEBUG ("%s:\n", __func__);
+
+ GstNVV4l2MemoryAllocator *nvmm_allocator = GST_NVMEMORY_ALLOCATOR (allocator);
+ GstNvV4l2CameraSrc *self = (GstNvV4l2CameraSrc*) nvmm_allocator->owner;
+ if (self == NULL) {
+ GST_ERROR_OBJECT(allocator, "NULL NvV4l2CameraSrc");
+ return NULL;
+ }
+
+ mem = g_slice_new0 (GstNVV4l2Memory);
+ nvbuf = g_slice_new0 (GstNvV4l2CameraSrcBuffer);
+
+ NvBufSurfaceAllocateParams param = {{0}};
+ param.params.width = self->width;
+ param.params.height = self->height;
+ param.params.layout = NVBUF_LAYOUT_PITCH;
+ param.params.memType = NVBUF_MEM_SURFACE_ARRAY;
+ param.params.gpuId = 0;
+ param.params.colorFormat = NVBUF_COLOR_FORMAT_UYVY;
+ param.memtag = NvBufSurfaceTag_CAMERA;
+
+ if (self->interlaced_flag)
+ {
+ GST_ERROR("interlaced stream not supported \n");
+ goto error;
+ }
+
+ ret = NvBufSurfaceAllocate (&nvbuf->surface, 1, ¶m);
+
+ if (ret != 0) {
+ GST_ERROR ("%s: NvBufSurfaceAllocate Failed \n", __func__);
+ goto error;
+ }
+
+ nvbuf->surface->numFilled = 1;
+
+ gst_memory_init (GST_MEMORY_CAST (mem), flags, allocator, NULL,
+ sizeof(NvBufSurface), 0 /* Alignment */,
+ 0, sizeof(NvBufSurface));
+
+ nvbuf->dmabuf_fd = nvbuf->surface->surfaceList[0].bufferDesc;
+
+ mem->nvcam_buf = nvbuf;
+ mem->nvcam_buf->dmabuf_fd = nvbuf->dmabuf_fd;
+
+ /* Prepare empty buffers to queue to v4l2 camera device */
+ mem->nvcam_buf->buffer = (struct v4l2_buffer *) g_malloc (sizeof (struct v4l2_buffer));
+ if (mem->nvcam_buf->buffer == NULL)
+ goto error;
+
+ memset(mem->nvcam_buf->buffer, 0, sizeof (struct v4l2_buffer));
+ mem->nvcam_buf->buffer->index = self->index;
+ mem->nvcam_buf->buffer->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ mem->nvcam_buf->buffer->memory = V4L2_MEMORY_DMABUF;
+ mem->nvcam_buf->buffer->m.fd = nvbuf->dmabuf_fd;
+
+ self->index++;
+
+ return GST_MEMORY_CAST (mem);
+
+error:
+ GST_DEBUG ("%s: FAILED\n", __func__);
+ g_slice_free (GstNvV4l2CameraSrcBuffer, nvbuf);
+ g_slice_free (GstNVV4l2Memory, mem);
+ return NULL;
+}
+
+/* In this function, plugin will deallocate interlaced or progressive buffers.
+ * This function is called when buffer pool is set to inactive and all buffers
+ * are released.
+ * */
+static void
+gst_nv_memory_allocator_free (GstAllocator * allocator, GstMemory * mem)
+{
+ gint ret = 0;
+
+ GST_DEBUG ("%s:\n", __func__);
+
+ GstNVV4l2Memory *nv_mem = (GstNVV4l2Memory *) mem;
+ if (nv_mem == NULL)
+ return;
+
+ GstNvV4l2CameraSrcBuffer *nvbuf = nv_mem->nvcam_buf;
+ if (nvbuf == NULL) {
+ GST_DEBUG ("%s: NULL Buffer \n", __func__);
+ g_slice_free (GstNVV4l2Memory, nv_mem);
+ return;
+ }
+
+ ret = NvBufSurfaceDestroy (nvbuf->surface);
+ if (ret != 0)
+ GST_ERROR ("%s: NvBufSurfaceDestroy Failed \n", __func__);
+
+ g_free (nv_mem->nvcam_buf->buffer);
+ nv_mem->nvcam_buf->buffer = NULL;
+ g_slice_free (GstNvV4l2CameraSrcBuffer, nvbuf);
+ g_slice_free (GstNVV4l2Memory, nv_mem);
+}
+
+static void
+gst_nv_memory_allocator_class_init (GstNVV4l2MemoryAllocatorClass * klass)
+{
+ GstAllocatorClass *allocator_class;
+ allocator_class = (GstAllocatorClass *) klass;
+
+ allocator_class->alloc = gst_nv_memory_allocator_alloc;
+ allocator_class->free = gst_nv_memory_allocator_free;
+}
+
+static void
+gst_nv_memory_allocator_init (GstNVV4l2MemoryAllocator * allocator)
+{
+ GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
+
+ alloc->mem_type = GST_NVV4L2_MEMORY_TYPE;
+ alloc->mem_map = gst_nv_memory_map;
+ alloc->mem_unmap = gst_nv_memory_unmap;
+ alloc->mem_share = gst_nv_memory_share;
+
+ /* default copy & is_span */
+ GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
+}
+
+static GstFlowReturn gst_nvv4l2camera_buffer_pool_acquire_buffer (
+ GstBufferPool *bpool, GstBuffer **buffer,
+ GstBufferPoolAcquireParams *params)
+{
+ GstFlowReturn ret = GST_FLOW_OK;
+ GstMemory *mem = NULL;
+ GstNVV4l2Memory *nv_mem = NULL;
+ struct v4l2_buffer tmp_v4l2_buf;
+ gint r = 0, i = 0;
+
+ GST_DEBUG_OBJECT (bpool, "acquire_buffer");
+
+ g_return_val_if_fail (GST_IS_BUFFER_POOL (bpool), GST_FLOW_ERROR);
+
+ GstNvV4l2CameraBufferPool *pool = GST_NVV4L2CAMERA_BUFFER_POOL (bpool);
+ GstNvV4l2CameraBufferPoolPrivate *priv = pool->priv;
+ if (!priv) {
+ GST_ERROR_OBJECT(pool, "NULL GstNvV4l2CameraBufferPoolPrivate");
+ return GST_FLOW_ERROR;
+ }
+
+ GstNVV4l2MemoryAllocator *nvmm_allocator = GST_NVMEMORY_ALLOCATOR (priv->allocator);
+ if (!nvmm_allocator) {
+ GST_ERROR_OBJECT(pool, "NULL GstNVV4l2MemoryAllocator");
+ return GST_FLOW_ERROR;
+ }
+
+ GstNvV4l2CameraSrc *src = (GstNvV4l2CameraSrc*) nvmm_allocator->owner;
+ if (!src) {
+ GST_ERROR_OBJECT(pool, "NULL GstNvV4l2CameraSrc");
+ return GST_FLOW_ERROR;
+ }
+
+ /*
+ * Currently, we are using base class version because we are not attaching
+ * anything extra to buffers. If we need to do so We will modify this function
+ * accordingly.
+ */
+ ret = GST_BUFFER_POOL_CLASS (bpool_parent_class)->acquire_buffer (bpool, buffer, params);
+
+ mem = gst_buffer_peek_memory (*buffer, 0);
+ if (!mem) {
+ goto no_memblk;
+ }
+
+ /* Setting timeout value of select to 5, this can be configured as required */
+ src->tv.tv_sec = DEQUE_TIMEOUT;
+
+ /* select the ready descriptor */
+ r = select(pool->video_fd + 1, &(src->read_set), NULL, NULL, &(src->tv));
+ if (0 == r) {
+ goto timeout_error;
+ }
+
+ if (-1 == r) {
+ goto select_error;
+ }
+
+ nv_mem = (GstNVV4l2Memory *) mem;
+ memset(nv_mem->nvcam_buf->buffer, 0, sizeof (struct v4l2_buffer));
+ nv_mem->nvcam_buf->buffer->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ nv_mem->nvcam_buf->buffer->memory = V4L2_MEMORY_DMABUF;
+ if (-1 == ioctl(pool->video_fd, VIDIOC_DQBUF, nv_mem->nvcam_buf->buffer))
+ goto dqbuf_error;
+
+ /* Search the buffer which driver returned */
+ if (nv_mem->nvcam_buf->buffer->m.fd != nv_mem->nvcam_buf->dmabuf_fd) {
+ memcpy (&tmp_v4l2_buf, nv_mem->nvcam_buf->buffer, sizeof (struct v4l2_buffer));
+ for (i = 0; i < MAX_SEARCH_COUNT; i ++) {
+ if (tmp_v4l2_buf.m.fd == nv_mem->nvcam_buf->dmabuf_fd)
+ break;
+
+ GST_WARNING_OBJECT(pool, "Search camera output buffer. Driver out fd: %d camera buffer fd: %d", tmp_v4l2_buf.m.fd, nv_mem->nvcam_buf->dmabuf_fd);
+
+ GST_BUFFER_POOL_CLASS (bpool_parent_class)->release_buffer (bpool, *buffer);
+ ret = GST_BUFFER_POOL_CLASS (bpool_parent_class)->acquire_buffer (bpool, buffer, params);
+
+ mem = gst_buffer_peek_memory (*buffer, 0);
+ if (!mem) {
+ goto no_memblk;
+ }
+ nv_mem = (GstNVV4l2Memory *) mem;
+ }
+ if (i == MAX_SEARCH_COUNT) {
+ goto no_buffer;
+ }
+ memcpy (nv_mem->nvcam_buf->buffer, &tmp_v4l2_buf, sizeof (struct v4l2_buffer));
+ }
+
+ return ret;
+
+no_memblk:
+ {
+ GST_ERROR_OBJECT(pool, "No memory block");
+ ret = GST_FLOW_ERROR;
+ return ret;
+ }
+dqbuf_error:
+ {
+ GST_ERROR_OBJECT(pool, "VIDIOC_DQBUF failed");
+ src->stop_requested = TRUE;
+ ret = GST_FLOW_OK;
+ return ret;
+ }
+timeout_error:
+ {
+ GST_ERROR_OBJECT(pool, "Timeout Error");
+ src->stop_requested = TRUE;
+ ret = GST_FLOW_OK;
+ return ret;
+ }
+select_error:
+ {
+ perror ("select");
+ GST_ERROR_OBJECT(pool, "Select Error");
+ src->stop_requested = TRUE;
+ ret = GST_FLOW_OK;
+ return ret;
+ }
+no_buffer:
+ {
+ GST_ERROR_OBJECT(pool, "Not found buffer which driver returned");
+ ret = GST_FLOW_ERROR;
+ return ret;
+ }
+}
+
+static GstFlowReturn
+gst_nvv4l2camera_buffer_pool_alloc_buffer (GstBufferPool *bpool,
+ GstBuffer **buffer, GstBufferPoolAcquireParams *params)
+{
+ GstBuffer *buf = NULL;
+ GstMemory *mem = NULL;
+
+ GST_DEBUG_OBJECT (bpool, "alloc_buffer");
+
+ g_return_val_if_fail (GST_IS_BUFFER_POOL (bpool), GST_FLOW_ERROR);
+
+ GstNvV4l2CameraBufferPool *pool = GST_NVV4L2CAMERA_BUFFER_POOL (bpool);
+ GstNvV4l2CameraBufferPoolPrivate *priv = pool->priv;
+ if (priv == NULL) {
+ *buffer = NULL;
+ return GST_FLOW_ERROR;
+ }
+
+ if (!g_strcmp0(priv->allocator->mem_type, GST_NVV4L2_MEMORY_TYPE)) {
+ mem = gst_nv_memory_allocator_alloc (priv->allocator, priv->size,
+ &priv->params);
+ g_return_val_if_fail (mem, GST_FLOW_ERROR);
+
+ buf = gst_buffer_new ();
+ g_return_val_if_fail (buf, GST_FLOW_ERROR);
+
+ gst_buffer_append_memory (buf, mem);
+ } else {
+ buf = gst_buffer_new_allocate (priv->allocator, priv->size,
+ &priv->params);
+
+ g_return_val_if_fail (buf, GST_FLOW_ERROR);
+ }
+
+ *buffer = buf;
+ return GST_FLOW_OK;
+}
+
+static void
+gst_nvv4l2camera_buffer_pool_finalize (GObject *object)
+{
+ GstNvV4l2CameraBufferPool *pool = GST_NVV4L2CAMERA_BUFFER_POOL (object);
+ GstNvV4l2CameraBufferPoolPrivate *priv = pool->priv;
+
+ if (priv) {
+ if (priv->caps)
+ gst_caps_unref (priv->caps);
+ priv->caps = NULL;
+
+ if (priv->allocator)
+ gst_object_unref (priv->allocator);
+ priv->allocator = NULL;
+ }
+
+ G_OBJECT_CLASS (bpool_parent_class)->finalize (object);
+}
+
+static void
+gst_nvv4l2camera_buffer_pool_free_buffer (GstBufferPool *bpool,
+ GstBuffer *buffer)
+{
+ GstNvV4l2CameraBufferPool *pool = GST_NVV4L2CAMERA_BUFFER_POOL (bpool);
+ GST_DEBUG_OBJECT (pool, "free_buffer");
+ GST_BUFFER_POOL_CLASS (bpool_parent_class)->free_buffer (bpool, buffer);
+}
+
+static void gst_nvv4l2camera_buffer_pool_init (GstNvV4l2CameraBufferPool *pool)
+{
+ GstNvV4l2CameraBufferPool *self = GST_NVV4L2CAMERA_BUFFER_POOL (pool);
+ pool->priv = (GstNvV4l2CameraBufferPoolPrivate *) gst_nvv4l2camera_buffer_pool_get_instance_private (self);
+
+ memset (pool->priv, 0, sizeof(GstNvV4l2CameraBufferPoolPrivate));
+
+ pool->priv->allocator = (GstAllocator *) g_object_new (
+ gst_nv_memory_allocator_get_type (), NULL);
+
+ gst_allocation_params_init (&pool->priv->params);
+
+ GST_DEBUG_OBJECT (pool, "created");
+}
+
+GstBufferPool * gst_nvv4l2camera_buffer_pool_new (void)
+{
+ GstNvV4l2CameraBufferPool *pool;
+ pool = (GstNvV4l2CameraBufferPool *) g_object_new (GST_TYPE_NVV4L2CAMERA_BUFFER_POOL, NULL);
+ if (!pool)
+ GST_DEBUG ("NULL GstNvV4l2CameraBufferPool\n");
+
+ return GST_BUFFER_POOL (pool);
+}
+
+static void gst_nvv4l2camera_buffer_pool_release_buffer (GstBufferPool *bpool,
+ GstBuffer *buffer)
+{
+ GstMemory *mem = NULL;
+ GstNVV4l2Memory *nv_mem = NULL;
+
+ g_return_if_fail (GST_IS_BUFFER_POOL (bpool));
+
+ GST_DEBUG_OBJECT (bpool, "release_buffer");
+
+ GstNvV4l2CameraBufferPool *pool = GST_NVV4L2CAMERA_BUFFER_POOL (bpool);
+
+ mem = gst_buffer_peek_memory (buffer, 0);
+
+ nv_mem = (GstNVV4l2Memory *) mem;
+ if (nv_mem && (nv_mem->nvcam_buf->buffer != NULL)) {
+ if(-1 == ioctl(pool->video_fd, VIDIOC_QBUF, nv_mem->nvcam_buf->buffer))
+ GST_ERROR_OBJECT(pool, "VIDIOC_QBUF failed :%s", g_strerror (errno));
+ }
+
+ GST_BUFFER_POOL_CLASS (bpool_parent_class)->release_buffer (bpool, buffer);
+}
+
+static gboolean
+gst_nvv4l2camera_buffer_pool_set_config (GstBufferPool *bpool, GstStructure *config)
+{
+ GstCaps *caps = NULL;
+ GstAllocator *allocator = NULL;
+ GstAllocationParams params = { (GstMemoryFlags)0, 0, 0, 0, };
+ GstVideoInfo info = {0};
+ guint size = 0;
+
+ g_return_val_if_fail (GST_IS_BUFFER_POOL (bpool), FALSE);
+ g_return_val_if_fail (config != NULL, FALSE);
+
+ GstNvV4l2CameraBufferPool *pool = GST_NVV4L2CAMERA_BUFFER_POOL (bpool);
+ GstNvV4l2CameraBufferPoolPrivate *priv = pool->priv;
+ if (priv == NULL) {
+ GST_ERROR("No pool initialized\n");
+ return FALSE;
+ }
+
+ GST_OBJECT_LOCK (pool);
+
+ if (!gst_buffer_pool_config_get_params (config, &caps, &size, NULL, NULL))
+ goto wrong_config;
+
+ if (caps == NULL)
+ goto no_caps;
+
+ if (!gst_video_info_from_caps (&info, caps))
+ goto wrong_video_caps;
+
+ priv->info = info;
+ priv->size = size;
+
+ if (!priv->size)
+ priv->size = info.size;
+
+ if (priv->caps)
+ gst_caps_unref (priv->caps);
+ priv->caps = gst_caps_ref (caps);
+
+ if (!gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms))
+ goto wrong_config;
+
+ if (allocator) {
+ // Update user provided allocator
+ if (priv->allocator)
+ gst_object_unref (priv->allocator);
+ if ((priv->allocator = allocator))
+ gst_object_ref (allocator);
+
+ priv->params = params;
+ }
+
+ if (!allocator) {
+ // Allocator is not set, use private allocator.
+ gst_buffer_pool_config_set_allocator (config, priv->allocator,
+ &priv->params);
+ }
+
+ GST_OBJECT_UNLOCK (pool);
+
+ return GST_BUFFER_POOL_CLASS (bpool_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 video info from caps %" GST_PTR_FORMAT, caps);
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_nvv4l2camera_buffer_pool_start (GstBufferPool *bpool)
+{
+ GstNvV4l2CameraBufferPool *pool = GST_NVV4L2CAMERA_BUFFER_POOL (bpool);
+
+ GST_DEBUG_OBJECT (pool, "start");
+
+ return GST_BUFFER_POOL_CLASS (bpool_parent_class)->start (bpool);
+}
+
+static gboolean gst_nvv4l2camera_buffer_pool_stop (GstBufferPool *bpool)
+{
+ GstNvV4l2CameraBufferPool *pool = GST_NVV4L2CAMERA_BUFFER_POOL (bpool);
+
+ GST_DEBUG_OBJECT (pool, "stop");
+
+ return GST_BUFFER_POOL_CLASS (bpool_parent_class)->stop (bpool);
+}
+
+static void
+gst_nvv4l2camera_buffer_pool_class_init (GstNvV4l2CameraBufferPoolClass *klass)
+{
+
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
+
+ gobject_class->finalize = gst_nvv4l2camera_buffer_pool_finalize;
+ gstbufferpool_class->start = gst_nvv4l2camera_buffer_pool_start;
+ gstbufferpool_class->stop = gst_nvv4l2camera_buffer_pool_stop;
+ gstbufferpool_class->set_config = gst_nvv4l2camera_buffer_pool_set_config;
+ gstbufferpool_class->alloc_buffer = gst_nvv4l2camera_buffer_pool_alloc_buffer;
+ gstbufferpool_class->free_buffer = gst_nvv4l2camera_buffer_pool_free_buffer;
+ gstbufferpool_class->acquire_buffer = gst_nvv4l2camera_buffer_pool_acquire_buffer;
+ gstbufferpool_class->release_buffer = gst_nvv4l2camera_buffer_pool_release_buffer;
+
+ GST_DEBUG_CATEGORY_INIT (gst_nv_v4l2_camera_src_debug, "nvv4l2camerapool", 0,
+ "nvv4l2camera buffer pool object");
+}
+
+static void gst_nv_v4l2_camera_src_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_nv_v4l2_camera_src_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+static void gst_nv_v4l2_camera_src_finalize (GObject *object);
+
+/* GObject vmethod implementations */
+
+static GstCaps * gst_nv_v4l2_camera_fixate (GstBaseSrc *src, GstCaps *caps)
+{
+ GstStructure *structure = NULL;
+ gboolean ret = TRUE;
+
+ g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
+
+ caps = gst_caps_make_writable (caps);
+
+ structure = gst_caps_get_structure (caps, 0);
+ if (structure == NULL) {
+ GST_ERROR_OBJECT (src, "Invalid caps structure");
+ return NULL;
+ }
+
+ /* Default fixated to progressive mode */
+ ret = gst_structure_fixate_field_nearest_int (structure, "width", 1920);
+ ret = gst_structure_fixate_field_nearest_int (structure, "height", 1080);
+ ret = gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1);
+
+ if (!ret)
+ GST_WARNING_OBJECT (src, "Unable to fixate caps structure");
+
+ caps = GST_BASE_SRC_CLASS (gst_nv_v4l2_camera_src_parent_class)->fixate (src, caps);
+
+ return caps;
+}
+
+static gboolean gst_nv_v4l2_camera_set_caps (GstBaseSrc *base, GstCaps *caps)
+{
+ GstVideoInfo info = {0};
+ GstCaps *old = NULL;
+ GstStructure *config = NULL;
+ GstNVV4l2MemoryAllocator *allocator = NULL;
+ GstStructure *structure = NULL;
+ enum v4l2_buf_type buf_type;
+ struct v4l2_streamparm streamparm = {};
+
+ GstNvV4l2CameraSrc *src = GST_NVV4L2CAMERASRC (base);
+
+ GST_DEBUG_OBJECT (src, "Received caps %" GST_PTR_FORMAT, caps);
+
+ if (!gst_video_info_from_caps (&info, caps))
+ {
+ GST_ERROR_OBJECT (src, "Invalid caps");
+ return FALSE;
+ }
+
+ structure = gst_caps_get_structure (caps, 0);
+ if (structure == NULL) {
+ GST_ERROR_OBJECT (src, "Invalid caps structure");
+ return FALSE;
+ }
+
+ if (gst_structure_has_field (structure, "interlace-mode")) {
+ /* interlace-mode field present with incaps */
+ if (!g_strcmp0 (gst_structure_get_string (structure, "interlace-mode"), "interlaced"))
+ {
+ src->interlaced_flag = TRUE;
+ GST_DEBUG_OBJECT (src, "interlace-mode set to interlaced mode\n");
+ }
+ else
+ {
+ src->interlaced_flag = FALSE;
+ GST_DEBUG_OBJECT (src, "interlace-mode set to progressive mode\n");
+ }
+ } else {
+ GST_DEBUG_OBJECT (src, "interlace-mode field not present in sink caps, setting to progressive mode\n");
+ src->interlaced_flag = FALSE;
+ }
+
+ src->width = info.width;
+ /* height is divided by 2 for setting the format with VIDIOC_S_FMT,
+ * as driver expects height of top and bottom field
+ * */
+ if (src->interlaced_flag)
+ src->height = info.height / 2;
+ else
+ src->height = info.height;
+ src->fps_n = info.fps_n;
+ src->fps_d = info.fps_d;
+
+ if ((old = src->outcaps) != caps)
+ {
+ if (caps)
+ src->outcaps = gst_caps_copy (caps);
+ else
+ src->outcaps = NULL;
+ if (old)
+ gst_caps_unref (old);
+ }
+
+ /* VIDIOC_S_FMT IOCTL on v4l2 device */
+ src->fmt->fmt.pix_mp.width = src->width;
+ src->fmt->fmt.pix_mp.height = src->height;
+ src->fmt->fmt.pix.bytesperline = src->width * 2;
+ if (-1 == ioctl(src->video_fd, VIDIOC_S_FMT, src->fmt)) {
+ GST_ERROR_OBJECT(src, "VIDIOC_S_FMT on %s device", src->videodev);
+ goto fmt_error;
+ }
+
+ /* Set framerate based on given parameters */
+ memset (&streamparm, 0x00, sizeof (struct v4l2_streamparm));
+ streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (ioctl (src->video_fd, VIDIOC_G_PARM, &streamparm) < 0) {
+ goto fmt_error;
+ }
+
+ /* Change the frame rate if camera driver has the capability */
+ if ((streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) != 0) {
+ streamparm.parm.capture.timeperframe.numerator = info.fps_d;
+ streamparm.parm.capture.timeperframe.denominator = info.fps_n;
+ if (ioctl (src->video_fd, VIDIOC_S_PARM, &streamparm)) {
+ goto fmt_error;
+ }
+
+ src->fps_d = streamparm.parm.output.timeperframe.numerator;
+ src->fps_n = streamparm.parm.output.timeperframe.denominator;
+ if (src->fps_d != info.fps_d || src->fps_n != info.fps_n) {
+ g_print ("Requested frame rate not supported. Fall back to %u/%u\n", src->fps_n, src->fps_d);
+ }
+ }
+
+
+ /* Requesting buffers for camera */
+ src->req = (struct v4l2_requestbuffers *) g_malloc (sizeof (struct v4l2_requestbuffers));
+ if (src->req == NULL) {
+ goto fmt_error;
+ }
+
+ memset(src->req, 0, sizeof(struct v4l2_requestbuffers));
+ src->req->count = src->cap_buf;
+ src->req->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ src->req->memory = V4L2_MEMORY_DMABUF;
+
+ if (-1 == ioctl(src->video_fd, VIDIOC_REQBUFS, src->req))
+ goto req_error;
+
+
+ if (src->pool) {
+ gst_object_unref (src->pool);
+ src->pool = NULL;
+ }
+ src->pool = gst_nvv4l2camera_buffer_pool_new ();
+ if (!src->pool)
+ goto buffer_pool_new_failed;
+
+ ((GstNvV4l2CameraBufferPool *)src->pool)->video_fd = src->video_fd;
+
+ allocator = (GstNVV4l2MemoryAllocator *) g_object_new (gst_nv_memory_allocator_get_type (), NULL);
+ if (!allocator) {
+ GST_ERROR_OBJECT(src->pool, "Failed to create GstNVV4l2MemoryAllocator");
+ if (gst_buffer_pool_is_active (src->pool)) {
+ gst_buffer_pool_set_active (src->pool, FALSE);
+ }
+ gst_object_unref (src->pool);
+ src->pool = NULL;
+ g_free (src->fmt);
+ src->fmt = NULL;
+ g_free (src->req);
+ src->req = NULL;
+ return FALSE;
+ }
+
+ allocator->owner = src;
+ config = gst_buffer_pool_get_config (src->pool);
+ gst_buffer_pool_config_set_allocator (config, GST_ALLOCATOR (allocator), NULL);
+
+ gst_buffer_pool_config_set_params (config, src->outcaps, sizeof(NvBufSurface), src->cap_buf, src->cap_buf);
+
+ gst_buffer_pool_set_config (src->pool, config);
+
+ if (allocator)
+ gst_object_unref (allocator);
+
+ gst_buffer_pool_set_active (src->pool, TRUE);
+
+ buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ /* VIDIOC_STREAMON IOCTL on v4l2 camera device */
+ if(-1 == ioctl(src->video_fd, VIDIOC_STREAMON, &buf_type))
+ {
+ goto streamon_error;
+ }
+
+ /* clear the read descriptor set */
+ FD_ZERO(&(src->read_set));
+
+ /* set src->video_fd in read_set */
+ FD_SET(src->video_fd, &(src->read_set));
+
+ /* Setting timeout value of select to 5, this can be configured as required */
+ src->tv = (struct timeval){ 0 };
+ src->tv.tv_sec = DEQUE_TIMEOUT;
+
+ return TRUE;
+
+fmt_error:
+ {
+ g_free (src->fmt);
+ src->fmt= NULL;
+ return FALSE;
+ }
+req_error:
+ {
+ GST_ERROR_OBJECT(src, "VIDIOC_REQBUFS on %s device", src->videodev);
+ goto cleanup;
+ }
+buffer_pool_new_failed:
+ {
+ GST_ERROR_OBJECT(src, "Buffer pool creation on %s device", src->videodev);
+ goto cleanup;
+ }
+streamon_error:
+ {
+ GST_ERROR_OBJECT(src, "VIDIOC_STREAMON on %s device", src->videodev);
+ if (gst_buffer_pool_is_active (src->pool)) {
+ gst_buffer_pool_set_active (src->pool, FALSE);
+ }
+ gst_object_unref (src->pool);
+ src->pool = NULL;
+ }
+cleanup:
+ {
+ g_free (src->fmt);
+ src->fmt = NULL;
+ g_free (src->req);
+ src->req = NULL;
+ return FALSE;
+ }
+}
+
+static gboolean gst_nv_v4l2_camera_start (GstBaseSrc * src_base)
+{
+ /* TODO, move this opening code to gst_nv_v4l2_camera_change_state */
+ GstNvV4l2CameraSrc *src = (GstNvV4l2CameraSrc *) src_base;
+ src->index = 0;
+
+ /* open the device */
+ src->video_fd = open (src->videodev, O_RDWR /* | O_NONBLOCK */ );
+
+ if (src->video_fd < 0)
+ goto open_error;
+ else
+ {
+ /* VIDIOC_QUERYCAP IOCTL on v4l2 device */
+ src->caps = (struct v4l2_capability *) g_malloc (sizeof (struct v4l2_capability));
+ if (src->caps == NULL)
+ {
+ GST_ERROR_OBJECT(src, "Caps allocation failed");
+ return FALSE;
+ }
+ memset(src->caps, 0, sizeof(struct v4l2_capability));
+ if (-1 == ioctl(src->video_fd, VIDIOC_QUERYCAP, src->caps))
+ goto caps_error;
+
+ if(!(src->caps->capabilities & V4L2_CAP_VIDEO_CAPTURE))
+ {
+ goto caps_error;
+ }
+ if (!(src->caps->capabilities & V4L2_CAP_STREAMING))
+ {
+ goto caps_error;
+ }
+
+ /* VIDIOC_G_FMT IOCTL on v4l2 device */
+ src->fmt = (struct v4l2_format *) g_malloc (sizeof (struct v4l2_format));
+ if (src->fmt == NULL) {
+ GST_ERROR_OBJECT(src, "Format allocation failed");
+ g_free (src->caps);
+ src->caps = NULL;
+ return FALSE;
+ }
+ memset(src->fmt, 0, sizeof(struct v4l2_format));
+
+ src->fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (-1 == ioctl(src->video_fd, VIDIOC_G_FMT, src->fmt))
+ {
+ goto gfmt_error;
+ }
+
+ /* NOTE: src->fmt->fmt.pix.field should provide enum v4l2_field value
+ for top & bottom field order for captured buffer which later
+ can be used to set BUFFER_FLAG_TFF on output gst buffers. */
+ src->field_order = src->fmt->fmt.pix.field;
+
+ return TRUE;
+ }
+open_error:
+ {
+ GST_ERROR_OBJECT(src, "Opening %s device", src->videodev);
+ return FALSE;
+ }
+caps_error:
+ {
+ GST_ERROR_OBJECT(src, "VIDIOC_QUERYCAP on %s device", src->videodev);
+ g_free (src->caps);
+ src->caps = NULL;
+ return FALSE;
+ }
+gfmt_error:
+ {
+ GST_ERROR_OBJECT(src, "VIDIOC_G_FMT on %s device", src->videodev);
+ g_free (src->caps);
+ src->caps = NULL;
+ g_free (src->fmt);
+ src->fmt = NULL;
+ return FALSE;
+ }
+}
+
+static gboolean gst_nv_v4l2_camera_unlock (GstBaseSrc *src)
+{
+ GstNvV4l2CameraSrc *self = (GstNvV4l2CameraSrc *) src;
+ self->unlock_requested = TRUE;
+ if (self->pool)
+ gst_buffer_pool_set_flushing (self->pool, TRUE);
+
+ return TRUE;
+}
+
+static gboolean gst_nv_v4l2_camera_unlock_stop (GstBaseSrc *src)
+{
+ GstNvV4l2CameraSrc *self = (GstNvV4l2CameraSrc *) src;
+ if (self->pool)
+ gst_buffer_pool_set_flushing (self->pool, FALSE);
+
+ self->unlock_requested = FALSE;
+
+ return TRUE;
+}
+
+static gboolean gst_nv_v4l2_camera_stop (GstBaseSrc * src_base)
+{
+ GstNvV4l2CameraSrc *src = (GstNvV4l2CameraSrc *) src_base;
+
+ enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ src->stop_requested = TRUE;
+
+ GST_DEBUG_OBJECT (src_base, "%s:\n", __func__);
+
+ if(-1 == ioctl(src->video_fd, VIDIOC_STREAMOFF, &buf_type))
+ g_print ("VIDIOC_STREAMOFF Ioctl Failed \n");
+
+ if (src->pool) {
+ if (gst_buffer_pool_is_active (src->pool))
+ gst_buffer_pool_set_active (src->pool, false);
+
+ gst_object_unref (src->pool);
+ src->pool = NULL;
+ }
+ if (src->video_fd >= 0 ) {
+ close (src->video_fd);
+ src->video_fd = -1;
+ }
+
+ if (src->req) {
+ g_free (src->req);
+ src->req = NULL;
+ }
+ if (src->caps) {
+ g_free (src->caps);
+ src->caps = NULL;
+ }
+ if (src->fmt) {
+ g_free (src->fmt);
+ src->fmt = NULL;
+ }
+ if (src->outcaps) {
+ gst_caps_unref (src->outcaps);
+ src->outcaps = NULL;
+ }
+ return TRUE;
+}
+
+static GstFlowReturn
+gst_nv_v4l2_camera_create (GstBaseSrc * src_base,
+ guint64 offset, guint size, GstBuffer ** buf)
+{
+ GstNvV4l2CameraSrc *self = GST_NVV4L2CAMERASRC (src_base);
+ GstFlowReturn ret = GST_FLOW_OK;
+
+ if (self->stop_requested || self->unlock_requested)
+ return GST_FLOW_EOS;
+
+ ret = gst_buffer_pool_acquire_buffer (self->pool, buf, NULL);
+ if (ret != GST_FLOW_OK)
+ return ret;
+
+ /* NOTE: Capture driver need to provide top/bottom field order based
+ on frame number.
+ Accordingly, BUFFER_FLAG_TFF needs to be set on gst buffer */
+ if (self->field_order == V4L2_FIELD_SEQ_TB)
+ GST_BUFFER_FLAG_SET (*buf, GST_VIDEO_BUFFER_FLAG_TFF);
+
+ return ret;
+}
+
+/* initialize the nvv4l2camerasrc's class */
+static void
+gst_nv_v4l2_camera_src_class_init (GstNvV4l2CameraSrcClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseSrcClass *base_src_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ base_src_class = (GstBaseSrcClass*) klass;
+
+ gobject_class->set_property = gst_nv_v4l2_camera_src_set_property;
+ gobject_class->get_property = gst_nv_v4l2_camera_src_get_property;
+ gobject_class->finalize = gst_nv_v4l2_camera_src_finalize;
+
+ base_src_class->set_caps = GST_DEBUG_FUNCPTR (gst_nv_v4l2_camera_set_caps);
+ base_src_class->fixate = GST_DEBUG_FUNCPTR (gst_nv_v4l2_camera_fixate);
+ base_src_class->start = GST_DEBUG_FUNCPTR (gst_nv_v4l2_camera_start);
+ base_src_class->stop = GST_DEBUG_FUNCPTR (gst_nv_v4l2_camera_stop);
+ base_src_class->create = GST_DEBUG_FUNCPTR (gst_nv_v4l2_camera_create);
+ base_src_class->unlock = GST_DEBUG_FUNCPTR (gst_nv_v4l2_camera_unlock);
+ base_src_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_nv_v4l2_camera_unlock_stop);
+
+ g_object_class_install_property (gobject_class, PROP_DEVICE,
+ g_param_spec_string ("device", "Device", "Device location, default = /dev/video0",
+ DEFAULT_PROP_DEVICE, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+ g_object_class_install_property (gobject_class, PROP_CAPTURE_BUFFERS,
+ g_param_spec_uint ("cap-buffers", "capture-buffers",
+ "number of capture buffers",
+ 2, MAX_BUFFERS, MIN_BUFFERS, (GParamFlags) G_PARAM_READWRITE));
+
+ gst_element_class_set_details_simple(gstelement_class,
+ "NvV4l2CameraSrc",
+ "Video/Capture",
+ "Nvidia V4l2 Camera Source",
+ "Ashwin Deshpande ");
+
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&src_factory));
+}
+
+/* initialize the new element
+ * instantiate pads and add them to element
+ * set pad calback functions
+ * initialize instance structure
+ */
+static void
+gst_nv_v4l2_camera_src_init (GstNvV4l2CameraSrc * src)
+{
+ src->cap_buf = MIN_BUFFERS;
+ src->width = 1920;
+ src->height = 1080;
+ src->fps_n = 30;
+ src->fps_d = 1;
+ src->field_order = V4L2_FIELD_NONE;
+ src->stop_requested = FALSE;
+ src->unlock_requested = FALSE;
+ src->outcaps = NULL;
+ src->caps = NULL;
+ src->fmt = NULL;
+ src->req = NULL;
+ src->field_order = 0;
+ src->interlaced_flag = 0;
+ src->videodev = g_strdup (DEFAULT_PROP_DEVICE);
+ src->video_fd = -1;
+
+ gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
+ gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
+ gst_base_src_set_do_timestamp (GST_BASE_SRC (src), TRUE);
+}
+
+static void
+gst_nv_v4l2_camera_src_finalize (GObject *object)
+{
+ GstNvV4l2CameraSrc *src= GST_NVV4L2CAMERASRC (object);
+ GST_DEBUG_OBJECT (src, "finalize");
+
+ if(src->videodev) {
+ g_free (src->videodev);
+ src->videodev = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_nv_v4l2_camera_src_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstNvV4l2CameraSrc *src = GST_NVV4L2CAMERASRC (object);
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE: {
+ g_free (src->videodev);
+ src->videodev = g_value_dup_string (value);
+ }
+ break;
+
+ case PROP_CAPTURE_BUFFERS: {
+ src->cap_buf = g_value_get_uint (value);
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_nv_v4l2_camera_src_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstNvV4l2CameraSrc *src = GST_NVV4L2CAMERASRC (object);
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE:
+ g_value_set_string (value, src->videodev);
+ break;
+
+ case PROP_CAPTURE_BUFFERS:
+ g_value_set_uint (value, src->cap_buf);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/* GstElement vmethod implementations */
+
+/* entry point to initialize the plug-in
+ * initialize the plug-in itself
+ * register the element factories and other features
+ */
+static gboolean
+nvv4l2camerasrc_init (GstPlugin * nvv4l2camerasrc)
+{
+ /* debug category for fltering log messages
+ *
+ * exchange the string 'Template nvv4l2camerasrc' with your description
+ */
+ GST_DEBUG_CATEGORY_INIT (gst_nv_v4l2_camera_src_debug, "nvv4l2camerasrc",
+ 0, "nvv4l2camerasrc");
+
+ return gst_element_register (nvv4l2camerasrc, "nvv4l2camerasrc", GST_RANK_PRIMARY,
+ GST_TYPE_NVV4L2CAMERASRC);
+}
+
+/* PACKAGE: this is usually set by autotools depending on some _INIT macro
+ * in configure.ac and then written into and defined in config.h, but we can
+ * just set it ourselves here in case someone doesn't use autotools to
+ * compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined.
+ */
+#ifndef PACKAGE
+#define PACKAGE "nvv4l2camerasrc"
+#endif
+
+/* gstreamer looks for this structure to register nvv4l2camerasrc
+ *
+ * exchange the string 'Template nvv4l2camerasrc' with your nvv4l2camerasrc description
+ */
+GST_PLUGIN_DEFINE (
+ GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ nvv4l2camerasrc,
+ "Nvidia v4l2 Source Component",
+ nvv4l2camerasrc_init,
+ "1.14.5",
+ "Proprietary",
+ "NvV4l2CameraSrc",
+ "http://nvidia.com/"
+)
diff --git a/gst-nvv4l2camera/gstnvv4l2camerasrc.hpp b/gst-nvv4l2camera/gstnvv4l2camerasrc.hpp
new file mode 100644
index 0000000..e126dee
--- /dev/null
+++ b/gst-nvv4l2camera/gstnvv4l2camerasrc.hpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2019-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:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of NVIDIA CORPORATION 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 ``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 OWNER 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_NVV4L2CAMERASRC_H__
+#define __GST_NVV4L2CAMERASRC_H__
+
+#include
+
+G_BEGIN_DECLS
+
+/* #defines don't like whitespacey bits */
+#define GST_TYPE_NVV4L2CAMERASRC \
+ (gst_nv_v4l2_camera_src_get_type())
+#define GST_NVV4L2CAMERASRC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NVV4L2CAMERASRC,GstNvV4l2CameraSrc))
+#define GST_NVV4L2CAMERASRC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NVV4L2CAMERASRC,GstNvV4l2CameraSrcClass))
+#define GST_IS_NVV4L2CAMERASRC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NVV4L2CAMERASRC))
+#define GST_IS_NVV4L2CAMERASRC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NVV4L2CAMERASRC))
+
+#define DEFAULT_PROP_DEVICE "/dev/video0"
+#define MIN_BUFFERS 6
+#define MAX_BUFFERS 16
+#define GST_NVV4L2_MEMORY_TYPE "nvV4l2Memory"
+#define DEQUE_TIMEOUT 5
+
+
+typedef struct _GstNvV4l2CameraSrc GstNvV4l2CameraSrc;
+typedef struct _GstNvV4l2CameraSrcClass GstNvV4l2CameraSrcClass;
+
+typedef struct _GstNvV4l2CameraSrcBuffer GstNvV4l2CameraSrcBuffer;
+
+/* NvV4l2CameraSrc buffer */
+struct _GstNvV4l2CameraSrcBuffer
+{
+ gint dmabuf_fd;
+ GstBuffer *gst_buf;
+ NvBufSurface *surface;
+ struct v4l2_buffer *buffer;
+};
+
+struct _GstNvV4l2CameraSrc
+{
+ GstBaseSrc base_nvv4l2camera;
+
+ GstPad *srcpad;
+
+ /* the video device */
+ char *videodev;
+ int video_fd;
+ struct v4l2_capability *caps;
+ struct v4l2_format *fmt;
+ struct v4l2_requestbuffers *req;
+ gint index;
+ guint cap_buf;
+
+ GstBufferPool *pool;
+
+ GstCaps *outcaps;
+
+ gint width;
+ gint height;
+ gint fps_n;
+ gint fps_d;
+ gint field_order;
+
+ gboolean stop_requested;
+ gboolean unlock_requested;
+ gboolean interlaced_flag;
+ fd_set read_set;
+ struct timeval tv;
+};
+
+struct _GstNvV4l2CameraSrcClass
+{
+ GstBaseSrcClass base_nvv4l2camera_class;
+};
+
+GType gst_nv_v4l2_camera_src_get_type (void);
+
+
+G_END_DECLS
+
+#endif /* __GST_NVV4L2CAMERASRC_H__ */
diff --git a/push_info.txt b/push_info.txt
new file mode 100644
index 0000000..dbe8a31
--- /dev/null
+++ b/push_info.txt
@@ -0,0 +1 @@
+jetson_38.2.1