/* * Copyright (c) 2017-2018, 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 "Error.h" #include "Thread.h" #include #include #include #include #include #include #include #include #include #include using namespace Argus; using namespace EGLStream; #define DUMP_ENABLE (1) /* Constants */ static const uint32_t MAX_CAMERA_NUM = 8; static const uint32_t DEFAULT_FRAME_COUNT = 10; static const uint32_t DEFAULT_FPS = 30; static const Size2D STREAM_SIZE( 1920, 1080); /* Globals */ UniqueObj g_cameraProvider; uint32_t g_stream_num = MAX_CAMERA_NUM; uint32_t g_frame_count = DEFAULT_FRAME_COUNT; /* Debug print macros */ #define PRODUCER_PRINT(...) printf("PRODUCER: " __VA_ARGS__) #define CONSUMER_PRINT(...) printf("CONSUMER: " __VA_ARGS__) namespace ArgusSamples { /* An utility class to hold all resources of one capture session */ class CaptureHolder : public Destructable { public: explicit CaptureHolder(); virtual ~CaptureHolder(); bool initialize(CameraDevice *device); CaptureSession* getSession() const { return m_captureSession.get(); } OutputStream* getStream() const { return m_outputStream.get(); } Request* getRequest() const { return m_request.get(); } virtual void destroy() { delete this; } private: UniqueObj m_captureSession; UniqueObj m_outputStream; UniqueObj m_request; }; CaptureHolder::CaptureHolder() { } CaptureHolder::~CaptureHolder() { /* Destroy the output stream */ m_outputStream.reset(); } bool CaptureHolder::initialize(CameraDevice *device) { ICameraProvider *iCameraProvider = interface_cast(g_cameraProvider); if (!iCameraProvider) ORIGINATE_ERROR("Failed to get ICameraProvider interface"); /* Create the capture session using the first device and get the core interface */ m_captureSession.reset(iCameraProvider->createCaptureSession(device)); ICaptureSession *iCaptureSession = interface_cast(m_captureSession); IEventProvider *iEventProvider = interface_cast(m_captureSession); if (!iCaptureSession || !iEventProvider) ORIGINATE_ERROR("Failed to create CaptureSession"); /* Create the OutputStream */ UniqueObj streamSettings( iCaptureSession->createOutputStreamSettings(STREAM_TYPE_EGL)); IEGLOutputStreamSettings *iEglStreamSettings = interface_cast(streamSettings); if (!iEglStreamSettings) ORIGINATE_ERROR("Failed to create EglOutputStreamSettings"); iEglStreamSettings->setPixelFormat(PIXEL_FMT_RAW16); iEglStreamSettings->setResolution(STREAM_SIZE); m_outputStream.reset(iCaptureSession->createOutputStream(streamSettings.get())); /* Create capture request and enable the output stream */ m_request.reset(iCaptureSession->createRequest()); IRequest *iRequest = interface_cast(m_request); if (!iRequest) ORIGINATE_ERROR("Failed to create Request"); iRequest->enableOutputStream(m_outputStream.get()); ISourceSettings *iSourceSettings = interface_cast(iRequest->getSourceSettings()); if (!iSourceSettings) ORIGINATE_ERROR("Failed to get ISourceSettings interface"); iSourceSettings->setFrameDurationRange(Range(1e9/DEFAULT_FPS)); return true; } /* * Argus Consumer Thread: * This is the thread acquires buffers from each stream and composite them to * one frame. Finally it renders the composited frame through EGLRenderer. */ class ConsumerThread : public Thread { public: explicit ConsumerThread(std::vector &streams) : m_streams(streams), m_framesRemaining(g_frame_count) { } virtual ~ConsumerThread(); protected: /** @name Thread methods */ /**@{*/ virtual bool threadInitialize(); virtual bool threadExecute(); virtual bool threadShutdown(); /**@}*/ std::vector &m_streams; uint32_t m_framesRemaining; UniqueObj m_consumers[MAX_CAMERA_NUM]; }; ConsumerThread::~ConsumerThread() { } bool ConsumerThread::threadInitialize() { /* Create the FrameConsumer */ for (uint32_t i = 0; i < m_streams.size(); i++) { m_consumers[i].reset(FrameConsumer::create(m_streams[i])); } return true; } bool ConsumerThread::threadExecute() { IEGLOutputStream *iEglOutputStreams[MAX_CAMERA_NUM]; IFrameConsumer *iFrameConsumers[MAX_CAMERA_NUM]; #if DUMP_ENABLE FILE *fp[MAX_CAMERA_NUM]; for (int i=0;i < MAX_CAMERA_NUM ;i++) { if ( i == 0) fp[i] = fopen( "raw_output0.bin", "w" ); if ( i == 1) fp[i] = fopen( "raw_output1.bin", "w" ); if ( i == 2) fp[i] = fopen( "raw_output2.bin", "w" ); if ( i == 3) fp[i] = fopen( "raw_output3.bin", "w" ); if ( i == 4) fp[i] = fopen( "raw_output4.bin", "w" ); if ( i == 5) fp[i] = fopen( "raw_output5.bin", "w" ); if ( i == 6) fp[i] = fopen( "raw_output6.bin", "w" ); if ( i == 7) fp[i] = fopen( "raw_output7.bin", "w" ); } #endif for (uint32_t i = 0; i < m_streams.size(); i++) { iEglOutputStreams[i] = interface_cast(m_streams[i]); iFrameConsumers[i] = interface_cast(m_consumers[i]); if (!iFrameConsumers[i]) ORIGINATE_ERROR("Failed to get IFrameConsumer interface"); /* Wait until the producer has connected to the stream */ CONSUMER_PRINT("Waiting until producer is connected...\n"); if (iEglOutputStreams[i]->waitUntilConnected() != STATUS_OK) ORIGINATE_ERROR("Stream failed to connect."); CONSUMER_PRINT("Producer has connected; continuing.\n"); } while (m_framesRemaining--) { for (uint32_t i = 0; i < m_streams.size(); i++) { /* Acquire a frame */ UniqueObj frame(iFrameConsumers[i]->acquireFrame()); IFrame *iFrame = interface_cast