Argus crash after enabling metadata

Hi,

We are working on a custom application that relies on Argus for capture. We need timestamps for calibration, so as close to true sensor SOF/EOF as possible. However, if we enable metadata with IEGLOutputStreamSettings::setMetadataEnable(true) , the application crashes after a few frames. This means we can’t use either of the following timestamps:

  • Argus::ICaptureMetadata::getSensorTimestamp()
  • Argus::Ext::ISensorTimestampTsc::getSensorSofTimestampTsc()
  • Argus::Ext::ISensorTimestampTsc::getSensorEofTimestampTsc()

We can use EGLStream::IFrame::getTime(), but we are looking for a timestamp closer to the SOF/EOF.

Additional setup details:

Platform: Xavier AGX JP 5.1.2, 8 cameras

Capture stack: Libargus / EGLStream

The application works very stable without metadata. With metadata enabled, we get a SIGSEGV on Argus after just a few frames.

I would appreciate any information regarding any of the following questions:

  1. Is this a known issue when enabling metadata? Is there a fix for it?
  2. Is there any alternative timestamp we could try that could fit our requirements?

Does the sensor output embedded data?

Confirm the embedded_metadata_height in device tree.

It doesn’t, embedded_metadata_height is set to 0.

setMetadataEnable(true) need sensor support EMBD.

How ever getSensorSofTimestampTsc/getSensorEofTimestampTsc don’t need setMetadataEnable(true)

Could you provide an example? If I don’t enable the metadata, both fields appear empty.

Here’s the example for your reference.

        const Ext::ISensorTimestampTsc *iSensorTimestampTsc =
                                   interface_cast<const Ext::ISensorTimestampTsc>(metadata);
        if (iSensorTimestampTsc)
        {
            frameData.sensorSofTimestampTsc = iSensorTimestampTsc->getSensorSofTimestampTsc();
            frameData.sensorEofTimestampTsc = iSensorTimestampTsc->getSensorEofTimestampTsc();
        }

I’m still getting no timestamps if metadata is disabled. For reference, these are the steps I follow prior to using the code you provided. Let me know if I’m missing something.

            EGLStream::IArgusCaptureMetadata* iArgusCaptureMetadata =
                Argus::interface_cast<EGLStream::IArgusCaptureMetadata>(frame); // iArgusCaptureMetadata is valid
            Argus::CaptureMetadata* captureMetadata =
                iArgusCaptureMetadata ? iArgusCaptureMetadata->getMetadata() : nullptr; // captureMetadata is nullptr

What’s the log for the code dump while setMetadataEnable(true)?

On the app we get all cameras report DISCONNECTED , on Argus all we get is a segfault.

argus.log (3.7 KB)

getSensorTimestamp() should able get the timestamp without setMetadataEnable(true)

I just confirm the internal test code setMetadataEnable(true) is necessary for sensor tsc timestamp.

If it’s necessary, do you have any idea what could be causing the segfault on Argus? Any way we could work around this?

Here’s a example based on the public Argus yuvJpeg sample. The only thing you add is the TSC extension header and the extra interface_cast/print; everything else stays as in the sample.

Could you check if this working for on you side.

1. Add the TSC header

In public/samples/yuvJpeg/main.cpp (or your Argus app), add:

#include <Argus/Argus.h>
#include <EGLStream/EGLStream.h>
#include <Argus/Ext/SensorTimestampTsc.h>   // <-- add this

2. Use getSensorSofTimestampTsc() in the consumer

Below is a drop-in replacement for the inner part of ConsumerThread::threadExecute() that compiles in the yuvJpeg sample (JP5/JP6/JP7 style Argus). It assumes you already have CONSUMER_PRINT, m_stream, m_consumer etc. from the sample:

