Files
libv4l2_nvargus/libv4l2_nvargus/nvargusv4l2_context.cpp
svcmobrel-release 9d0a7f9ced 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
2023-12-05 20:47:45 -08:00

323 lines
11 KiB
C++

/*
* 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);
}