Stop and start sensor using argus

Hi,

I have a problem starting and stopping the camera device using argus and C++. I want to start/stop it multiple times within the scope of the program.
First of all the code I currently use to start the sensor:


  // Create the CameraProvider object
  cameraProvider  = Argus::UniqueObj<Argus::CameraProvider>(Argus::CameraProvider::create());
  iCameraProvider = Argus::interface_cast<Argus::ICameraProvider>(cameraProvider);

  if (iCameraProvider == nullptr)
  {
    LOG_ERROR(m_log, "Failed to create CameraProvider");
  }

  LOG_INFO(m_log, "Argus Version: " + iCameraProvider->getVersion());

  std::vector<Argus::CameraDevice*> cameraDevices;
  Argus::Status                     status = iCameraProvider->getCameraDevices(&cameraDevices);

  // Get the selected CameraDevice and SensorMode.
  cameraDevice = ArgusSamples::ArgusHelpers::getCameraDevice(cameraProvider.get(), cameraDeviceIndex);

  if (cameraDevice == nullptr)
  {
    LOG_ERROR(m_log, "Selected camera device is not available");
  }

  sensorMode  = ArgusSamples::ArgusHelpers::getSensorMode(cameraDevice, sensorModeIndex);
  iSensorMode = Argus::interface_cast<Argus::ISensorMode>(sensorMode);

  if (iSensorMode == nullptr)
  {
    LOG_ERROR(m_log, "Selected sensor mode not available");
  }

  // Create the capture session using the selected device.
  captureSession  = Argus::UniqueObj<Argus::CaptureSession>(iCameraProvider->createCaptureSession(cameraDevice));
  iCaptureSession = Argus::interface_cast<Argus::ICaptureSession>(captureSession);

  if (iCaptureSession == nullptr)
  {
    LOG_ERROR(m_log, "Failed to create CaptureSession");
    throw std::invalid_argument("cannot start capture session");
  }
  LOG_INFO(m_log, "Creating output stream\n");
  streamSettings =
    Argus::UniqueObj<Argus::OutputStreamSettings>(iCaptureSession->createOutputStreamSettings(Argus::STREAM_TYPE_EGL));
  iEGLStreamSettings = Argus::interface_cast<Argus::IEGLOutputStreamSettings>(streamSettings);

  if (iEGLStreamSettings == nullptr)
  {
    LOG_ERROR(m_log, "Failed to create OutputStreamSettings");
  }
  iEGLStreamSettings->setPixelFormat(Argus::PIXEL_FMT_YCbCr_420_888);
  iEGLStreamSettings->setResolution(iSensorMode->getResolution());
  iEGLStreamSettings->setMode(Argus::EGL_STREAM_MODE_MAILBOX);
  iEGLStreamSettings->setMetadataEnable(true);
  outputStream     = Argus::UniqueObj<Argus::OutputStream>(iCaptureSession->createOutputStream(streamSettings.get()));
  iEGLOutputStream = Argus::interface_cast<Argus::IEGLOutputStream>(outputStream);
  if (iEGLOutputStream == nullptr)
  {
    LOG_ERROR(m_log, "Failed to create EGLOutputStream");
  }

  // Initialize and connect CUDA as the EGLStream consumer.
  if (!ArgusSamples::initCUDA(&g_cudaContext))
  {
    LOG_ERROR(m_log, "Cuda could not be initialized");
  }

  LOG_INFO(m_log, "Connecting CUDA to OutputStream as an EGLStream consumer");
  cudaConnection    = std::make_shared<CUeglStreamConnection>();
  CUresult cuResult = cuEGLStreamConsumerConnect(cudaConnection.get(), iEGLOutputStream->getEGLStream());

  if (cuResult != CUDA_SUCCESS)
  {
    LOG_ERROR(m_log,
                    "Unable to connect CUDA to EGLStream as a consumer CUresult: "
                      + std::string(ArgusSamples::getCudaErrorString(cuResult)));
  }
  // Create capture request, set sensor mode, and enable output stream.
  request  = Argus::UniqueObj<Argus::Request>(iCaptureSession->createRequest());
  iRequest = Argus::interface_cast<Argus::IRequest>(request);
  if (iRequest == nullptr)
  {
    LOG_ERROR(m_log, "Failed to create Request");
  }
  iRequest->enableOutputStream(outputStream.get());

  autoControlSettings = Argus::interface_cast<Argus::IAutoControlSettings>(iRequest->getAutoControlSettings());
  if (autoControlSettings == nullptr)
  {
    LOG_ERROR(m_log, "Failed to create auto control settings");
  }

  // Set the sensor mode in the request.
  iSourceSettings = Argus::interface_cast<Argus::ISourceSettings>(request);
  if (iSourceSettings == nullptr)
  {
    LOG_ERROR(m_log, "Failed to get source settings request interface");
  }
  iSourceSettings->setSensorMode(sensorMode);
  iSourceSettings->setFrameDurationRange(Argus::Range<std::uint64_t>(static_cast<std::uint64_t>(1e9 / kFramerate)));
  status = iSourceSettings->setExposureTimeRange(kExposureTimeRange);
  if (status != Argus::STATUS_OK)
  {
    LOG_WARN(m_log, "Could not set exposure time!");
  }
  iSourceSettings->setGainRange(kGainRange);
  LOG_INFO(m_log, "Starting repeat capture requests.");
  status = iCaptureSession->repeat(request.get());
  if (status != Argus::STATUS_OK)
  {
    LOG_ERROR(m_log, "Failed to submit capture request status " + std::to_string(status));
  }

