Updating prebuilts and/or headers

2a8f761ddbd0acd63d41333cfd33c0130a68f986 - libv4l2_nvargus/nvargusv4l2.cpp
592bab81439af0cb17984e0b0e1d1b4b1a498ea2 - libv4l2_nvargus/nvargusv4l2_nvqueue.cpp
138a72695eb516d82dba17bf87260fe5a692ec74 - libv4l2_nvargus/nvargusv4l2_ioctl.cpp
55cebd96a410e6ff9c74c0e9b1a7ec68cf7ee4d5 - libv4l2_nvargus/libv4l2_nvargus.cpp
6d69d9bce88ea97989ac2ecf80df794a8c066623 - libv4l2_nvargus/nvargusv4l2_argus.cpp
08591e4e7c932d134ab3b5de5608f79817f25b10 - libv4l2_nvargus/Makefile
1b22fa15e66aeb472a541aa4fa9ee68b6f631fdf - libv4l2_nvargus/nvargusv4l2_context.cpp
62ff489fd24d7e62098d8bd0b681f017a3f1ed89 - libv4l2_nvargus/nvargusv4l2_os.cpp
e5896289dc5cf1a1be97cd111bef4715314a657d - libv4l2_nvargus/README
25353aa29a931dfc9f52054852b50d690716a64c - libv4l2_nvargus/inc/nvargusv4l2_nvqueue.h
e0025b2f87abda4cd744e356e26cef85246a1fdc - libv4l2_nvargus/inc/nvargusv4l2_os.h
1522ea0088250fb7ce0c9f77c75dbca5d0f511f4 - libv4l2_nvargus/inc/nvargusv4l2.h
553b571fc97552659847ad0b2bc6e34384724d29 - libv4l2_nvargus/inc/nvargusv4l2_context.h
d1c5f6e8cd188bbd39c99c32d4e4e68ee85e0f8b - libv4l2_nvargus/inc/nvargusv4l2_argus.h
ebcc91d051727ba390d71db0887f788ffcfd8091 - libv4l2_nvargus/inc/nvargusv4l2_ioctl.h

Change-Id: I08281700e9f5d70d8e09159b75fc376a293fead1
This commit is contained in:
svcmobrel-release
2023-12-05 20:47:45 -08:00
parent dc3e705715
commit 9d0a7f9ced
17 changed files with 4359 additions and 0 deletions

17
commitFile.txt Normal file
View File

@@ -0,0 +1,17 @@
Updating prebuilts and/or headers
2a8f761ddbd0acd63d41333cfd33c0130a68f986 - libv4l2_nvargus/nvargusv4l2.cpp
592bab81439af0cb17984e0b0e1d1b4b1a498ea2 - libv4l2_nvargus/nvargusv4l2_nvqueue.cpp
138a72695eb516d82dba17bf87260fe5a692ec74 - libv4l2_nvargus/nvargusv4l2_ioctl.cpp
55cebd96a410e6ff9c74c0e9b1a7ec68cf7ee4d5 - libv4l2_nvargus/libv4l2_nvargus.cpp
6d69d9bce88ea97989ac2ecf80df794a8c066623 - libv4l2_nvargus/nvargusv4l2_argus.cpp
08591e4e7c932d134ab3b5de5608f79817f25b10 - libv4l2_nvargus/Makefile
1b22fa15e66aeb472a541aa4fa9ee68b6f631fdf - libv4l2_nvargus/nvargusv4l2_context.cpp
62ff489fd24d7e62098d8bd0b681f017a3f1ed89 - libv4l2_nvargus/nvargusv4l2_os.cpp
e5896289dc5cf1a1be97cd111bef4715314a657d - libv4l2_nvargus/README
25353aa29a931dfc9f52054852b50d690716a64c - libv4l2_nvargus/inc/nvargusv4l2_nvqueue.h
e0025b2f87abda4cd744e356e26cef85246a1fdc - libv4l2_nvargus/inc/nvargusv4l2_os.h
1522ea0088250fb7ce0c9f77c75dbca5d0f511f4 - libv4l2_nvargus/inc/nvargusv4l2.h
553b571fc97552659847ad0b2bc6e34384724d29 - libv4l2_nvargus/inc/nvargusv4l2_context.h
d1c5f6e8cd188bbd39c99c32d4e4e68ee85e0f8b - libv4l2_nvargus/inc/nvargusv4l2_argus.h
ebcc91d051727ba390d71db0887f788ffcfd8091 - libv4l2_nvargus/inc/nvargusv4l2_ioctl.h

125
libv4l2_nvargus/Makefile Normal file
View File