bool ConsumerThread::threadExecute()
{
    IEGLOutputStream *iStream       = interface_cast<IEGLOutputStream>(m_stream);
    IFrameConsumer  *iFrameConsumer = interface_cast<IFrameConsumer>(m_consumer);
    if (!iStream || !iFrameConsumer)
        return false;

    CONSUMER_PRINT("Waiting until producer is connected...\n");
    if (iStream->waitUntilConnected() != STATUS_OK)
    {
        CONSUMER_PRINT("Failed to wait for producer connection\n");
        return false;
    }

    uint32_t frameCount = 0;

    while (!m_gotError)
    {
        // Acquire a frame from Argus
        UniqueObj<Frame> frame(iFrameConsumer->acquireFrame());
        IFrame *iFrame = interface_cast<IFrame>(frame);
        if (!iFrame)
            break;

        // Get Argus capture metadata
        EGLStream::IArgusCaptureMetadata *iArgusCaptureMetadata =
            interface_cast<EGLStream::IArgusCaptureMetadata>(frame);
        if (!iArgusCaptureMetadata)
            continue;

        CaptureMetadata *metadata = iArgusCaptureMetadata->getMetadata();
        if (!metadata)
            continue;

        IMetadata *iMetadata = interface_cast<IMetadata>(metadata);
        if (!iMetadata)
            continue;

        const uint64_t sensorTs = iMetadata->getSensorTimestamp();
        const float    sceneLux = iMetadata->getSceneLux();

        CONSUMER_PRINT("Acquired Frame: %u, time %llu\n",
                       frameCount,
                       static_cast<unsigned long long>(sensorTs));
        CONSUMER_PRINT("\tSensor Timestamp: %llu, LUX: %f\n",
                       static_cast<unsigned long long>(sensorTs),
                       sceneLux);

        // --- TSC-based SOF timestamp here ---
        const Argus::Ext::ISensorTimestampTsc *iSensorTimestampTsc =
            interface_cast<const Argus::Ext::ISensorTimestampTsc>(metadata);

        if (iSensorTimestampTsc)
        {
            const unsigned long long sofTsc =
                static_cast<unsigned long long>(
                    iSensorTimestampTsc->getSensorSofTimestampTsc());

            CONSUMER_PRINT("\tSOF timestamp (TSC): %llu\n", sofTsc);
        }
        // -------------------------------------

        // Existing yuvJpeg image handling goes here (unchanged):
        //   - get IImage, map buffers, save JPEG, etc.
        //   - ...
        //
        // Example skeleton:
        // Image  *image  = iFrame->getImage();
        // IImage *iImage = interface_cast<IImage>(image);
        // if (!iImage) continue;
        // ... (rest of original sample code) ...

        frameCount++;
    }

    return true;
}

This is exactly the pattern used internally (yuvJpeg + Argus::Ext::ISensorTimestampTsc::getSensorSofTimestampTsc()), and it builds with the standard Jetson Multimedia API/Argus sample makefiles.

Below is the result on my sensor ov5693 that doesn’t have EMBED data output from the sensor.

./argus_yuvjpeg 
Executing Argus Sample: argus_yuvjpeg
Argus Version: 0.99.3.3 (multi-process)
PRODUCER: Creating output stream
PRODUCER: Launching consumer thread
CONSUMER: Waiting until producer is connected...
PRODUCER: Starting repeat capture requests.
CONSUMER: Producer has connected; continuing.
CONSUMER: Acquired Frame: 1, time 621527709000
CONSUMER: 	Sensor Timestamp: 621455468000, LUX: 1104.662720
CONSUMER: 	SOF timestamp (TSC): 644536244000
CONSUMER: 	IImage(2D): buffer 0 (2592x1944, 2624 stride), 74 70 7d 88 74 70 74 6a 80 91 76 5e
CONSUMER: 	IImage(2D): buffer 1 (1296x972, 2624 stride), 7c 83 7e 87 7a 88 7a 7d 79 84 7a 82
CONSUMER: 	Wrote JPEG: 1.JPG