Hi,
I write a small sample from multiSensor.
- Two camera session
- Two JPEG consumer
Please modified your use-case from this sample.
I think you should duplicate all the pipeline components.
For example, iRequest.
(Sorry for the the hard-code style since it’s better for understanding.)
/*
* Copyright (c) 2016, 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 "EGLGlobal.h"
#include "GLContext.h"
#include "JPEGConsumer.h"
#include "PreviewConsumer.h"
#include "Window.h"
#include "Thread.h"
#include <Argus/Argus.h>
#include <unistd.h>
#include <stdlib.h>
#include <sstream>
#include <iomanip>
using namespace Argus;
/*
* This sample opens two independent camera sessions using 2 sensors it then uses the first sensor
* to display a preview on the screen, while taking jpeg snapshots every second from the second
* sensor. The Jpeg saving and Preview consumption happen on two consumer threads in the
* PreviewConsumerThread and JPEGConsumerThread classes, located in the util folder.
*/
namespace ArgusSamples
{
// Constants.
static const uint32_t CAPTURE_TIME = 5; // In seconds.
static const uint32_t NUMBER_SESSIONS = 2;
// Globals and derived constants.
UniqueObj<CameraProvider> g_cameraProvider;
// Debug print macros.
#define PRODUCER_PRINT(...) printf("PRODUCER: " __VA_ARGS__)
static bool execute()
{
Window &window = Window::getInstance();
// Initialize the Argus camera provider.
UniqueObj<CameraProvider> cameraProvider(CameraProvider::create());
// Get the ICameraProvider interface from the global CameraProvider.
ICameraProvider *iCameraProvider = interface_cast<ICameraProvider>(cameraProvider);
if (!iCameraProvider)
ORIGINATE_ERROR("Failed to get ICameraProvider interface");
// Get the camera devices.
std::vector<CameraDevice*> cameraDevices;
iCameraProvider->getCameraDevices(&cameraDevices);
if (cameraDevices.size() == 0)
ORIGINATE_ERROR("No cameras available");
if (cameraDevices.size() < NUMBER_SESSIONS)
{
ORIGINATE_ERROR("Insufficient number of sensors present cannot run multisensor sample");
}
// Get the second cameras properties since it is used for the storage session.
ICameraProperties *iCameraDevice = interface_cast<ICameraProperties>(cameraDevices[1]);
if (!iCameraDevice)
{
ORIGINATE_ERROR("Failed to get the camera device.");
}
std::vector<Argus::SensorMode*> sensorModes;
iCameraDevice->getSensorModes(&sensorModes);
if (!sensorModes.size())
{
ORIGINATE_ERROR("Failed to get valid sensor mode list.");
}
// Create the capture sessions, one will be for storing images and one for preview.
UniqueObj<CaptureSession> captureSessions[NUMBER_SESSIONS];
for (uint32_t i = 0; i < NUMBER_SESSIONS; i++)
{
captureSessions[i] =
UniqueObj<CaptureSession>(iCameraProvider->createCaptureSession(cameraDevices[i]));
if (!captureSessions[i])
ORIGINATE_ERROR("Failed to create CaptureSession with device %d.", i);
}
ICaptureSession *iStorageCaptureSession1 = interface_cast<ICaptureSession>(captureSessions[0]);
ICaptureSession *iStorageCaptureSession2 = interface_cast<ICaptureSession>(captureSessions[1]);
if (!iStorageCaptureSession1 || !iStorageCaptureSession2)
ORIGINATE_ERROR("Failed to get capture session interfaces");
// Use the 1st sensor mode as the size we want to store.
ISensorMode *iMode = interface_cast<ISensorMode>(sensorModes[0]);
if (!iMode)
ORIGINATE_ERROR("Failed to get the sensor mode.");
// Create streams.
PRODUCER_PRINT("Creating the storage stream.\n");
UniqueObj<OutputStreamSettings> storageSettings1(
iStorageCaptureSession1->createOutputStreamSettings());
UniqueObj<OutputStreamSettings> storageSettings2(
iStorageCaptureSession2->createOutputStreamSettings());
IOutputStreamSettings *iStorageSettings1 =
interface_cast<IOutputStreamSettings>(storageSettings1);
IOutputStreamSettings *iStorageSettings2 =
interface_cast<IOutputStreamSettings>(storageSettings2);
if (iStorageSettings1)
{
iStorageSettings1->setPixelFormat(PIXEL_FMT_YCbCr_420_888);
iStorageSettings1->setResolution(iMode->getResolution());
}
if (iStorageSettings2)
{
iStorageSettings2->setPixelFormat(PIXEL_FMT_YCbCr_420_888);
iStorageSettings2->setResolution(iMode->getResolution());
}
UniqueObj<OutputStream> storageStream1(
iStorageCaptureSession1->createOutputStream(storageSettings1.get()));
UniqueObj<OutputStream> storageStream2(
iStorageCaptureSession2->createOutputStream(storageSettings2.get()));
if (!storageStream1.get())
ORIGINATE_ERROR("Failed to create StorageStream");
if (!storageStream2.get())
ORIGINATE_ERROR("Failed to create StorageStream");
JPEGConsumerThread jpegConsumer1(storageStream1.get());
JPEGConsumerThread jpegConsumer2(storageStream2.get());
PROPAGATE_ERROR(jpegConsumer1.initialize());
PROPAGATE_ERROR(jpegConsumer2.initialize());
PROPAGATE_ERROR(jpegConsumer1.threadSetPrefix("Camera1_"));
PROPAGATE_ERROR(jpegConsumer2.threadSetPrefix("Camera2_"));
PROPAGATE_ERROR(jpegConsumer1.waitRunning());
PROPAGATE_ERROR(jpegConsumer2.waitRunning());
// Create the two requests
UniqueObj<Request> storageRequest1(iStorageCaptureSession1->createRequest());
UniqueObj<Request> storageRequest2(iStorageCaptureSession2->createRequest());
if (!storageRequest1 || !storageRequest2)
ORIGINATE_ERROR("Failed to create Request");
IRequest *iStorageRequest1 = interface_cast<IRequest>(storageRequest1);
IRequest *iStorageRequest2 = interface_cast<IRequest>(storageRequest2);
if (!iStorageRequest1 || !iStorageRequest2)
ORIGINATE_ERROR("Failed to create Request interface");
iStorageRequest1->enableOutputStream(storageStream1.get());
iStorageRequest2->enableOutputStream(storageStream2.get());
// Wait for CAPTURE_TIME seconds and do a storage capture every second.
for (uint32_t i = 0; i < CAPTURE_TIME; i++)
{
if (iStorageCaptureSession1->repeat(storageRequest1.get()) != STATUS_OK)
ORIGINATE_ERROR("Failed to start repeat capture request for jpg");
if (iStorageCaptureSession2->repeat(storageRequest2.get()) != STATUS_OK)
ORIGINATE_ERROR("Failed to start repeat capture request for jpg");
sleep(1);
}
// all done shut down
iStorageCaptureSession1->stopRepeat();
iStorageCaptureSession2->stopRepeat();
iStorageCaptureSession1->waitForIdle();
iStorageCaptureSession2->waitForIdle();
storageStream1.reset();
storageStream2.reset();
// Wait for the consumer threads to complete.
PROPAGATE_ERROR(jpegConsumer1.shutdown());
PROPAGATE_ERROR(jpegConsumer2.shutdown());
// Shut down Argus.
cameraProvider.reset();
PRODUCER_PRINT("Done -- exiting.\n");
return true;
}
}; // namespace ArgusSamples
int main(int argc, const char *argv[])
{
if (!ArgusSamples::execute())
return EXIT_FAILURE;
return EXIT_SUCCESS;
}