Stopping it is done like so:

if (iCaptureSession != nullptr)
{
iCaptureSession->stopRepeat();
Argus::Status status = iCaptureSession->waitForIdle(); // 30s

if (status != Argus::STATUS_OK)
{
  LOG_ERROR(m_log, "Failed to wait for idle");
}

LOG_INFO(m_log, "iCaptureSession finished");
}

// Disconnect the Argus producer from the stream.
/// @todo: This is a WAR for a bug in cuEGLStreamConsumerDisconnect (see bug 200239336).
if (iEGLOutputStream != nullptr)
{
LOG_INFO(m_log, "Disconnect iEGLOutputStream");
iEGLOutputStream->disconnect();
}
captureSession.reset();

// Shut down Argus.
cameraProvider.reset();

LOG_INFO(m_log, "close done\n");

However when I then call start again, I get this error:

(Argus) Error EndOfFile: Unexpected error in reading socket (in src/rpc/socket/client/ClientSocketManager.cpp, function recvThreadCore(), line 277)
(Argus) Error EndOfFile: Receive worker failure, notifying 1 waiting threads (in src/rpc/socket/client/ClientSocketManager.cpp, function recvThreadCore(), line 350)
(Argus) Error InvalidState: Argus client is exiting with 1 outstanding client threads (in src/rpc/socket/client/ClientSocketManager.cpp, function recvThreadCore(), line 366)
(Argus) Error EndOfFile: Receiving thread terminated with error (in src/rpc/socket/client/ClientSocketManager.cpp, function recvThreadWrapper(), line 379)
(Argus) Error EndOfFile: Client thread received an error from socket (in src/rpc/socket/client/ClientSocketManager.cpp, function send(), line 145)
(Argus) Error EndOfFile: (propagating from src/rpc/socket/client/SocketClientDispatch.cpp, function dispatch(), line 91)
(Argus) Error InvalidState: Receive thread is not running cannot send. (in src/rpc/socket/client/ClientSocketManager.cpp, function send(), line 96)
(Argus) Error InvalidState: (propagating from src/rpc/socket/client/SocketClientDispatch.cpp, function dispatch(), line 91)

hello PS1234,

may I know what’s the real use-case?
for example, do you expect your program always-on, but camera service restart in the background?

Hi Jerry,

yes the application should be always on but the camera can be started or stopped. For example I want to change the sensor mode (resolution) of the camera. And I did not find a way to configure that while the camera is running using libargus.

hello PS1234,

there’s sample app, argus_camera which demonstrate this.
it also contain some UI to toggle camera controls.

you may download MMAPI package, $ sudo apt install nvidia-l4t-jetson-multimedia-api
for instance, /jetson_multimedia_api/argus/apps/camera/ui/camera/

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.