diff --git a/commitFile.txt b/commitFile.txt new file mode 100644 index 0000000..f940afe --- /dev/null +++ b/commitFile.txt @@ -0,0 +1,10 @@ +Updating prebuilts and/or headers + +1be6fc0d7406e0633b7e2cba49166a2f0a085cdd - gst-nvarguscamera/Makefile +85aa07275306e93b61dc11f05d3733ba6a79d17c - gst-nvarguscamera/3rdpartyheaders.tbz2 +599e80d95060e15842bc5d41b27ef7da35cbf8c0 - gst-nvarguscamera/gstnvarguscamerasrc.hpp +5d36eec5a4929d1a09ab8ca8e7f618b8f349275d - gst-nvarguscamera/gstnvarguscamerasrc.cpp +f2949ff626879be5aaeabf40e9ad8eab11238b6e - gst-nvarguscamera/gstnvarguscamera_utils.h +44b0e909f18f7e2f457ba501fc47d80ecedd150b - gst-nvarguscamera/nvbufsurface.h +5b71a3ab30d24949dcf3770e509d17dd1af64256 - gst-nvarguscamera/gstnvarguscamera_utils.cpp +fa14f1cb043a26a6465ce793ac78479d8f6afa02 - gst-nvarguscamera/gstnvdsbufferpool.h diff --git a/gst-nvarguscamera/3rdpartyheaders.tbz2 b/gst-nvarguscamera/3rdpartyheaders.tbz2 new file mode 100644 index 0000000..9a69cc7 Binary files /dev/null and b/gst-nvarguscamera/3rdpartyheaders.tbz2 differ diff --git a/gst-nvarguscamera/Makefile b/gst-nvarguscamera/Makefile new file mode 100644 index 0000000..b5a4940 --- /dev/null +++ b/gst-nvarguscamera/Makefile @@ -0,0 +1,74 @@ +# Copyright (c) 2020-2022, NVIDIA CORPORATION. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * 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 := libgstnvarguscamerasrc.so + +CC := g++ + +GST_INSTALL_DIR?=/usr/lib/aarch64-linux-gnu/gstreamer-1.0/ +LIB_INSTALL_DIR?=/usr/lib/aarch64-linux-gnu/tegra/ +CFLAGS:= +LIBS:= -lnvbufsurface -lnvbufsurftransform -lnvdsbufferpool -lnvargus_socketclient -lpthread + +SRCS := $(wildcard *.cpp) + +INCLUDES += -I./ -I../ + +# Include jetson_mm_api include path +INCLUDES += -I/usr/src/jetson_multimedia_api/include/ +INCLUDES += -I/usr/src/jetson_multimedia_api/argus/samples/utils/ + +PKGS := gstreamer-1.0 \ + gstreamer-base-1.0 \ + gstreamer-video-1.0 \ + gstreamer-allocators-1.0 \ + glib-2.0 + +OBJS := $(SRCS:.cpp=.o) + +CFLAGS += -fPIC + +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-nvarguscamera/README.txt b/gst-nvarguscamera/README.txt new file mode 100644 index 0000000..f04de1c --- /dev/null +++ b/gst-nvarguscamera/README.txt @@ -0,0 +1,51 @@ +# Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * 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-nvarguscamera" 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 \ + libegl1-mesa-dev + +2) Install "jetson_multimedia_api" package from latest Jetpack release. + +3) Download and extract the package "gst-nvarguscamera_src.tbz2" as follow: + + tar -I lbzip2 -xvf gst-nvarguscamera_src.tbz2 + +3) Run the following commands to build and install "libgstnvarguscamerasrc.so": + cd "gst-nvarguscamera" + make + make install + or + DEST_DIR= make install + + Note: "make install" will copy library "libgstnvarguscamerasrc.so" + into "/usr/lib/aarch64-linux-gnu/gstreamer-1.0" directory. diff --git a/gst-nvarguscamera/gstnvarguscamera_utils.cpp b/gst-nvarguscamera/gstnvarguscamera_utils.cpp new file mode 100644 index 0000000..c21e9c4 --- /dev/null +++ b/gst-nvarguscamera/gstnvarguscamera_utils.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2017-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. + */ + +#include "gstnvarguscamera_utils.h" +#include + +GType +gst_nvarguscam_white_balance_mode_get_type (void) +{ + static gsize white_balance_type = 0; + static const GEnumValue white_balance_mode[] = { + {NvArgusCamAwbMode_Off, "GST_NVCAM_WB_MODE_OFF", "off"}, + {NvArgusCamAwbMode_Auto, "GST_NVCAM_WB_MODE_AUTO", "auto"}, + {NvArgusCamAwbMode_Incandescent, "GST_NVCAM_WB_MODE_INCANDESCENT", + "incandescent"}, + {NvArgusCamAwbMode_Fluorescent, "GST_NVCAM_WB_MODE_FLUORESCENT", "fluorescent"}, + {NvArgusCamAwbMode_WarmFluorescent, "GST_NVCAM_WB_MODE_WARM_FLUORESCENT", + "warm-fluorescent"}, + {NvArgusCamAwbMode_Daylight, "GST_NVCAM_WB_MODE_DAYLIGHT", "daylight"}, + {NvArgusCamAwbMode_CloudyDaylight, "GST_NVCAM_WB_MODE_CLOUDY_DAYLIGHT", + "cloudy-daylight"}, + {NvArgusCamAwbMode_Twilight, "GST_NVCAM_WB_MODE_TWILIGHT", "twilight"}, + {NvArgusCamAwbMode_Shade, "GST_NVCAM_WB_MODE_SHADE", "shade"}, + {NvArgusCamAwbMode_Manual, "GST_NVCAM_WB_MODE_MANUAL", "manual"}, + {0, NULL, NULL} + }; + + if (g_once_init_enter (&white_balance_type)) { + GType tmp = g_enum_register_static ("GstNvArgusCamWBMode", white_balance_mode); + g_once_init_leave (&white_balance_type, tmp); + } + + return (GType) white_balance_type; +} + +GType +gst_nvarguscam_tnr_mode_get_type (void) +{ + static gsize tnr_type = 0; + static const GEnumValue tnr_mode[] = { + {NvArgusCamNoiseReductionMode_Off, "GST_NVCAM_NR_OFF", "NoiseReduction_Off"}, + {NvArgusCamNoiseReductionMode_Fast, "GST_NVCAM_NR_FAST", "NoiseReduction_Fast"}, + {NvArgusCamNoiseReductionMode_HighQuality, "GST_NVCAM_NR_HIGHQUALITY", "NoiseReduction_HighQuality"}, + {0, NULL, NULL} + }; + + if (g_once_init_enter (&tnr_type)) { + GType tmp = g_enum_register_static ("GstNvArgusCamTNRMode", tnr_mode); + g_once_init_leave (&tnr_type, tmp); + } + return (GType) tnr_type; +} + +GType +gst_nvarguscam_edge_enhancement_mode_get_type (void) +{ + static gsize edge_enhancement_type = 0; + static const GEnumValue edge_enhancement_mode[] = { + {NvArgusCamEdgeEnhancementMode_Off, "GST_NVCAM_EE_OFF", "EdgeEnhancement_Off"}, + {NvArgusCamEdgeEnhancementMode_Fast, "GST_NVCAM_EE_FAST", "EdgeEnhancement_Fast"}, + {NvArgusCamEdgeEnhancementMode_HighQuality, "GST_NVCAM_EE_HIGHQUALITY", "EdgeEnhancement_HighQuality"}, + {0, NULL, NULL} + }; + + if (g_once_init_enter (&edge_enhancement_type)) { + GType tmp = g_enum_register_static ("GstNvArgusCamEEMode", edge_enhancement_mode); + g_once_init_leave (&edge_enhancement_type, tmp); + } + return (GType) edge_enhancement_type; +} + +GType +gst_nvarguscam_aeantibanding_mode_get_type (void) +{ + static gsize aeantibanding_type = 0; + static const GEnumValue aeantibanding_mode[] = { + {NvArgusCamAeAntibandingMode_Off, "GST_NVCAM_AEANTIBANDING_OFF", "AeAntibandingMode_Off"}, + {NvArgusCamAeAntibandingMode_Auto, "GST_NVCAM_AEANTIBANDING_AUTO", "AeAntibandingMode_Auto"}, + {NvArgusCamAeAntibandingMode_50HZ, "GST_NVCAM_AEANTIBANDING_50HZ", "AeAntibandingMode_50HZ"}, + {NvArgusCamAeAntibandingMode_60HZ, "GST_NVCAM_AEANTIBANDING_60HZ", "AeAntibandingMode_60HZ"}, + {0, NULL, NULL} + }; + + if (g_once_init_enter (&aeantibanding_type)) { + GType tmp = g_enum_register_static ("GstNvArgusCamAeAntiBandingMode", aeantibanding_mode); + g_once_init_leave (&aeantibanding_type, tmp); + } + return (GType) aeantibanding_type; +} \ No newline at end of file diff --git a/gst-nvarguscamera/gstnvarguscamera_utils.h b/gst-nvarguscamera/gstnvarguscamera_utils.h new file mode 100644 index 0000000..3bfea40 --- /dev/null +++ b/gst-nvarguscamera/gstnvarguscamera_utils.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2017-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 GSTNVARGUSCAMERA_UTILS_H_ +#define GSTNVARGUSCAMERA_UTILS_H_ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef enum +{ + NvArgusCamAwbMode_Off = 0, + NvArgusCamAwbMode_Auto, + NvArgusCamAwbMode_Incandescent, + NvArgusCamAwbMode_Fluorescent, + NvArgusCamAwbMode_WarmFluorescent, + NvArgusCamAwbMode_Daylight, + NvArgusCamAwbMode_CloudyDaylight, + NvArgusCamAwbMode_Twilight, + NvArgusCamAwbMode_Shade, + NvArgusCamAwbMode_Manual, + +} NvArgusCamAwbMode; + +typedef enum +{ + NvArgusCamNoiseReductionMode_Off = 0, + NvArgusCamNoiseReductionMode_Fast, + NvArgusCamNoiseReductionMode_HighQuality + +} NvArgusCamNoiseReductionMode; + +typedef enum +{ + NvArgusCamEdgeEnhancementMode_Off = 0, + NvArgusCamEdgeEnhancementMode_Fast, + NvArgusCamEdgeEnhancementMode_HighQuality + +} NvArgusCamEdgeEnhancementMode; + +typedef enum +{ + NvArgusCamAeAntibandingMode_Off = 0, + NvArgusCamAeAntibandingMode_Auto, + NvArgusCamAeAntibandingMode_50HZ, + NvArgusCamAeAntibandingMode_60HZ + +} NvArgusCamAeAntibandingMode; + +GType gst_nvarguscam_white_balance_mode_get_type (void); +#define GST_TYPE_NVARGUSCAM_WB_MODE (gst_nvarguscam_white_balance_mode_get_type()) + +GType gst_nvarguscam_tnr_mode_get_type (void); +#define GST_TYPE_NVARGUSCAM_TNR_MODE (gst_nvarguscam_tnr_mode_get_type()) + +GType gst_nvarguscam_edge_enhancement_mode_get_type (void); +#define GST_TYPE_NVARGUSCAM_EDGE_ENHANCEMENT_MODE (gst_nvarguscam_edge_enhancement_mode_get_type()) + +GType gst_nvarguscam_aeantibanding_mode_get_type (void); +#define GST_TYPE_NVARGUSCAM_AEANTIBANDING_MODE (gst_nvarguscam_aeantibanding_mode_get_type()) + +#ifdef __cplusplus +} +#endif + +#endif /* GSTNVARGUSCAMERA_UTILS_H_ */ diff --git a/gst-nvarguscamera/gstnvarguscamerasrc.cpp b/gst-nvarguscamera/gstnvarguscamerasrc.cpp new file mode 100644 index 0000000..620c338 --- /dev/null +++ b/gst-nvarguscamera/gstnvarguscamerasrc.cpp @@ -0,0 +1,2589 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2017-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Sample pipeline + * + * gst-launch-1.0 + * nvarguscamerasrc ! + * "video/x-raw(memory:NVMM), width=640, height=480, format=NV12, framerate=30/1" ! + * nvoverlaysink -e -v + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include // for useconds_t + +#include "Ordered.h" + +#include "gstnvarguscamerasrc.hpp" +#include "Error.h" + +#define CAPTURE_CAPS \ + "video/x-raw(memory:NVMM), " \ + "width = (int) [ 1, MAX ], " \ + "height = (int) [ 1, MAX ], " \ + "format = (string) { NV12 }, " \ + "framerate = (fraction) [ 0, MAX ];" + +#define MIN_BUFFERS 6 +#define MAX_BUFFERS 8 + +// this is gain value applied by ISP, its default range is [1, 256]. +#define MIN_DIGITAL_GAIN 1 +#define MAX_DIGITAL_GAIN 256 + +#define GST_NVARGUS_MEMORY_TYPE "nvarguscam" +static const int DEFAULT_FPS = 30; +static const uint64_t DEFAULT_WAIT_FOR_EVENT_TIMEOUT = 3000000000; +static const uint64_t DEFAULT_ACQUIRE_FRAME_TIMEOUT = 5000000000; + +/* TODO: Remove this as camera o/p should always be BL. Will change once BL interop pipelines are supported for OpenRM */ +static gboolean is_nvgpu = TRUE; + +#ifdef __cplusplus +extern "C" +{ +#endif + +using namespace std; +using namespace Argus; +using namespace EGLStream; + +std::mutex g_mtx; +class CameraProviderContainer +{ +public: + CameraProviderContainer() + { + m_cameraProvider = CameraProvider::create(); + if (!m_cameraProvider) + return; + + m_iCameraProvider = interface_cast(m_cameraProvider); + m_iCameraProvider->getCameraDevices(&m_cameraDevices); + } + + ~CameraProviderContainer() + { + if (m_cameraProvider) + m_cameraProvider->destroy(); + } + + ICameraProvider* getICameraProvider(); + std::vector getCameraDevices(); +private: + CameraProvider *m_cameraProvider = NULL; + ICameraProvider *m_iCameraProvider = NULL; + std::vector m_cameraDevices; +}; + +ICameraProvider* CameraProviderContainer::getICameraProvider() +{ + if (!m_cameraProvider) + return NULL; + + return m_iCameraProvider; +} + +vector CameraProviderContainer::getCameraDevices() +{ + return m_cameraDevices; +} + +shared_ptr g_cameraProvider = make_shared(); + +namespace ArgusSamples +{ + +ThreadArgus::ThreadArgus() + : m_doShutdown(false) + , m_threadID(0) + , m_threadState(THREAD_INACTIVE) + +{ +} + +ThreadArgus::~ThreadArgus() +{ + (void)shutdown(); +} + +bool ThreadArgus::initialize(GstNvArgusCameraSrc *src) +{ + if (m_threadID) + return true; + + this->src = src; + + if (pthread_create(&m_threadID, NULL, threadFunctionStub, this) != 0) + ORIGINATE_ERROR("Failed to create thread."); + + // wait for the thread to start up + while (m_threadState == THREAD_INACTIVE) + { + usleep(100); + if (m_threadState == THREAD_FAILED) + return false; + } + + return true; +} + +bool ThreadArgus::shutdown() +{ + if (m_threadID) + { + m_doShutdown = true; + if (pthread_join(m_threadID, NULL) != 0) + ORIGINATE_ERROR("Failed to join thread"); + m_threadID = 0; + m_doShutdown = false; + m_threadState = THREAD_INACTIVE; + } + + return true; +} + +bool ThreadArgus::waitRunning(useconds_t timeoutUs) +{ + // Can only wait for a thread which is initializing or already running + if ((m_threadState != THREAD_INITIALIZING) && (m_threadState != THREAD_RUNNING)) + ORIGINATE_ERROR("Invalid thread state %d", m_threadState.get()); + + // wait for the thread to run + const useconds_t sleepTimeUs = 100; + while (m_threadState != THREAD_RUNNING) + { + usleep(sleepTimeUs); + if (m_threadState == THREAD_FAILED) + { + ORIGINATE_ERROR("Invalid thread state %d", m_threadState.get()); + } +#ifdef DEBUG + // in debug mode wait indefinitely +#else + if (timeoutUs < sleepTimeUs) + return false; + timeoutUs -= sleepTimeUs; +#endif + } + + return true; +} + +/** + * Thread function stub, calls the real thread function. + * + * @param [in] dataPtr Pointer to user data + */ +/* static */ void *ThreadArgus::threadFunctionStub(void *dataPtr) +{ + ThreadArgus *thread = static_cast(dataPtr); + + if (!thread->threadFunction(thread->src)) + thread->m_threadState = ThreadArgus::THREAD_FAILED; + else + thread->m_threadState = ThreadArgus::THREAD_DONE; + + return NULL; +} + +/** + * Thread function + */ +bool ThreadArgus::threadFunction(GstNvArgusCameraSrc *src) +{ + m_threadState = THREAD_INITIALIZING; + + PROPAGATE_ERROR(threadInitialize(src)); + + m_threadState = THREAD_RUNNING; + + while (!m_doShutdown) + { + PROPAGATE_ERROR(threadExecute(src)); + } + + PROPAGATE_ERROR(threadShutdown(src)); + + return true; +} + +}; // namespace ArgusSamples + +namespace ArgusCamera +{ + +// Constants + +#define GST_ARGUS_PRINT(...) printf("GST_ARGUS: " __VA_ARGS__) +#define CONSUMER_PRINT(...) printf("CONSUMER: " __VA_ARGS__) +#define GST_ARGUS_ERROR(...) printf("ARGUS_ERROR: Error generated. %s, %s: %d %s", __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__) + +const char* getStatusString(Argus::Status status); + +/******************************************************************************* + * StreamConsumer thread: + * Creates a StreamConsumer object to read frames from the OutputStream just tests + * for sanity. + ******************************************************************************/ +class StreamConsumer : public ArgusSamples::ThreadArgus +{ +public: + explicit StreamConsumer(OutputStream* stream) : + m_stream(stream) + { + } + ~StreamConsumer() + { + } + +private: + /** @name Thread methods */ + /**@{*/ + virtual bool threadInitialize(GstNvArgusCameraSrc *); + virtual bool threadExecute(GstNvArgusCameraSrc *); + virtual bool threadShutdown(GstNvArgusCameraSrc *); + /**@}*/ + + OutputStream* m_stream; + //GstNvArgusCameraSrc *argus_src; + UniqueObj m_consumer; +}; + +const char* getStatusString(Argus::Status status) +{ + switch (status) + { + case Argus::STATUS_OK: return "OK"; + case Argus::STATUS_INVALID_PARAMS: return "INVALID_PARAMS"; + case Argus::STATUS_INVALID_SETTINGS: return "INVALID_SETTINGS"; + case Argus::STATUS_UNAVAILABLE: return "UNAVAILABLE"; + case Argus::STATUS_OUT_OF_MEMORY: return "OUT_OF_MEMORY"; + case Argus::STATUS_UNIMPLEMENTED: return "UNIMPLEMENTED"; + case Argus::STATUS_TIMEOUT: return "TIMEOUT"; + case Argus::STATUS_CANCELLED: return "CANCELLED"; + case Argus::STATUS_DISCONNECTED: return "DISCONNECTED"; + case Argus::STATUS_END_OF_STREAM: return "END_OF_STREAM"; + default: return "BAD STATUS"; + } +} + +bool StreamConsumer::threadInitialize(GstNvArgusCameraSrc *src) +{ + // Create the FrameConsumer. + m_consumer = UniqueObj(FrameConsumer::create(m_stream)); + if (!m_consumer) + ORIGINATE_ERROR("Failed to create FrameConsumer"); + + return true; +} + +bool StreamConsumer::threadExecute(GstNvArgusCameraSrc *src) +{ + IEGLOutputStream *iStream = interface_cast(m_stream); + Size2D streamSize (src->width, src->height); + IFrameConsumer *iFrameConsumer = interface_cast(m_consumer); + + // Wait until the producer has connected to the stream. + CONSUMER_PRINT("Waiting until producer is connected...\n"); + if (iStream->waitUntilConnected() != STATUS_OK) + { + src->argus_in_error = TRUE; + ORIGINATE_ERROR("Stream failed to connect."); + } + CONSUMER_PRINT("Producer has connected; continuing.\n"); + IAutoControlSettings* l_iAutoControlSettings_ptr = (IAutoControlSettings *)src->iAutoControlSettings_ptr; + ICaptureSession* l_iCaptureSession = (ICaptureSession *)src->iCaptureSession_ptr; + IDenoiseSettings* l_iDenoiseSettings_ptr = (IDenoiseSettings *)src->iDenoiseSettings_ptr; + IEdgeEnhanceSettings* l_iEeSettings_ptr = (IEdgeEnhanceSettings *)src->iEeSettings_ptr; + ISourceSettings* l_iRequestSourceSettings_ptr = (ISourceSettings *)src->iRequestSourceSettings_ptr; + Request* l_captureRequest = (Request*)src->request_ptr; + IEventProvider *iEventProvider_ptr = (IEventProvider*)src->iEventProvider_ptr; + IEventQueue *iEventQueue_ptr = (IEventQueue*)src->iEventQueue_ptr; + Range sensorModeAnalogGainRange; + Range ispDigitalGainRange; + Range limitExposureTimeRange; + l_iCaptureSession->repeat(l_captureRequest); + + src->frameInfo = g_slice_new(NvArgusFrameInfo); + src->frameInfo->fd = -1; + src->captureIdMap.clear(); + GError *error = NULL; + + while (true) + { + Argus::Status frame_status; + Argus::EventType frame_event; + Event* event = NULL; + IEvent* iEvent = NULL; + static GQuark domain = g_quark_from_static_string ("NvArgusCameraSrc"); + + g_mutex_lock(&src->queue_lock); + if (src->queue.get() == NULL) + { + g_mutex_unlock(&src->queue_lock); + break; + } + + iEventProvider_ptr->waitForEvents(src->queue.get(), src->event_timeout); + g_mutex_unlock(&src->queue_lock); + + if (iEventQueue_ptr->getSize() == 0) + { + g_mutex_lock (&src->argus_buffers_queue_lock); + src->stop_requested = TRUE; + g_mutex_unlock (&src->argus_buffers_queue_lock); + break; + } + + event = (Event* )iEventQueue_ptr->getEvent(iEventQueue_ptr->getSize() - 1); + iEvent = (IEvent*)interface_cast(event); + + if (!iEvent) + { + src->argus_in_error = TRUE; + ORIGINATE_ERROR("Failed to get IEvent interface"); + } + + // Retrieved event types + frame_event = iEvent->getEventType(); + + if (frame_event == EVENT_TYPE_ERROR) + { + if (src->stop_requested == TRUE || src->timeout_complete == TRUE) + break; + + src->argus_in_error = TRUE; + const IEventError* iEventError = interface_cast(event); + Argus::Status argusStatus = iEventError->getStatus(); + error = g_error_new_literal (domain, argusStatus, getStatusString(argusStatus)); + GstMessage *message = gst_message_new_error (GST_OBJECT(src), error, "Argus Error Status"); + gst_element_post_message (GST_ELEMENT_CAST(src), message); + g_mutex_lock (&src->argus_buffers_queue_lock); + src->stop_requested = TRUE; + g_mutex_unlock (&src->argus_buffers_queue_lock); + break; + } + else if (frame_event == EVENT_TYPE_CAPTURE_STARTED) + { + if (src->show_latency) { + guint64 capture_id = iEvent->getCaptureId(); + guint64 time = iEvent->getTime() / 1000; + src->captureIdMap.insert(std::pair(capture_id, time)); + } + else { + continue; + } + } + else if (frame_event == EVENT_TYPE_CAPTURE_COMPLETE) + { + UniqueObj frame(iFrameConsumer->acquireFrame(src->acquire_timeout, &frame_status)); + + if (src->stop_requested == TRUE || src->timeout_complete == TRUE) + { + break; + } + + if (frame_status != STATUS_OK) + { + src->argus_in_error = TRUE; + error = g_error_new_literal (domain, frame_status, getStatusString(frame_status)); + GstMessage *message = gst_message_new_error (GST_OBJECT(src), error, "Argus Error Status"); + gst_element_post_message (GST_ELEMENT_CAST(src), message); + g_mutex_lock (&src->argus_buffers_queue_lock); + src->stop_requested = TRUE; + g_mutex_unlock (&src->argus_buffers_queue_lock); + break; + } + if (!frame) + { + g_mutex_lock (&src->argus_buffers_queue_lock); + src->stop_requested = TRUE; + g_mutex_unlock (&src->argus_buffers_queue_lock); + break; + } + + if (src->wbPropSet) + { + switch (src->controls.wbmode) + { + case NvArgusCamAwbMode_Off: + l_iAutoControlSettings_ptr->setAwbMode(AWB_MODE_OFF); + break; + case NvArgusCamAwbMode_Auto: + l_iAutoControlSettings_ptr->setAwbMode(AWB_MODE_AUTO); + break; + case NvArgusCamAwbMode_Incandescent: + l_iAutoControlSettings_ptr->setAwbMode(AWB_MODE_INCANDESCENT); + break; + case NvArgusCamAwbMode_Fluorescent: + l_iAutoControlSettings_ptr->setAwbMode(AWB_MODE_FLUORESCENT); + break; + case NvArgusCamAwbMode_WarmFluorescent: + l_iAutoControlSettings_ptr->setAwbMode(AWB_MODE_WARM_FLUORESCENT); + break; + case NvArgusCamAwbMode_Daylight: + l_iAutoControlSettings_ptr->setAwbMode(AWB_MODE_DAYLIGHT); + break; + case NvArgusCamAwbMode_CloudyDaylight: + l_iAutoControlSettings_ptr->setAwbMode(AWB_MODE_CLOUDY_DAYLIGHT); + break; + case NvArgusCamAwbMode_Twilight: + l_iAutoControlSettings_ptr->setAwbMode(AWB_MODE_TWILIGHT); + break; + case NvArgusCamAwbMode_Shade: + l_iAutoControlSettings_ptr->setAwbMode(AWB_MODE_SHADE); + break; + case NvArgusCamAwbMode_Manual: + l_iAutoControlSettings_ptr->setAwbMode(AWB_MODE_MANUAL); + break; + default : + l_iAutoControlSettings_ptr->setAwbMode(AWB_MODE_AUTO); + break; + } + src->wbPropSet = FALSE; + l_iCaptureSession->repeat(l_captureRequest); + } + + if (src->saturationPropSet) + { + l_iAutoControlSettings_ptr->setColorSaturationEnable(TRUE); + l_iAutoControlSettings_ptr->setColorSaturation(src->controls.saturation); + l_iCaptureSession->repeat(l_captureRequest); + src->saturationPropSet = FALSE; + } + + if (src->exposureCompensationPropSet) + { + l_iAutoControlSettings_ptr->setExposureCompensation(src->controls.ExposureCompensation); + l_iCaptureSession->repeat(l_captureRequest); + src->exposureCompensationPropSet = FALSE; + } + + if(src->aeLockPropSet) + { + if(src->controls.AeLock) + l_iAutoControlSettings_ptr->setAeLock(true); + else + l_iAutoControlSettings_ptr->setAeLock(false); + l_iCaptureSession->repeat(l_captureRequest); + src->aeLockPropSet = FALSE; + } + + if(src->awbLockPropSet) + { + if(src->controls.AwbLock) + l_iAutoControlSettings_ptr->setAwbLock(true); + else + l_iAutoControlSettings_ptr->setAwbLock(false); + l_iCaptureSession->repeat(l_captureRequest); + src->awbLockPropSet = FALSE; + } + + if(src->tnrModePropSet) + { + switch (src->controls.NoiseReductionMode) + { + case NvArgusCamNoiseReductionMode_Off: + l_iDenoiseSettings_ptr->setDenoiseMode(DENOISE_MODE_OFF); + break; + case NvArgusCamNoiseReductionMode_Fast: + l_iDenoiseSettings_ptr->setDenoiseMode(DENOISE_MODE_FAST); + break; + case NvArgusCamNoiseReductionMode_HighQuality: + l_iDenoiseSettings_ptr->setDenoiseMode(DENOISE_MODE_HIGH_QUALITY); + break; + default : + l_iDenoiseSettings_ptr->setDenoiseMode(DENOISE_MODE_OFF); + break; + } + l_iCaptureSession->repeat(l_captureRequest); + src->tnrModePropSet = FALSE; + } + + if(src->tnrStrengthPropSet) + { + l_iDenoiseSettings_ptr->setDenoiseStrength(src->controls.NoiseReductionStrength); + l_iCaptureSession->repeat(l_captureRequest); + src->tnrStrengthPropSet = FALSE; + } + + if(src->edgeEnhancementModePropSet) + { + switch (src->controls.EdgeEnhancementMode) + { + case NvArgusCamEdgeEnhancementMode_Off: + l_iEeSettings_ptr->setEdgeEnhanceMode(EDGE_ENHANCE_MODE_OFF); + break; + case NvArgusCamEdgeEnhancementMode_Fast: + l_iEeSettings_ptr->setEdgeEnhanceMode(EDGE_ENHANCE_MODE_FAST); + break; + case NvArgusCamEdgeEnhancementMode_HighQuality: + l_iEeSettings_ptr->setEdgeEnhanceMode(EDGE_ENHANCE_MODE_HIGH_QUALITY); + break; + default : + l_iEeSettings_ptr->setEdgeEnhanceMode(EDGE_ENHANCE_MODE_OFF); + break; + } + l_iCaptureSession->repeat(l_captureRequest); + src->edgeEnhancementModePropSet = FALSE; + } + + if(src->edgeEnhancementStrengthPropSet) + { + l_iEeSettings_ptr->setEdgeEnhanceStrength(src->controls.EdgeEnhancementStrength); + l_iCaptureSession->repeat(l_captureRequest); + src->edgeEnhancementStrengthPropSet = FALSE; + } + + if(src->aeAntibandingPropSet) + { + switch (src->controls.AeAntibandingMode) + { + case NvArgusCamAeAntibandingMode_Off: + l_iAutoControlSettings_ptr->setAeAntibandingMode(AE_ANTIBANDING_MODE_OFF); + break; + case NvArgusCamAeAntibandingMode_Auto: + l_iAutoControlSettings_ptr->setAeAntibandingMode(AE_ANTIBANDING_MODE_AUTO); + break; + case NvArgusCamAeAntibandingMode_50HZ: + l_iAutoControlSettings_ptr->setAeAntibandingMode(AE_ANTIBANDING_MODE_50HZ); + break; + case NvArgusCamAeAntibandingMode_60HZ: + l_iAutoControlSettings_ptr->setAeAntibandingMode(AE_ANTIBANDING_MODE_60HZ); + break; + default : + l_iAutoControlSettings_ptr->setAeAntibandingMode(AE_ANTIBANDING_MODE_OFF); + break; + } + l_iCaptureSession->repeat(l_captureRequest); + src->aeAntibandingPropSet = FALSE; + } + + if(src->gainRangePropSet == TRUE) + { + if (src->controls.gainRange.low < sensorModeAnalogGainRange.min()) + { + GST_ARGUS_PRINT("Invalid min gain value, using default minimum gain: %f instead.\n", + sensorModeAnalogGainRange.min()); + src->controls.gainRange.low = sensorModeAnalogGainRange.min(); + } + if (src->controls.gainRange.high > sensorModeAnalogGainRange.max()) + { + GST_ARGUS_PRINT("Invalid max gain value, using default maximum gain: %f instead.\n", + sensorModeAnalogGainRange.max()); + src->controls.gainRange.high = sensorModeAnalogGainRange.max(); + } + + sensorModeAnalogGainRange.min() = src->controls.gainRange.low; + sensorModeAnalogGainRange.max() = src->controls.gainRange.high; + l_iRequestSourceSettings_ptr->setGainRange(sensorModeAnalogGainRange); + l_iCaptureSession->repeat(l_captureRequest); + src->gainRangePropSet = FALSE; + } + + if(src->ispDigitalGainRangePropSet == TRUE) + { + ispDigitalGainRange.min() = src->controls.ispDigitalGainRange.low; + ispDigitalGainRange.max() = src->controls.ispDigitalGainRange.high; + l_iAutoControlSettings_ptr->setIspDigitalGainRange(ispDigitalGainRange); + l_iCaptureSession->repeat(l_captureRequest); + src->ispDigitalGainRangePropSet = FALSE; + } + + if(src->exposureTimePropSet == TRUE) + { + if (src->controls.exposureTimeRange.low < limitExposureTimeRange.min()) + { + GST_ARGUS_PRINT("Invalid min exp value, using default minimum exp: %ju instead.\n", + limitExposureTimeRange.min()); + src->controls.exposureTimeRange.low = limitExposureTimeRange.min(); + } + if (src->controls.exposureTimeRange.high > limitExposureTimeRange.max()) + { + GST_ARGUS_PRINT("Invalid max exp value, using default maximum exp: %ju instead.\n", + limitExposureTimeRange.max()); + src->controls.exposureTimeRange.high = limitExposureTimeRange.max(); + } + + limitExposureTimeRange.min() = src->controls.exposureTimeRange.low; + limitExposureTimeRange.max() = src->controls.exposureTimeRange.high; + l_iRequestSourceSettings_ptr->setExposureTimeRange(limitExposureTimeRange); + l_iCaptureSession->repeat(l_captureRequest); + src->exposureTimePropSet = FALSE; + } + + if(src->aeRegionPropSet == TRUE) + { + std::vector < AcRegion > AeRegion; + AcRegion ae(src->controls.AeRegion.left(), src->controls.AeRegion.top(), + src->controls.AeRegion.right(), src->controls.AeRegion.bottom(), + src->controls.AeRegion.weight()); + AeRegion.push_back(ae); + GST_ARGUS_PRINT("Setting AeRegion on the fly: %d %d %d %d %f \n", + AeRegion[0].left(), AeRegion[0].top(), AeRegion[0].right(), + AeRegion[0].bottom(), AeRegion[0].weight()); + l_iAutoControlSettings_ptr->setAeRegions(AeRegion); + l_iCaptureSession->repeat(l_captureRequest); + src->aeRegionPropSet = FALSE; + } + + // Use the IFrame interface to print out the frame number/timestamp, and + // to provide access to the Image in the Frame. + IFrame *iFrame = interface_cast