@@ -0,0 +1,125 @@
###############################################################################
#
# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# makefile for libv4l2_nvargus library
#
###############################################################################
LIBRARY_NAME:= libv4l2_nvargus.so
# Clear the flags from env
CPPFLAGS :=
LDFLAGS :=
LIBS :=
INSTALL_DIR?=/usr/lib/aarch64-linux-gnu/tegra/
LINK_DIR?=/usr/lib/aarch64-linux-gnu/libv4l/plugins/nv/
# Verbose flag
ifeq ($(VERBOSE), 1)
AT =
else
AT = @
endif
# ARM ABI of the target platform
TEGRA_ARMABI ?= aarch64-linux-gnu
# Location of the target rootfs
ifeq ($(shell uname -m), aarch64)
TARGET_ROOTFS :=
CROSS_COMPILE :=
else
CROSS_COMPILE ?= aarch64-unknown-linux-gnu-
ifeq ($(TARGET_ROOTFS),)
$(error "TARGET_ROOTFS" is not set. Please set TARGET_ROOTFS if you are cross-compiling.)
endif
endif
ARGUS_UTILS_GTK_PATH := $(TARGET_ROOTFS)/usr/src/jetson_multimedia_api/argus/samples/utils/gtk
ARGUS_UTILS_SRC_PATH := $(TARGET_ROOTFS)/usr/src/jetson_multimedia_api/argus/samples/utils
CC = $(AT) $(CROSS_COMPILE)gcc
CPP = $(AT) $(CROSS_COMPILE)gcc
RM = $(AT) $(CROSS_COMPILE)rm -f
PKGS := gtk+-3.0 \
glx \
glib-2.0
CPPFLAGS += \
-I"$(TARGET_ROOTFS)/usr/include" \
-I"$(TARGET_ROOTFS)/usr/include/$(TEGRA_ARMABI)" \
-I"$(TARGET_ROOTFS)/usr/src/argus/include" \
-I"$(TARGET_ROOTFS)/usr/src/jetson_multimedia_api/argus/samples/utils" \
-I"$(TARGET_ROOTFS)/usr/src/jetson_multimedia_api/argus/samples/utils/gtk" \
-I"$(TARGET_ROOTFS)/usr/src/jetson_multimedia_api/include" \
-I./inc
CPPFLAGS += \
-pthread \
-fno-rtti -std=gnu++14 -Wall -fPIC
CPPFLAGS += `pkg-config --cflags $(PKGS)`
LIBS += \
-shared -lnvv4l2 -lEGL -lGLESv2 -lX11 -lpthread -Wl,--no-undefined \
-lnvbufsurface -lnvbufsurftransform -lnvargus_socketclient -ldl -lstdc++ -lm
LDFLAGS += -L"/usr/lib" \
-L"/usr/lib/$(TEGRA_ARMABI)/" \
-L"/usr/lib/$(TEGRA_ARMABI)/tegra"
LIBS += `pkg-config --libs $(PKGS)`
SRCS := \
libv4l2_nvargus.cpp \
nvargusv4l2.cpp \
nvargusv4l2_context.cpp \
nvargusv4l2_ioctl.cpp \
nvargusv4l2_argus.cpp \
nvargusv4l2_os.cpp \
nvargusv4l2_nvqueue.cpp \
$(wildcard $(ARGUS_UTILS_GTK_PATH)/*.cpp) \
$(ARGUS_UTILS_SRC_PATH)/nvmmapi/NvNativeBuffer.cpp \
$(filter-out $(ARGUS_UTILS_SRC_PATH)/CUDAHelper.cpp, \
$(wildcard $(ARGUS_UTILS_SRC_PATH)/*.cpp))
OBJS = $(patsubst %.cpp,%.o,$(SRCS))
all: $(LIBRARY_NAME)
.o: .cpp
@echo "Compiling: $(CPP) $(CPPFLAGS) $<"
$(CPP) $(CPPFLAGS) -c $<
$(LIBRARY_NAME): $(OBJS)
@echo "Linking: $@"
$(CPP) -o $@ $(OBJS) $(CPPFLAGS) $(LIBS) $(LDFLAGS)
.PHONY: install
install: $(LIBRARY_NAME)
sudo cp -vp $(LIBRARY_NAME) $(INSTALL_DIR)
sudo ln -sf $(INSTALL_DIR)$(LIBRARY_NAME) $(LINK_DIR)$(LIBRARY_NAME)
clean:
$(RM) *.o $(LIBRARY_NAME) *~

52
libv4l2_nvargus/README Normal file
View File

@@ -0,0 +1,52 @@
*****************************************************************************
* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
LIBV4L2_NVARGUS API is a V4L2 API interface written over Libargus Camera to support
capture and record v4l2 camera application development.
API_NOTE:
1. For V4L2 DMABUF Memory buffers, additional VIDIOC_QUERYBUF ioctl is also required
to have proper mapping between application allocated buffers to Libargus buffers.
LIBV4L2_NVARGUS API includes:
1. Source files of the written V4L2 interface, where respective v4l2_ioctl calls
are mapped to LibArgus calls.
2. README
Pre-requisites:
1. Install "jetson_multimedia_api" package from latest Jetpack release.
2. Install below packages:
$ sudo apt-get install autoconf automake libtool curl make g++ unzip \
pkg-config libx11-dev libgtk-3-dev libjpeg-dev libgstreamer1.0-dev
Steps for copying sources on target:
1. Copy the tar file libv4l2_nvargus_src.tbz2 to the booted Jetson device.
2. Run the following command on the Jetson device to install sources:
$ sudo tar -xpf libv4l2_nvargus_src.tbz2 -C .
Steps to build sources:
$ cd libv4l2_nvargus_src
$ make [-jN] # Optional flag -jN for parallel build where N is the job count
$ sudo make install
NOTE: above command will install libv4l2_nvargus.so at "/usr/lib/aarch64-linux-gnu/tegra/"
To install at different location run "$ sudo INSTALL_DIR=<your_path> make install"

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/* This file is the public interface for using the libargusV4L2.
libargusv4l2 implements the V4L2 behavior in userspace and hence
uses all the structure/macro definitions from standard V4L2 header file
i.e videodev2.h
Standard system calls like open(), ioctl() and close() are replaced
with below APIs.
*/
#ifndef __NVARGUSV4L2_H__
#define __NVARGUSV4L2_H__
/* Equivalent to the standard open() system call on a V4L2 Device.
Camera indices do not have one-to-one map with devnode indices.
Creates an instance and returns a fd equivalent to the client if successful,
-1 if error.
*/
int ArgusV4L2_Open(const int camera_index, int flags);
/* Equivalent to the standard close() system call on a V4L2 Device.*/
int ArgusV4L2_Close(int fd);
/* Equivalent to the standard ioctl() system call on a V4L2 Device.*/
int ArgusV4L2_Ioctl(int fd, unsigned long cmd, ...);
#endif /* __NVARGUSV4L2_H__ */

View File

@@ -0,0 +1,90 @@
/*
* Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __NVARGUSV4L2_HELPER_H__
#define __NVARGUSV4L2_HELPER_H__
#include "nvargusv4l2_context.h"
#include "nvargusv4l2_ioctl.h"
#define TIMEOUT_FOUR_SECONDS 4000000000
#define TIMEOUT_TWO_SECONDS 2000000000
extern Argus::CameraProvider *g_cameraProvider;
extern Argus::ICameraProvider *g_iCameraProvider;
/* Returns the Argus status code in string */
const char* getStatusString(Argus::Status status);
/* Reads boolean variable atomically */
bool v4l2_cam_atomic_read_bool(v4l2_camera_context* ctx, bool *var);
/* Writes boolean variable atomically */
void v4l2_cam_atomic_write_bool(v4l2_camera_context* ctx, bool *var, bool value);
/* Return the value of the variable atomically */
uint32_t v4l2_cam_atomic_get(v4l2_camera_context *ctx, uint32_t *var);
/* Release Argus::Buffer with the given index to the stream */
int32_t ReleaseStreamBuffer(v4l2_camera_context *ctx, int32_t index);
/* Recieves pointer to the filled Argus::Buffer from the stream */
Argus::Buffer* AcquireStreamBuffer(v4l2_camera_context *ctx, uint32_t timeout);
/* Initializes the Argus::OutputStream */
int32_t initialize_outputstream(v4l2_camera_context *ctx, cam_params *argus_params);
/* Set all the Argus related properties and settings */
int32_t v4l2_cam_set_argus_settings(v4l2_camera_context *ctx, uint32_t ctrl_id);
/* Sets Frame Rate */
int32_t set_framerate(v4l2_camera_context *ctx, float frame_duration);
/* Sets Denoise Settings */
int32_t v4l2_cam_set_denoise_settings(v4l2_camera_context *ctx, uint32_t ctrl_id,
struct denoise_values *ctrl_value);
/* Allocates all capture queues */
int32_t allocate_all_capture_queues(v4l2_camera_context *ctx);
/* Allocates buffers in the memory (MMAP) */
int32_t allocate_capture_buffers(v4l2_camera_context *ctx, cam_params *argus_params);
/* Allocate argus buffers for DMABUF memory */
int32_t allocate_argus_buffers(v4l2_camera_context *ctx, cam_params *argus_params, int32_t dmabuf_fd, uint32_t buffer_idx);
/* Deallocates the previously alloacted buffers */
void free_cap_buffers(v4l2_camera_context *ctx);
/* Query the buffer */
int32_t query_cam_buffers(v4l2_camera_context *ctx, cam_params *argus_params, uint64_t *psizes);
/* Close camera context */
void v4l2_close_argus_context(v4l2_context *v4l2_ctx);
/* Queues the empty capture plane buffers to Argus */
int32_t nvargus_enqueue_instream_buffers_from_capture_inQ(v4l2_camera_context *ctx, int32_t idx);
/* Callback function to the argus_thread */
void argus_capture_thread_func(void *args);
#endif

View File

@@ -0,0 +1,274 @@
/*
* Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __NVARGUSV4L2_CONTEXT_H__
#define __NVARGUSV4L2_CONTEXT_H__
#include <pthread.h>
#include "nvbufsurface.h"
#include "nvargusv4l2_os.h"
#include "nvargusv4l2_nvqueue.h"
#include "linux/videodev2.h"
#include "v4l2_nv_extensions.h"
#include "Thread.h"
#include <Argus/Argus.h>
#include <EGLStream/EGLStream.h>
#include "EGLGlobal.h"
#define MAX_CONTEXTS 32
#define FRAMESIZE_MIN_WIDTH 48
#define FRAMESIZE_MIN_HEIGHT 48
#define MAX_OP_BUFFERS 32
#define MIN_OP_BUFFERS 6
#define MAX_PLANES 4
#ifdef _DEBUG
#define DEBUG_LOGS 0
#else
#define DEBUG_LOGS 0
#endif
#define DBG_PRINT(...) \
do { \
if (DEBUG_LOGS) \
fprintf(stderr, "LIBV4L2ARGUS: " __VA_ARGS__); \
} while (0)
#define REL_PRINT(...) \
do { \
if (runtime_logs_enabled) \
{ \
fprintf(stderr, "(tid) : %x ", (unsigned int) pthread_self()); \
fprintf(stderr, "LIBV4L2ARGUS: " __VA_ARGS__); \
} \
} while (0)
#define ERROR_PRINT(...) \
do { \
fprintf(stderr, "LIBV4L2ARGUS ERROR: " __VA_ARGS__); \
} while (0)
#define V4L2_BUFFER_TYPE_SUPPORTED_OR_ERROR(buffer_type) \
if (buffer_type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { \
printf("Unsupported buffer type\n"); \
return EINVAL; }
#define V4L2_MEMORY_TYPE_SUPPORTED_OR_ERROR(memory_type) \
if (memory_type != V4L2_MEMORY_MMAP && memory_type != V4L2_MEMORY_DMABUF) { \
printf("Unsupported memory type\n"); \
return EINVAL; }
extern Argus::CameraProvider *g_cameraProvider;
extern Argus::ICameraProvider *g_iCameraProvider;
extern std::vector<Argus::CameraDevice*> g_cameraDevices;
/* This structure identifies an instance which is created when
* argusv4l2_open() is called
*/
typedef struct v4l2_context_rec {
NvMutexHandle ioctl_mutex;
/* Pointer to the camera context */
void *actual_context;
} v4l2_context;
/* Structure to store Argus color format information */
typedef struct {
uint32_t width, height;
/* V4L2 fourcc */
uint32_t pixelformat;
Argus::PixelFormat argus_format;
/* color depth */
uint32_t bitdepth;
} cam_params;
/* The structure store the information needed for V4L2_ENUM_FRAMESIZES.
* This is used to store minimum & maximum width height, frame duration
* supported for a given format.
*/
typedef struct {
uint32_t min_width;
uint32_t min_height;
uint32_t max_width;
uint32_t max_height;
uint32_t bitdepth;
float frame_duration;
float minGainRange;
float maxGainRange;
uint64_t minExposureTimeRange;
uint64_t maxExposureTimeRange;
} argusv4l2_sensormode;
/* Defines v4l2_buffer */
typedef struct camerav4l2_buffer_rec {
/* Buffer Index*/
int32_t buffer_id;
/* Surface List params for allocated buffer.*/
NvBufSurfaceParams surf_params;
/* Represent state of buffer*/
uint32_t flags;
/* Repesent that buffer structure is allocated or not*/
uint32_t allocated;
/* Stores the buf_fd returned by nvbuf_utils API */
uint32_t buf_fd;
/* Memory representation of argus buffer mapped to the NvMMBuffer FD */
Argus::Buffer* argus_buffer;
} camerav4l2_buffer;
/* The strcuture stores metadata retrieved from acquired buffer */
struct argusframe_metadata {
bool aeLocked;
bool colorCorrectionMatrixEnable;
bool toneMapCurveEnabled;
float ispDigitalGain;
float sceneLux;
float sensorAnalogGain;
int32_t focuserPosition;
uint32_t awbCct;
uint32_t id;
uint32_t sensorSensitivity;
uint64_t frameDuration;
uint64_t frameReadoutTime;
uint64_t sensorExposureTime;
uint64_t sensorTimestamp;
Argus::AeState aeState;
Argus::AwbState awbState;
argusframe_metadata()
: aeState(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "AE_STATE_UNKNOWN")
, awbState(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "AWB_STATE_UNKNOWN")
{}
};
/* The structure stores the Argus controls values */
typedef struct argus_settings_rec {
bool awbLock;
bool aeLock;
bool enableColorSaturation;
int32_t sensorModeIdx;
uint32_t denoiseMode;
uint32_t edgeEnhanceMode;
uint32_t aeAntibandingMode;
uint32_t awbMode;
float frameDuration;
float edgeEnhanceStrength;
float denoiseStrength;
float exposureCompensation;
float colorSaturation;
Argus::Range<float> ispDigitalGainRange;
Argus::Range<float> gainRange;
Argus::Range<uint64_t> exposureTimeRange;
Argus::IAutoControlSettings *autoControlSettingsPtr;
Argus::IDenoiseSettings *denoiseSettingsPtr;
Argus::IEdgeEnhanceSettings *EESettingsPtr;
} cam_settings;
/* This structure defines the camera context structure.
*/
typedef struct v4l2_camera_context_rec {
/* Context mutex, used for simultaneous access from multiple threads.*/
NvMutexHandle context_mutex;
/* Stats mutex, used for atomic update/read/access statistics */
NvMutexHandle stats_mutex;
/* Semaphore for dqbuf on capture plane */
NvSemaphoreHandle acquirebuf_sema;
/* Queue for buffer indices which are returned from Argus,
ready to be DQBUF'ed on capture plane */
NvQueueHandle capplane_Q;
/* Thread for argus capture processing */
NvThreadHandle argus_capture_thread;
bool blocking_mode;
bool stream_on;
bool error_flag;
/* This flag if set indicates that Argus is in STOP state */
bool camera_state_stopped;
/* Number of buffers on capture plane for V4L2 */
uint32_t capture_buffer_count;
/* Number of queued buffer */
uint32_t num_queued_capture_buffers;
/* Either DMABUF or MMAP */
uint32_t capture_memory_type;
cam_params argus_params;
cam_settings argus_settings;
camerav4l2_buffer cap_buffers[MAX_OP_BUFFERS];
argusframe_metadata *frame_metadata[MAX_OP_BUFFERS];
void* inbuf_mapped_address[MAX_OP_BUFFERS][MAX_PLANES];
/* Argus Members */
Argus::Status m_cameraStatus;
Argus::UniqueObj<Argus::CaptureSession> m_captureSession;
Argus::ICaptureSession *m_iCaptureSession;
Argus::IEventProvider *m_iEventProvider;
Argus::IEventQueue *m_iEventQueue;
Argus::UniqueObj<Argus::EventQueue> m_eventQueue;
Argus::ICameraProperties *m_iCameraProperties;
Argus::UniqueObj<Argus::OutputStreamSettings> m_streamSettings;
Argus::IBufferOutputStreamSettings *m_iStreamSettings;
Argus::UniqueObj<Argus::OutputStream> m_outputStream;
Argus::IBufferOutputStream *m_iStream;
Argus::UniqueObj<Argus::Request> m_request;
Argus::IRequest *m_iRequest;
Argus::ISourceSettings *m_iSourceSettings;
const Argus::CaptureMetadata *m_captureMetadata;
std::vector<argusv4l2_sensormode> argusv4l2_sensormodes;
std::vector<Argus::SensorMode*> m_sensorModes;
std::vector<Argus::EventType> m_eventTypes;
} v4l2_camera_context;
/* Returns a context from a fd */
v4l2_context* v4l2_get_context(int32_t fd);
int initialize_camera_provider();
/* Queries and fills the data of all avaiable sensor modes from Argus */
void v4l2_argus_fill_sensor_modes(std::vector<Argus::SensorMode*> sensorModes,
std::vector<argusv4l2_sensormode> *argusv4l2_sensormodes);
/* Initializes argus environment when a valid context gets created */
int32_t initialize_arguscamera(v4l2_camera_context *camera_ctx, uint32_t camera_index);
/* Sets argus default parameters */
void v4l2_argus_set_defaults(cam_params *argus_defaults, cam_settings *argus_settings);
/* Opens a new context */
int32_t v4l2_open_camera_context(uint32_t camera_index, int flags);
/* Closes the contexts and destroys all the memory associated with it.*/
void v4l2_close_camera_context(int32_t fd);
/* Tries to acquire the global mutex to avoid two open/close contexts at a time */
void v4l2_lock_global_mutex(void);
/* Releases the global mutex to avoid two open/close contexts at a time */
void v4l2_unlock_global_mutex(void);
/* This flag is set if /tmp/argusv4l2_logs file exists. This is checked
when the library is loaded. This mechanism provides conditional logging
in the same binary based on environment parameters.*/
extern bool runtime_logs_enabled;
#endif /* __NVARGUSV4L2_CONTEXT_H__ */

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __NVARGUSV4L2_IOCTL_H__
#define __NVARGUSV4L2_IOCTL_H__
#include "nvargusv4l2_context.h"
#include "nvargusv4l2_argus.h"
#define ALIGN_BYTES 255
#define MEM_ALIGN_16(X) (((X) + 0xF)&~0xF)
#define MIN_EXPOSURE_COMPENSATION -2.0
#define MAX_EXPOSURE_COMPENSATION 2.0
#define MIN_EE_STRENGTH -1.0
#define MAX_EE_STRENGTH 1.0
#define MIN_DENOISE_STRENGTH -1.0
#define MAX_DENOISE_STRENGTH 1.0
#define MIN_DIGITAL_GAIN 1
#define MAX_DIGITAL_GAIN 256
#define MIN_COLOR_SATURATION 0.0
#define MAX_COLOR_SATURATION 2.0
extern Argus::CameraProvider *g_cameraProvider;
extern Argus::ICameraProvider *g_iCameraProvider;
/* Structure to map corresponding v4l2 format and
* Argus pixel format.
*/
struct argusv4l2_fmt_struct
{
/* Color format description */
char name[32];
/* Argus pixel format */
const Argus::PixelFormat argus_format;
/* V4L2 fourcc */
uint32_t fourcc;
/* Number of planes */
uint32_t num_planes;
/* bytes per pixel */
uint32_t bpp;
};
/* Entry structure which is added/removed in the queues */
typedef struct _q_entry
{
/* Index of the buffer */
uint32_t index;
/* Size of the buffer */
uint32_t size;
/* Timestamp */
uint64_t timestamp;
/* FD */
uint32_t fd;
/* Stores the config store id of this buffer */
uint32_t config_store;
} q_entry;
/* IOCTL calls for Argus camera */
int32_t nvargus_ioctl(int32_t fd, unsigned long cmd, void *arg);
int32_t vidioc_cam_querycap(int32_t fd, struct v4l2_capability *caps);
int32_t vidioc_cam_enum_fmt(int32_t fd, struct v4l2_fmtdesc *fmt);
int32_t vidioc_cam_enum_framesizes(int32_t fd, struct v4l2_frmsizeenum *frame);
int32_t vidioc_cam_enum_frameintervals(int32_t fd, struct v4l2_frmivalenum *frameival);
int32_t vidioc_cam_g_fmt(int32_t fd, struct v4l2_format *format);
int32_t vidioc_cam_s_fmt(int32_t fd, struct v4l2_format *format);
int32_t vidioc_cam_reqbufs(int32_t fd, struct v4l2_requestbuffers *reqbufs);
int32_t vidioc_cam_streamon(int32_t fd, unsigned int *type);
int32_t vidioc_cam_streamoff(int32_t fd, unsigned int *type);
int32_t vidioc_cam_qbuf(int32_t fd, struct v4l2_buffer *buffer);
int32_t vidioc_cam_dqbuf(int32_t fd, struct v4l2_buffer *buffer);
int32_t vidioc_cam_querybuf(int32_t fd, v4l2_buffer *buffer);
int32_t vidioc_cam_expbuf(int32_t fd, struct v4l2_exportbuffer *export_buffer);
int32_t vidioc_cam_s_extctrls(int32_t fd, struct v4l2_ext_controls *ctrl);
int32_t vidic_cam_g_extctrls(int32_t fd, struct v4l2_ext_controls *ctrl);
int32_t vidioc_cam_sparm(int32_t fd, struct v4l2_streamparm *streamparms);
#endif /* __NVARGUSV4L2_IOCTL_H__ */

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARGUSV4L2_NVQUEUE_H__
#define __ARGUSV4L2_NVQUEUE_H__
#include <stdlib.h>
#include "nvargusv4l2_os.h"
typedef struct NvQueueRec
{
NvMutexHandle mutexLock; /* mutex lock for queue */
u_int32_t maxEntries; /* maximum number of allowed entries */
u_int32_t entrySize; /* size of individual entry */
u_int32_t pushIndex; /* index of where to push entry */
u_int32_t popIndex; /* index of where to grab entry */
u_int8_t *pEntryList; /* pointer to beginning entry */
} NvQueue;
typedef struct NvQueueRec *NvQueueHandle;
int32_t NvQueueCreate(NvQueueHandle *phQueue, u_int32_t maxEntries, u_int32_t entrySize);
int32_t NvQueueEnQ(NvQueueHandle hQueue, void *pElem);
int32_t NvQueueDeQ(NvQueueHandle hQueue, void *pElem);
int32_t NvQueuePeek(NvQueueHandle hQueue, void *pElem);
int32_t NvQueuePeekEntry(NvQueueHandle hQueue, void *pElem, u_int32_t entry);
void NvQueueDestroy(NvQueueHandle *phQueue);
u_int32_t NvQueueGetNumEntries(NvQueueHandle hQueue);
#endif /* __ARGUSV4L2_NVQUEUE_H__ */

View File

@@ -0,0 +1,146 @@
/*
* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __NVARGUSV4L2_OS_H__
#define __NVARGUSV4L2_OS_H__
#include <stdlib.h>
typedef struct NvMutex_ *NvMutexHandle;
typedef struct NvSemaphore_ *NvSemaphoreHandle;
typedef struct NvThread_ *NvThreadHandle;
/** Entry point for a thread.
*/
typedef void (*NvThreadFunction)(void *args);
/**
* Allocates a new process-local mutex.
*
* @note Mutexes can be locked recursively; if a thread owns the lock,
* it can lock it again as long as it unlocks it an equal number of times.
*
* @param mutex The mutex to initialize.
*
* @return \a ENOMEM, or one of common error codes on
* failure.
*/
int32_t NvMutexCreate(NvMutexHandle *mutex);
/** Locks the given unlocked mutex.
*
* @param mutex The mutex to lock; note it is a recursive lock.
*
* @return \a EINVAL, or one of common error codes on
* failure.
*/
int32_t NvMutexAcquire(NvMutexHandle mutex);
/** Unlocks a locked mutex.
*
* @param mutex The mutex to unlock.
*
* @return \a EINVAL, or one of common error codes on
* failure.
*/
int32_t NvMutexRelease(NvMutexHandle mutex);
/** Frees the resources held by a mutex.
*
* Mutexes will be destroyed only when last reference has gone away.
*
* @param mutex The mutex to destroy.
*
* @return \a EINVAL, or one of common error codes on
* failure.
*/
int32_t NvMutexDestroy(NvMutexHandle mutex);
/** Creates a counting semaphore.
*
* @param semaphore A pointer to the semaphore to initialize.
* @param value The initial semaphore value.
*
* @retval 0 on success, or the appropriate error code.
*/
int32_t NvSemaphoreCreate(NvSemaphoreHandle *semaphore, u_int32_t value);
/** Waits until the semaphore value becomes non-zero, then
* decrements the value and returns.
*
* @param semaphore The semaphore to wait for.
*/
void NvSemaphoreWait(NvSemaphoreHandle semaphore);
/** Increments the semaphore value.
*
* @param semaphore The semaphore to signal.
*/
void NvSemaphoreSignal(NvSemaphoreHandle semaphore);
/** Frees resources held by the semaphore.
*
* Semaphores are reference counted across the multiprocesses,
* and will be destroyed when the last reference has
* gone away.
*
* @param semaphore The semaphore to destroy.
*
* @retval 0 on success, or the appropriate error code.
*/
int32_t NvSemaphoreDestroy(NvSemaphoreHandle semaphore);
/** Creates a thread.
*
* @param function The thread entry point.
* @param args A pointer to the thread arguments.
* @param [out] thread A pointer to the result thread ID structure.
*
* @retval 0 on success, or the appropriate error code.
*/
int32_t NvThreadCreate(NvThreadFunction function, void *args,
NvThreadHandle *thread);
/** Assigns the given name to the given thread.
*
* @param thread The thread to assign the name to.
* @param name thread name string.
*/
int32_t NvThreadSetName(NvThreadHandle thread, const char *name);
/** Waits for the given thread to exit.
*
* The joined thread will be destroyed automatically. All OS resources
* will be reclaimed.
*
* @param thread The thread to wait for.
*/
void NvThreadJoin(NvThreadHandle thread);
/** Returns current thread ID.
*
* @retval ThreadId
*/
u_int64_t NvGetCurrentThreadId(void);
#endif /* __NVARGUSV4L2_OS_H__ */

View File

@@ -0,0 +1,320 @@
/*
* Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <iostream>
#include <errno.h>
#include <fcntl.h>
#include <linux/videodev2.h>
#include <pthread.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string>
#include "libv4l-plugin.h"
#include "nvargusv4l2.h"
#include "nvargusv4l2_context.h"
#include "nvargusv4l2_ioctl.h"
#if HAVE_VISIBILITY
#define PLUGIN_PUBLIC __attribute__ ((visibility("default")))
#else
#define PLUGIN_PUBLIC
#endif
#define NVARGUS_DEV_STRING "/dev/video"
#define MAX_CAMERA_NODE_LIMITS 64
#define LOG_Q_DQ(fmt, args...) \
do { \
if (profile_enabled_flag) \
{ \
struct timeval start; \
struct timezone tzp; \
gettimeofday(&start, &tzp); \
FILE* pFile = fopen("/tmp/profile_argusbuffer_logs.txt", "a"); \
fprintf(pFile, "\n%x: %lu: "fmt, (unsigned int) pthread_self(), (1000000 * start.tv_sec + start.tv_usec),##args); \
fclose(pFile); \
} \
} while (0)
struct nvargus_plugin_ctx
{
int nvv4l2argus_fd;
int fd_blocking_mode;
};
uint32_t profile_enabled_flag = 0;
void __attribute__((constructor)) libv4l2_nvargus_init(void);
void __attribute__((destructor)) libv4l2_nvargus_deinit(void);
void *plugin_init(int fd);
void plugin_close(void *dev_ops_priv);
int plugin_ioctl(void *dev_ops_priv, int fd,
unsigned long int cmd, void *arg);
void __attribute__((constructor)) libv4l2_nvargus_init(void)
{
struct stat file_stats;
if(stat("/tmp/libv4l2argusPlugin_profile", &file_stats) == 0)
profile_enabled_flag = 1;
else
profile_enabled_flag = 0;
}
void __attribute__((destructor)) libv4l2_nvargus_deinit(void)
{
}
typedef struct
{
int32_t device_index;
int32_t argus_index;
bool is_usb;
} camera_type;
class CameraNode
{
public:
static CameraNode& GetCameraNode()
{
static CameraNode s_instance;
return s_instance;
}
static int GetIndex(int node_index)
{
return GetCameraNode().GetIndexInternal(node_index);
}
void operator=(CameraNode const&) = delete;
private:
CameraNode() {}
int GetIndexInternal(int node_index);
int QueryNode(int node_index, char* device_path);
camera_type m_cameraNodes[MAX_CAMERA_NODE_LIMITS] =
{{-1, -1, false}, {-1, -1, false}, {-1, -1, false}, {-1, -1, false},
{-1, -1, false}, {-1, -1, false}, {-1, -1, false}, {-1, -1, false},
{-1, -1, false}, {-1, -1, false}, {-1, -1, false}, {-1, -1, false},
{-1, -1, false}, {-1, -1, false}, {-1, -1, false}, {-1, -1, false},
{-1, -1, false}, {-1, -1, false}, {-1, -1, false}, {-1, -1, false},
{-1, -1, false}, {-1, -1, false}, {-1, -1, false}, {-1, -1, false},
{-1, -1, false}, {-1, -1, false}, {-1, -1, false}, {-1, -1, false},
{-1, -1, false}, {-1, -1, false}, {-1, -1, false}, {-1, -1, false},
{-1, -1, false}, {-1, -1, false}, {-1, -1, false}, {-1, -1, false},
{-1, -1, false}, {-1, -1, false}, {-1, -1, false}, {-1, -1, false},
{-1, -1, false}, {-1, -1, false}, {-1, -1, false}, {-1, -1, false},
{-1, -1, false}, {-1, -1, false}, {-1, -1, false}, {-1, -1, false},
{-1, -1, false}, {-1, -1, false}, {-1, -1, false}, {-1, -1, false},
{-1, -1, false}, {-1, -1, false}, {-1, -1, false}, {-1, -1, false},
{-1, -1, false}, {-1, -1, false}, {-1, -1, false}, {-1, -1, false},
{-1, -1, false}, {-1, -1, false}, {-1, -1, false}, {-1, -1, false},
};
};
int CameraNode::GetIndexInternal(int node_index)
{
int index;
int argus_index = 0;
if (node_index < 0)
return -1;
for (index = 0; index <= node_index; index++)
{
if (m_cameraNodes[index].device_index == -1)
{
char camera_path[128];
m_cameraNodes[index].device_index = index;
snprintf(camera_path, sizeof(camera_path), "%s%d", NVARGUS_DEV_STRING, index);
if (QueryNode(m_cameraNodes[index].device_index, camera_path) != 0)
continue;
if (!m_cameraNodes[index].is_usb)
{
m_cameraNodes[index].argus_index = argus_index++;
}
}
}
if (!m_cameraNodes[node_index].is_usb)
return m_cameraNodes[node_index].argus_index;
return -1;
}
int CameraNode::QueryNode(int node_index, char* device_path)
{
struct v4l2_capability v4l2_caps;
char usb[] = "usb";
int32_t camera_fd = open(device_path, O_RDWR);
if (camera_fd < 0)
{
fprintf(stderr, "Failed to open %s: %s\n", device_path,
strerror(errno));
return -1;
}
memset(&v4l2_caps, 0, sizeof(struct v4l2_capability));
if (ioctl(camera_fd, VIDIOC_QUERYCAP, &v4l2_caps))
{
fprintf(stderr, "%s: not a v4l2 node\n", device_path);
errno = ENOTTY;
close(camera_fd);
return -1;
}
if(strstr((char*)v4l2_caps.bus_info, usb) != NULL)
m_cameraNodes[node_index].is_usb = true;
close(camera_fd);
return 0;
}
void *plugin_init(int fd)
{
struct stat sb;
char str_proc_fd[512];
char device_path[512];
int index = 0;
int flags = 0;
int camera_index = -1;
ssize_t nbytes;
struct nvargus_plugin_ctx *plugin = NULL;
memset(str_proc_fd, 0, sizeof(str_proc_fd));
memset(device_path, 0, sizeof(device_path));
if (fstat(fd, &sb) == -1)
{
perror("stat");
errno = EINVAL;
return 0;
}
snprintf(str_proc_fd, sizeof(str_proc_fd), "/proc/self/fd/%d", fd);
nbytes = readlink(str_proc_fd, device_path, sizeof(device_path));
if (nbytes == -1)
{
perror("readlink");
errno = EINVAL;
return NULL;
}
flags = fcntl(fd, F_GETFL, 0);
/* Check the valid camera node "/dev/videox" */
if (strncmp(NVARGUS_DEV_STRING, device_path, 10) == 0)
{
/* To know the type of video node being opened
* by the application, an additional call is made to
* the camera driver. For USB or other unsupported devices,
* we return without initializing the argus instance.
*/
std::string argus_pathname = device_path;
try {
camera_index = stoi(argus_pathname.substr(10,
argus_pathname.length() - 10));
}
catch (...) {
perror("Error in getting camera_index\n");
return NULL;
}
int32_t argus_index = CameraNode::GetIndex(camera_index);
if (argus_index == -1)
return NULL;
// For Blocking implementation
if (flags != -1)
{
printf("Opening in BLOCKING MODE\n");
}
index = ArgusV4L2_Open(argus_index, flags);
if (index == -1)
{
perror("ArgusV4L2_Open failed");
errno = EINVAL;
return NULL;
}
plugin = (nvargus_plugin_ctx *)calloc(1, sizeof(*plugin));
if (!plugin)
{
perror("Unable to allocate memory for plugin");
errno = ENOMEM;
return NULL;
}
// CI for Blocking mode only
plugin->fd_blocking_mode = 1;
plugin->nvv4l2argus_fd = index;
}
else
return NULL;
return (void *)plugin;
}
int plugin_ioctl(void *dev_ops_priv, int fd,
unsigned long int cmd, void *arg)
{
int ret_val;
struct nvargus_plugin_ctx *plugin;
plugin = (struct nvargus_plugin_ctx *)dev_ops_priv;
ret_val = ArgusV4L2_Ioctl(plugin->nvv4l2argus_fd, cmd, arg);
return ret_val;
}
void plugin_close(void *dev_ops_priv)
{
if (dev_ops_priv == NULL)
return;
struct nvargus_plugin_ctx *ctx = (struct nvargus_plugin_ctx *)dev_ops_priv;
ArgusV4L2_Close(ctx->nvv4l2argus_fd);
free(ctx);
}
#ifdef __cplusplus
extern "C"
#endif
PLUGIN_PUBLIC const struct libv4l_dev_ops libv4l2_plugin =
{
.init = &plugin_init,
.close = &plugin_close,
.ioctl = &plugin_ioctl,
};

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <dlfcn.h>
#include "linux/videodev2.h"
#include "nvargusv4l2_os.h"
#include "nvargusv4l2.h"
#include "nvargusv4l2_context.h"
#include "nvargusv4l2_ioctl.h"
/* Default node path
*/
#define V4L2_ARGUS_DEV_NODE "/dev/video0"
/* A global mutex used to protect simultaneous access
* while opening or closing the contexts
*/
NvMutexHandle global_mutex = NULL;
bool runtime_logs_enabled = false;
static void *hLibHandle = NULL;
void __attribute__((constructor)) nvargus_init(void);
void __attribute__((destructor)) nvargus_deinit(void);
void __attribute__((constructor)) nvargus_init(void)
{
struct stat file_stats;
if (stat("/tmp/argusv4l2_logs", &file_stats) == 0)
runtime_logs_enabled = true;
hLibHandle = dlopen("libnvargus.so", RTLD_LAZY);
if (NULL == hLibHandle)
REL_PRINT("Error opening libnvargus.so in %s\n", __FUNCTION__);
if (NvMutexCreate(&global_mutex) != 0)
REL_PRINT("Error creating the global mutex\n");
}
void __attribute__((destructor)) nvargus_deinit(void)
{
NvMutexDestroy(global_mutex);
if (hLibHandle)
dlclose(hLibHandle);
}
int32_t ArgusV4L2_Open(const int camera_index, int32_t flags)
{
DBG_PRINT("Enter %s Camera Index %d\n", __FUNCTION__, camera_index);
return v4l2_open_camera_context(camera_index, flags);
}
int32_t ArgusV4L2_Close(int32_t fd)
{
DBG_PRINT("Enter %s FD %d \n", __FUNCTION__, fd);
v4l2_close_camera_context(fd);
return 0;
}
int32_t ArgusV4L2_Ioctl(int32_t fd, unsigned long cmd, ...)
{
void *arg;
v4l2_context *ctx = v4l2_get_context(fd);
va_list listPointer;
va_start(listPointer, cmd);
arg = va_arg(listPointer, void *);
va_end(listPointer);
if ((ctx == NULL) || (arg == NULL))
{
errno = EINVAL;
return -1;
}
NvMutexAcquire(ctx->ioctl_mutex);
errno = nvargus_ioctl(fd, cmd, arg);
NvMutexRelease(ctx->ioctl_mutex);
if (errno != 0)
return -1;
return errno;
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,322 @@
/*
* Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/* This file implements the context related interface methods.*/
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "linux/videodev2.h"
#include "nvargusv4l2_os.h"
#include "nvargusv4l2.h"
#include "nvargusv4l2_context.h"
#include "nvargusv4l2_ioctl.h"
static v4l2_context *contexts[MAX_CONTEXTS];
static int32_t next_free_index;
static int32_t total_open_instances;
extern NvMutexHandle global_mutex;
Argus::CameraProvider *g_cameraProvider = NULL;
Argus::ICameraProvider *g_iCameraProvider = NULL;
std::vector<Argus::CameraDevice*> g_cameraDevices; // All devices (sensors)
v4l2_context* v4l2_get_context(int32_t fd)
{
if (contexts[fd] == NULL)
{
REL_PRINT("NULL context on given FD\n");
return NULL;
}
return contexts[fd];
}
int32_t initialize_camera_provider()
{
if (!g_cameraProvider)
{
g_cameraProvider = Argus::CameraProvider::create();
if (!g_cameraProvider)
{
REL_PRINT("Failed to create Argus CameraProvider\n");
return -1;
}
}
/* Get the core interface. */
g_iCameraProvider = Argus::interface_cast<Argus::ICameraProvider>(
g_cameraProvider);
if (!g_iCameraProvider)
{
REL_PRINT("Argus does not support core camera interface\n");
return -1;
}
/* Get the list of CameraDevices to test valid execution. */
if (g_iCameraProvider->getCameraDevices(&g_cameraDevices) != Argus::STATUS_OK)
{
REL_PRINT("Failed to get camera devices\n");
return -1;
}
if (g_cameraDevices.size() == 0)
return -1;
return 0;
}
void v4l2_argus_fill_sensor_modes(std::vector<Argus::SensorMode*> sensorModes,
std::vector<argusv4l2_sensormode> *argusv4l2_sensormodes)
{
printf("Available Sensor modes :\n");
for (uint32_t idx = 0; idx < sensorModes.size(); ++idx)
{
Argus::ISensorMode *iSensorMode = NULL;
argusv4l2_sensormode argusv4l2_smidx;
iSensorMode = Argus::interface_cast<Argus::ISensorMode>(sensorModes[idx]);
argusv4l2_smidx.min_width = FRAMESIZE_MIN_WIDTH;
argusv4l2_smidx.min_height = FRAMESIZE_MIN_HEIGHT;
argusv4l2_smidx.max_width = iSensorMode->getResolution().width();
argusv4l2_smidx.max_height = iSensorMode->getResolution().height();
argusv4l2_smidx.frame_duration = iSensorMode->getFrameDurationRange().min();
argusv4l2_smidx.bitdepth = iSensorMode->getInputBitDepth();
argusv4l2_smidx.minGainRange = iSensorMode->getAnalogGainRange().min();
argusv4l2_smidx.maxGainRange = iSensorMode->getAnalogGainRange().max();
argusv4l2_smidx.minExposureTimeRange = iSensorMode->getExposureTimeRange().min();
argusv4l2_smidx.maxExposureTimeRange = iSensorMode->getExposureTimeRange().max();
argusv4l2_sensormodes->push_back(argusv4l2_smidx);
printf("Resolution: %d x %d ; Framerate = %f; Analog Gain Range Min %f, Max %f, "
"Exposure Range Min %lu, Max %lu\n\n", iSensorMode->getResolution().width(),
iSensorMode->getResolution().height(), (1e9/iSensorMode->getFrameDurationRange().min()),
iSensorMode->getAnalogGainRange().min(), iSensorMode->getAnalogGainRange().max(),
iSensorMode->getExposureTimeRange().min(), iSensorMode->getExposureTimeRange().max());
}
}
void v4l2_argus_set_defaults(cam_params *argus_defaults, cam_settings *argus_settings)
{
/* Argus Defaults */
argus_defaults->width = 640;
argus_defaults->height = 480;
argus_defaults->pixelformat = V4L2_PIX_FMT_NV12M;
argus_defaults->argus_format = Argus::PIXEL_FMT_YCbCr_420_888;
argus_defaults->bitdepth = 8;
argus_settings->sensorModeIdx = -1;
argus_settings->frameDuration = 1e9/30;
argus_settings->awbLock = false;
argus_settings->aeLock = false;
argus_settings->aeAntibandingMode = V4L2_ARGUS_AE_ANTIBANDING_MODE_AUTO;
argus_settings->awbMode = V4L2_ARGUS_AWB_MODE_AUTO;
argus_settings->edgeEnhanceMode = V4L2_ARGUS_EDGE_ENHANCE_MODE_FAST;
argus_settings->edgeEnhanceStrength = -1.0;
argus_settings->denoiseMode = V4L2_ARGUS_DENOISE_MODE_FAST;
argus_settings->denoiseStrength = -1.0;
argus_settings->exposureCompensation = 0.0;
argus_settings->ispDigitalGainRange = Argus::Range<float>(1.0, 256.0);
argus_settings->enableColorSaturation = true;
argus_settings->colorSaturation = 1.0;
argus_settings->gainRange = Argus::Range<float>(1.0, 16.0);
}
// This call checks if we can register the plugin under Argus
int32_t initialize_arguscamera(v4l2_camera_context *ctx, uint32_t camera_index)
{
/* Create the CameraProvider. */
if (initialize_camera_provider() != 0)
{
REL_PRINT("Failed to initialize camera devices\n");
goto error;
}
ctx->m_captureSession = Argus::UniqueObj<Argus::CaptureSession>(
g_iCameraProvider->createCaptureSession(g_cameraDevices[camera_index]));
ctx->m_iCaptureSession =
Argus::interface_cast<Argus::ICaptureSession>(ctx->m_captureSession);
if (!ctx->m_iCaptureSession)
{
REL_PRINT("Failed to get ICaptureSession interface\n");
goto error;
}
ctx->m_iEventProvider =
Argus::interface_cast<Argus::IEventProvider>(ctx->m_captureSession);
if (!ctx->m_iEventProvider)
{
REL_PRINT("Failed to get IEventProvider interface\n");
goto error;
}
/* Argus drops EVENT_TYPE_ERROR if all 3 events are not subscribed. Setting all for now */
ctx->m_eventTypes.push_back(Argus::EVENT_TYPE_CAPTURE_COMPLETE);
ctx->m_eventTypes.push_back(Argus::EVENT_TYPE_CAPTURE_STARTED);
ctx->m_eventTypes.push_back(Argus::EVENT_TYPE_ERROR);
ctx->m_eventQueue = Argus::UniqueObj<Argus::EventQueue>(
ctx->m_iEventProvider->createEventQueue(ctx->m_eventTypes));
ctx->m_iEventQueue = Argus::interface_cast<Argus::IEventQueue>(ctx->m_eventQueue);
if (!ctx->m_iEventQueue)
{
REL_PRINT("Failed to get EventQueue interface\n");
goto error;
}
ctx->m_iCameraProperties = Argus::interface_cast<Argus::ICameraProperties>(
g_cameraDevices[camera_index]);
if (!ctx->m_iCameraProperties)
{
REL_PRINT("Failed to create camera properties\n");
goto error;
}
ctx->m_iCameraProperties->getAllSensorModes(&ctx->m_sensorModes);
if (ctx->m_sensorModes.size() == 0)
{
REL_PRINT("No Sensor Mode found associated with the camera node\n");
goto error;
}
v4l2_argus_fill_sensor_modes(ctx->m_sensorModes, &ctx->argusv4l2_sensormodes);
v4l2_argus_set_defaults(&ctx->argus_params, &ctx->argus_settings);
return 0;
error:
if (g_cameraProvider)
g_cameraProvider->destroy();
if (ctx->m_captureSession)
ctx->m_captureSession.reset();
if (ctx->m_eventQueue)
ctx->m_eventQueue.reset();
g_cameraDevices.clear();
ctx->m_sensorModes.clear();
ctx->m_eventTypes.clear();
g_iCameraProvider = NULL;
ctx->m_iCaptureSession = NULL;
ctx->m_iEventProvider = NULL;
ctx->m_iEventQueue = NULL;
ctx->m_iCameraProperties = NULL;
return -1;
}
int32_t v4l2_open_camera_context(uint32_t camera_index, int32_t flags)
{
int32_t index = 0, loop_cnt = 0;
v4l2_context *ctx = NULL;
v4l2_camera_context *camera_ctx = NULL;
v4l2_lock_global_mutex();
index = next_free_index;
for (loop_cnt = 0; loop_cnt < MAX_CONTEXTS; ++loop_cnt)
{
if (contexts[index] == NULL)
{
contexts[index] = (v4l2_context *)malloc(sizeof(v4l2_context));
ctx = contexts[index];
memset(contexts[index], 0x0, sizeof(v4l2_context));
REL_PRINT("Allocated ctx %p at idx %d\n", contexts[index], index);
if (NvMutexCreate(&ctx->ioctl_mutex) != 0)
{
REL_PRINT("Error in creating ioctl_mutex\n");
free(contexts[index]);
goto ctx_error;
}
camera_ctx = (v4l2_camera_context *)malloc(sizeof(v4l2_camera_context));
if (camera_ctx == NULL)
{
REL_PRINT("Error allocating argus context\n");
free(contexts[index]);
goto ctx_error;
}
memset((void*)camera_ctx, 0x0, sizeof(v4l2_camera_context));
if (initialize_arguscamera(camera_ctx, camera_index) < 0)
{
REL_PRINT("Failed to initialize camera\n");
free(camera_ctx);
free(contexts[index]);
goto ctx_error;
}
ctx->actual_context = (void *)camera_ctx;
total_open_instances++;
if (NvMutexCreate(&camera_ctx->context_mutex) != 0)
{
REL_PRINT("Error creating context mutex\n");
free(camera_ctx);
free(contexts[index]);
goto ctx_error;
}
camera_ctx->blocking_mode = ! (flags & O_NONBLOCK);
next_free_index = index + 1;
if (next_free_index == 128)
next_free_index = 0;
v4l2_unlock_global_mutex();
return index;
}
index++;
if (index == MAX_CONTEXTS)
index = 0;
}
REL_PRINT("No free index left , something is wrong \n");
ctx_error:
v4l2_unlock_global_mutex();
return -1;
}
void v4l2_close_camera_context(int32_t fd)
{
v4l2_context *ctx = v4l2_get_context(fd);
REL_PRINT("CAM_CTX(%p) Closing the context %s\n", ctx->actual_context, __func__);
/* Close the camera context */
NvMutexAcquire(ctx->ioctl_mutex);
v4l2_lock_global_mutex();
total_open_instances--;
v4l2_close_argus_context(ctx);
NvMutexRelease(ctx->ioctl_mutex);
NvMutexDestroy(ctx->ioctl_mutex);
free(ctx);
contexts[fd] = NULL;
if (total_open_instances == 0)
{
if (g_cameraProvider)
g_cameraProvider->destroy();
g_cameraDevices.clear();
g_iCameraProvider = NULL;
}
REL_PRINT("Total Opened instances: %d\n", total_open_instances);
v4l2_unlock_global_mutex();
}
void v4l2_lock_global_mutex(void)
{
assert(global_mutex != NULL);
NvMutexAcquire(global_mutex);
}
void v4l2_unlock_global_mutex(void)
{
assert(global_mutex != NULL);
NvMutexRelease(global_mutex);
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,208 @@
/*
* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <string.h>
#include <errno.h>
#include "nvargusv4l2_nvqueue.h"
int32_t NvQueueCreate(NvQueueHandle *phQueue, u_int32_t maxEntries, u_int32_t entrySize)
{
NvQueue *pQueue;
int32_t retval = 0;
if (maxEntries == 0)
return EINVAL;
pQueue = (NvQueue *)malloc(sizeof(NvQueue));
if (!pQueue)
return ENOMEM;
memset(pQueue, 0x0, sizeof(NvQueue));
pQueue->pEntryList = 0;
pQueue->pushIndex = 0;
pQueue->popIndex = 0;
pQueue->maxEntries = maxEntries + 1;
pQueue->entrySize = entrySize;
retval = NvMutexCreate(&pQueue->mutexLock);
if (retval != 0)
goto nvqueue_exit;
pQueue->pEntryList = (u_int8_t *)malloc(pQueue->maxEntries * entrySize);
if (!pQueue->pEntryList)
{
retval = ENOMEM;
goto nvqueue_exit;
}
*phQueue = pQueue;
return 0;
nvqueue_exit:
if (pQueue)
{
NvMutexDestroy(pQueue->mutexLock);
free(pQueue);
}
*phQueue = 0;
return retval;
}
int32_t NvQueueEnQ(NvQueueHandle hQueue, void *pElem)
{
NvQueue *pQueue = hQueue;
int32_t retval = 0;
u_int32_t pushIdx, popIdx;
NvMutexAcquire(pQueue->mutexLock);
if (pElem == NULL)
{
retval = EINVAL;
goto nvqueue_exit;
}
pushIdx = pQueue->pushIndex;
popIdx = pQueue->popIndex;
/* Check if space available */
if (pushIdx + 1 == popIdx || pushIdx + 1 == popIdx + pQueue->maxEntries)
{
retval = ENOMEM;
goto nvqueue_exit;
}
memcpy(&pQueue->pEntryList[pushIdx * pQueue->entrySize], pElem,
pQueue->entrySize);
if (++pushIdx >= pQueue->maxEntries)
pushIdx = 0;
pQueue->pushIndex = pushIdx;
nvqueue_exit:
NvMutexRelease(pQueue->mutexLock);
return retval;
}
int32_t NvQueueDeQ(NvQueueHandle hQueue, void *pElem)
{
NvQueue *pQueue = hQueue;
int32_t retval = 0;
u_int32_t popIdx;
NvMutexAcquire(pQueue->mutexLock);
popIdx = pQueue->popIndex;
if (pQueue->pushIndex == popIdx)
{
retval = EINVAL;
goto nvqueue_exit;
}
memcpy(pElem, &pQueue->pEntryList[popIdx * pQueue->entrySize],
pQueue->entrySize);
if (++popIdx >= pQueue->maxEntries)
popIdx = 0;
pQueue->popIndex = popIdx;
nvqueue_exit:
NvMutexRelease(pQueue->mutexLock);
return retval;
}
int32_t NvQueuePeek(NvQueueHandle hQueue, void *pElem)
{
NvQueue *pQueue = hQueue;
int32_t retval = 0;
u_int32_t popIdx;
NvMutexAcquire(pQueue->mutexLock);
popIdx = pQueue->popIndex;
if (pQueue->pushIndex == popIdx)
{
retval = EINVAL;
goto nvqueue_exit;
}
memcpy(pElem, &pQueue->pEntryList[popIdx * pQueue->entrySize],
pQueue->entrySize);
nvqueue_exit:
NvMutexRelease(pQueue->mutexLock);
return retval;
}
int32_t NvQueuePeekEntry(NvQueueHandle hQueue, void *pElem, u_int32_t nEntry)
{
NvQueue *pQueue = hQueue;
int32_t err = 0;
u_int32_t entry, pushIdx, popIdx, numEntries;
NvMutexAcquire(pQueue->mutexLock);
pushIdx = pQueue->pushIndex;
popIdx = pQueue->popIndex;
numEntries = (pushIdx >= popIdx) ? pushIdx - popIdx : pQueue->maxEntries - popIdx + pushIdx;
if ((numEntries == 0) || (numEntries <= nEntry))
{
err = EINVAL;
goto nvqueue_exit;
}
entry = popIdx + nEntry;
if (entry >= pQueue->maxEntries)
entry -= pQueue->maxEntries;
memcpy(pElem, &pQueue->pEntryList[entry * pQueue->entrySize],
pQueue->entrySize);
nvqueue_exit:
NvMutexRelease(pQueue->mutexLock);
return err;
}
void NvQueueDestroy(NvQueueHandle *phQueue)
{
NvQueue *pQueue = *phQueue;
if (!pQueue)
return;
NvMutexDestroy(pQueue->mutexLock);
free(pQueue->pEntryList);
free(pQueue);
*phQueue = NULL;
}
u_int32_t NvQueueGetNumEntries(NvQueueHandle hQueue)
{
NvQueue *pQueue = hQueue;
u_int32_t pushIdx = pQueue->pushIndex;
u_int32_t popIdx = pQueue->popIndex;
u_int32_t numEntries = (pushIdx >= popIdx) ? pushIdx - popIdx : pQueue->maxEntries - popIdx + pushIdx;
return numEntries;
}

View File

@@ -0,0 +1,287 @@
/*
* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <errno.h>
#include "nvargusv4l2_os.h"
typedef struct NvMutex_
{
pthread_mutex_t mutex;
u_int32_t count;
} NvMutex;
typedef struct NvSemaphore_
{
pthread_mutex_t mutex;
pthread_cond_t cond;
u_int32_t count; /* Sema value*/
} NvSemaphore;
typedef struct NvThread_
{
pthread_t thread;
} NvThread;
typedef struct
{
NvThreadFunction function;
NvThread *thread;
pthread_mutex_t barrier;
void *thread_args;
NvSemaphoreHandle init;
} NvThreadArgs;
int32_t NvMutexCreate(NvMutexHandle *mHandle)
{
NvMutex *m;
pthread_mutexattr_t attr;
m = (NvMutex *)malloc(sizeof(NvMutex));
if (!m)
{
*mHandle = NULL;
return ENOMEM;
}
/* Mutex initialization for local process */
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m->mutex, &attr);
pthread_mutexattr_destroy(&attr);
m->count = 0;
*mHandle = m;
return 0;
}
int32_t NvMutexAcquire(NvMutexHandle mHandle)
{
int32_t val = 0;
if (!mHandle)
return EINVAL;
val = pthread_mutex_lock(&mHandle->mutex);
mHandle->count++;
if (val)
return val;
return 0;
}
int32_t NvMutexRelease(NvMutexHandle mHandle)
{
int32_t val = 0;
if (!mHandle)
return EINVAL;
mHandle->count--;
val = pthread_mutex_unlock(&mHandle->mutex);
if (val)
return val;
return 0;
}
int32_t NvMutexDestroy(NvMutexHandle mHandle)
{
int32_t val = 0;
if (!mHandle)
return EINVAL;
val = pthread_mutex_destroy(&mHandle->mutex);
if (val)
return val;
free(mHandle);
return 0;
}
int32_t NvSemaphoreCreate(NvSemaphoreHandle *semaHandle, u_int32_t cnt)
{
int32_t val = 0;
NvSemaphore *sema = (NvSemaphore *)malloc(sizeof(NvSemaphore));
if (!sema)
return ENOMEM;
val = pthread_mutex_init(&sema->mutex, 0);
if (val)
{
free(sema);
return val;
}
val = pthread_cond_init(&sema->cond, 0);
if (val)
{
pthread_mutex_destroy(&sema->mutex);
free(sema);
return val;
}
sema->count = cnt;
*semaHandle = sema;
return 0;
}
void NvSemaphoreWait(NvSemaphoreHandle semaHandle)
{
if (!semaHandle)
return;
pthread_mutex_lock(&semaHandle->mutex);
while (!semaHandle->count)
{
pthread_cond_wait(&semaHandle->cond, &semaHandle->mutex);
}
semaHandle->count--;
pthread_mutex_unlock(&semaHandle->mutex);
}
void NvSemaphoreSignal(NvSemaphoreHandle semaHandle)
{
if (!semaHandle)
return;
pthread_mutex_lock(&semaHandle->mutex);
semaHandle->count++;
pthread_cond_signal(&semaHandle->cond);
pthread_mutex_unlock(&semaHandle->mutex);
}
int32_t NvSemaphoreDestroy(NvSemaphoreHandle semaHandle)
{
int32_t val_m = 0, val_c = 0;
if (!semaHandle)
return EINVAL;
val_m = pthread_mutex_destroy(&semaHandle->mutex);
val_c = pthread_cond_destroy(&semaHandle->cond);
free(semaHandle);
return (!val_m && !val_c) ? 0 : EINVAL;
}
static void *thread_wrapper(void *pThread)
{
NvThreadArgs *args = (NvThreadArgs *)pThread;
if (!args)
return NULL;
NvSemaphoreSignal(args->init);
pthread_mutex_lock(&args->barrier);
pthread_mutex_unlock(&args->barrier);
args->function(args->thread_args);
pthread_mutex_destroy(&args->barrier);
NvSemaphoreDestroy(args->init);
free(args);
return 0;
}
int32_t NvThreadCreate(
NvThreadFunction function,
void *tArgs,
NvThreadHandle *tHandle)
{
int32_t err;
NvThread *thrd = 0;
NvThreadArgs *args = 0;
if (!function || !tHandle)
return EINVAL;
/* create the thread struct */
thrd = (NvThread *)malloc(sizeof(NvThread));
if (thrd == NULL)
goto fail;
memset(thrd, 0x0, sizeof(NvThread));
/* setup the thread args */
args = (NvThreadArgs *)malloc(sizeof(NvThreadArgs));
if (args == NULL)
goto fail;
memset(args, 0x0, sizeof(NvThreadArgs));
args->function = function;
args->thread = thrd;
args->thread_args = tArgs;
(void)pthread_mutex_init(&args->barrier, 0);
/* The thread is created with the mutex lock held, to prevent
* race conditions between thread assignment and
* thread function execution */
NvSemaphoreCreate(&args->init, 0);
pthread_mutex_lock(&args->barrier);
err = pthread_create(&thrd->thread, 0, thread_wrapper, args);
if (err)
goto fail;
NvSemaphoreWait(args->init);
*tHandle = thrd;
pthread_mutex_unlock(&args->barrier);
return 0;
fail:
if (args)
{
pthread_mutex_unlock(&args->barrier);
pthread_mutex_destroy(&args->barrier);
}
free(args);
free(thrd);
*tHandle = 0;
return ENOMEM;
}
int32_t NvThreadSetName(NvThreadHandle t, const char *name)
{
int32_t val = pthread_setname_np(t->thread, name);
return val;
}
void NvThreadJoin(NvThreadHandle tHandle)
{
if (!tHandle)
return;
int32_t val = pthread_join(tHandle->thread, 0);
if (val)
return;
free(tHandle);
}
u_int64_t NvGetCurrentThreadId(void)
{
return pthread_self();
}

1
push_info.txt Normal file
View File

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