Hello, I’m trying to get frames from Argus into OpenCV, so I’d like to have something that wok in the same way as OpenCV’s VideoCapture, so for that I created myself a class. In short, I run some code for the initialization, then a short time later, I try to capture frames in another function call.
Here’s my class
class ArgusCamera : public Camera
{
unsigned char *m_OutputBuffer;
int m_dmabuf;
UniqueObj<CaptureSession> captureSession;
ICaptureSession* iCaptureSession;
UniqueObj<OutputStream> outputStream;
UniqueObj<FrameConsumer> m_consumer;
IEGLOutputStream *iEglOutputStream;
IFrameConsumer *iFrameConsumer;
CUcontext g_cudaContext;
public:
ArgusCamera(CameraSettings InSettings);
~ArgusCamera();
virtual bool StartFeed() override;
virtual bool Grab(int BufferIndex) override;
virtual bool Read(int BufferIndex) override;
};
Here’s the code I use for initialization :
bool ArgusCamera::StartFeed()
{
/* Create the CameraProvider object and get the core interface */
UniqueObj<CameraProvider> cameraProvider = UniqueObj<CameraProvider>(CameraProvider::create());
ICameraProvider *iCameraProvider = interface_cast<ICameraProvider>(cameraProvider);
if (!iCameraProvider){
return false;
cerr << "Failed to create CameraProvider" << endl;
}
cout << "Camera provider created at " << cameraProvider.get() << endl;
/* Get the camera devices */
std::vector<CameraDevice*> cameraDevices;
iCameraProvider->getCameraDevices(&cameraDevices);
if (cameraDevices.size() == 0){
return false;
//ORIGINATE_ERROR("No cameras available");
}
ICameraProperties *iCameraProperties = interface_cast<ICameraProperties>(cameraDevices[0]);
if (!iCameraProperties){
return false;
//ORIGINATE_ERROR("Failed to get ICameraProperties interface");
}
cout << "Camera properties created at " << iCameraProperties << endl;
vector<SensorMode*> modes;
iCameraProperties->getAllSensorModes(&modes);
Size WantedRes(1920,1080);
int CAPTURE_FPS = 30;
SensorMode* ChosenMode = NULL;
ISensorMode* IChosenMode = NULL;
for (int i = 0; i < modes.size(); i++)
{
SensorMode* mode = modes[i];
ISensorMode *iMode = interface_cast<ISensorMode>(mode);
auto resolution = iMode->getResolution();
cout << "Mode " << i << " : " << resolution.width() << "x" << resolution.height() << endl;
if (ChosenMode == NULL || (resolution.width() == WantedRes.width && resolution.height() == WantedRes.height))
{
ChosenMode = mode;
IChosenMode = iMode;
}
}
/* Create the capture session using the first device and get the core interface */
captureSession = (UniqueObj<CaptureSession>)(iCameraProvider->createCaptureSession(cameraDevices[0]));
iCaptureSession = interface_cast<ICaptureSession>(captureSession);
if (!iCaptureSession)
{
cerr << "Failed to get ICaptureSession interface" << endl;
return false;
}
cout << "Capture session created at " << captureSession.get() << endl;
//setup stream from camera
//PRODUCER_PRINT("Creating output stream\n");
UniqueObj<OutputStreamSettings> streamSettings(iCaptureSession->createOutputStreamSettings(STREAM_TYPE_EGL));
IEGLOutputStreamSettings *iEglStreamSettings = interface_cast<IEGLOutputStreamSettings>(streamSettings);
if (!iEglStreamSettings)
{
cerr << "Failed to get IEGLOutputStreamSettings interface" << endl;
return false;
}
cout << "Stream settings created at " << streamSettings.get() << endl;
iEglStreamSettings->setPixelFormat(PIXEL_FMT_YCbCr_420_888);
iEglStreamSettings->setResolution(IChosenMode->getResolution());
//Create output stream connected to capture session
outputStream = (UniqueObj<OutputStream>)(iCaptureSession->createOutputStream(streamSettings.get()));
if (!outputStream)
{
cerr << "Failed to create the output stream" << endl;
return false;
}
iEglOutputStream = interface_cast<IEGLOutputStream>(outputStream.get());
cout << "Output Stream created at " << outputStream.get() << endl;
//Create frame consumer connected to output stream
m_consumer = UniqueObj<FrameConsumer>(FrameConsumer::create(outputStream.get()));
if (!m_consumer)
{
cerr << "Failed to create FrameConsumer" << endl;
return false;
}
cout << "Frame Consumer created at " << m_consumer.get() << endl;
iFrameConsumer = interface_cast<IFrameConsumer>(m_consumer);
// Create capture request for the capture session, set the sensor mode, and enable the output stream.
UniqueObj<Request> request(iCaptureSession->createRequest());
IRequest *iRequest = interface_cast<IRequest>(request);
if (!iRequest)
{
cerr << "Failed to create Request" << endl;
return false;
}
cout << "Request created at " << request.get() << endl;
iRequest->enableOutputStream(outputStream.get());
ISourceSettings *iSourceSettings = interface_cast<ISourceSettings>(request);
if (!iSourceSettings)
{
cerr << "Failed to get source settings request interface" <<endl;
return false;
}
iSourceSettings->setSensorMode(ChosenMode);
/* Check fps */
Argus::Range<uint64_t> sensorDuration(IChosenMode->getFrameDurationRange());
Argus::Range<uint64_t> desireDuration(1e9/CAPTURE_FPS+0.9);
if (desireDuration.min() < sensorDuration.min() ||
desireDuration.max() > sensorDuration.max()) {
cout << "Requested FPS out of range. Fall back to 30" << endl;
CAPTURE_FPS = 30;
}
/* Set the fps */
iSourceSettings->setFrameDurationRange(Argus::Range<uint64_t>(1e9/CAPTURE_FPS));
cout << "Starting repeat capture requests." << endl;
if (iCaptureSession->repeat(request.get()) != STATUS_OK) {
cerr << "Failed to start repeat capture request" << endl;
return false;
}
// Wait until the producer has connected to the stream.
cout << "Waiting until producer is connected..." <<endl;
if (iEglOutputStream->waitUntilConnected() != STATUS_OK)
{
cerr << "Stream failed to connect." << endl;
return false;
}
cout << "Producer has connected; continuing." << endl;
return true;
}
and the code I use to capture the frames :
bool ArgusCamera::Read(int BufferIdx)
{
//return false;
Argus::Status framestatus;
UniqueObj<Frame> frame(iFrameConsumer->acquireFrame(TIMEOUT_INFINITE, &framestatus));
IFrame *iFrame = interface_cast<IFrame>(frame);
if (!iFrame)
{
cerr << "Failed to acquire frame, status=" << (int)framestatus << endl;
return false;
}
NV::IImageNativeBuffer *iNativeBuffer = interface_cast<NV::IImageNativeBuffer>(iFrame->getImage());
if (!iNativeBuffer)
{
cerr << "IImageNativeBuffer not supported by Image." << endl;
return false;
}
if (m_dmabuf == -1)
{
m_dmabuf = iNativeBuffer->createNvBuffer(iEglOutputStream->getResolution(),
NvBufferColorFormat_YUV420,
NvBufferLayout_BlockLinear);
if (m_dmabuf == -1)
{
cerr << "Failed to create NvBuffer" << endl;
return false;
}
}
auto resolution = iEglOutputStream->getResolution();
UMat bufftarget(Size(resolution.width(), resolution.height()), CV_8SC3);
unsigned long size = resolution.area() * bufftarget.elemSize();
unsigned char *buffer = reinterpret_cast<unsigned char*>(bufftarget.handle(AccessFlag::ACCESS_RW));
NvBuffer2Raw(m_dmabuf, 0, resolution.width(), resolution.height(), buffer);
imshow("It Came From Argus !", bufftarget);
waitKey();
return true;
}
The problem that I have, is that while the stream gets successfully connected during the initialization, the status I get while trying to read the frames is STATUS_DISCONNECTED (=8) : see the following log
Camera provider created at 0x55c2e77e30
Camera properties created at 0x55c2fc2ed0
Mode 0 : 3264x2464
Mode 1 : 3264x1848
Mode 2 : 1920x1080
Mode 3 : 1640x1232
Mode 4 : 1280x720
Mode 5 : 1280x720
Capture session created at 0x55c31c2d90
Stream settings created at 0x55c3082570
Output Stream created at 0x55c306f760
Frame Consumer created at 0x55c31c3eb0
Request created at 0x55c31c4790
Starting repeat capture requests.
Waiting until producer is connected...
Producer has connected; continuing.
Failed to acquire frame, status=8
Failed to acquire frame, status=8
Failed to acquire frame, status=8
Failed to acquire frame, status=8
Failed to acquire frame, status=8
Failed to acquire frame, status=8
Failed to acquire frame, status=8
Failed to acquire frame, status=8
Failed to acquire frame, status=8
Failed to acquire frame, status=8
Successfully stopped capture session
I don’t know why it gets disconnected between the two function calls.
My main is basically just this :
{
ArgusCamera* CamTest = new ArgusCamera(CameraSettings());
CamTest->StartFeed();
for (int i = 0; i < 10; i++)
{
CamTest->Read(0);
}
delete CamTest;
exit(EXIT_SUCCESS);
}
There’s nothing that should cause it to disconnect…