Why EGLstream API spend long time ?

Hi, could you share steps to reproduce the issue? Are you on r28.1?

Hi ClancyLian,

Have you clarified the cause? Any further progress can be shared?

Thanks

Hi DaneLLL and kayccc,
I have test these days. my code like this :

main

#include "stream.h"
#include <gst/gst.h>
#include <cuda_runtime.h>
#include "dbg.h"
#include <thread>
using namespace std;
using namespace std::chrono;

int main(int argc, char *argv[])
{   
    gst_init(&argc, &argv);

    Stream *pStream = new Stream();

    while( !pStream->ready() ) {
        std::this_thread::sleep_for(milliseconds(100));
    }

    time_point<steady_clock, nanoseconds> timerPoint(steady_clock::now());
    int delta = 1000 / 25;
    int count = 0;
    while(1) {
        timerPoint += milliseconds(delta);
        std::this_thread::sleep_until(timerPoint);

        CUeglFrame *frames = pStream->fetchFrames();
        if(frames != nullptr)
        {
            //dbgInfo("frames address is %x.\n",frames);
            dbgInfo("frames array address is %x.\n",frames->frame.pPitch[0]);
            std::this_thread::sleep_for(milliseconds(10));
            pStream->releaseFrames();
        }
        count++;
    }

    delete pStream;

    return 0;
}

and my Stream.cpp is

#include "stream.h"
#include "dbg.h"
#include "stdio.h"
#include <memory>
#include "gstreamerutils.h"

using namespace std;

Stream::Stream()
{
    videoPlaying = false;

    videoPipeline = gst_pipeline_new("video");
    if (videoPipeline == nullptr) {
        dbgError("Create video pipeline failed.\n");
        throw;
    }

    consumer = new EGLFrameConsumer(4, 0);

    if(!setPipeline()) {
        dbgError("set pipeline failed.\n");
        throw;
    }

    GstStateChangeReturn ret = gst_element_set_state(videoPipeline, GST_STATE_PLAYING);
    if (ret == GST_STATE_CHANGE_FAILURE) {
        throw;
    }
}

Stream::~Stream()
{
    gst_element_set_state(videoPipeline, GST_STATE_NULL);
    gst_object_unref(GST_OBJECT(videoPipeline));

    if( consumer != NULL ) {
        delete consumer;
    }
}

bool Stream::setPipeline()
{
    dbgError("Setting up Pipeline.\n");

    GstElement *source = gst_element_factory_make("rtspsrc", nullptr);
    if (source == nullptr) {       
        dbgError("Create source failed.\n");
        return false;
    }
    std::string strRtsp = "rtsp://192.168.22.55:9001/bs0";
    dbgInfo("strRtsp = %s.\n", strRtsp.c_str());
    g_object_set(G_OBJECT(source), "location", strRtsp.c_str(), nullptr);
    g_object_set(G_OBJECT(source), "protocols", 0x4, nullptr);
    g_object_set(G_OBJECT(source), "timeout", 10000000, nullptr);

    GstElement *dbin = gst_element_factory_make("decodebin", nullptr);
    if (dbin == nullptr) {
        dbgError("Create decodebin failed.\n");
        return false;
    }

    GstElement *convert = gst_element_factory_make("nvvidconv", nullptr);
    if (convert == nullptr) {
        dbgError("Create nvvidconv failed.\n");
        return false;
    }

    g_object_set(convert, "output-buffers", 4, nullptr);

    GstElement *sink = gst_element_factory_make("nvvideosink", nullptr);
    if (sink == nullptr) {
        dbgError("Create sink failed.\n");
        return false;
    }

    g_object_set(sink, "display", consumer->getEGLDisplay(), nullptr);
    g_object_set(sink, "stream", consumer->getEGLStream(), nullptr);
    if (consumer->isFIFOMode()) {
        g_object_set(sink, "fifo", true, nullptr);
        g_object_set(sink, "fifo-size", consumer->getFIFOLen(), nullptr);
    }

    g_signal_connect(source, "pad-added", G_CALLBACK(onSourcePadAdded), dbin);
    g_signal_connect(dbin, "pad-added", G_CALLBACK(onDbinPadAdded), convert);

    gst_bin_add_many(GST_BIN(videoPipeline), source, dbin, convert, sink, nullptr);

    std::unique_ptr<GstCaps, GStreamerObjectDeleter> capsNvvidconv(
                gst_caps_from_string("video/x-raw(memory:NVMM), format=(string){I420}"));
    if (!gst_element_link_filtered(convert, sink, capsNvvidconv.get())) {
        dbgError("Link elememt convert <-> sink failed.\n");
        gst_object_unref(videoPipeline);
        return false;
    }

    return true;

}

bool Stream::ready()
{
    if (videoPlaying) {
        return true;
    }

    GstState state, pending;
    GstStateChangeReturn ret = gst_element_get_state(videoPipeline, &state, &pending, 0);
    if (ret == GST_STATE_CHANGE_SUCCESS && state == GST_STATE_PLAYING) {
        dbgInfo("IP cameras start playing.\n");
        videoPlaying = true;
        return true;
    }

    return false;
}

CUeglFrame* Stream::fetchFrames()
{
    frame = consumer->fetch();
    return frame;
}

void Stream::releaseFrames()
{
    if (frame != nullptr) {
        consumer->release();
    }
}

The consumer is the class like the demo in nvixo/src/NVX/FrameSource/GStreamer/GStreamerEGLStreamSinkFrameSourceImpl.cpp , and here consumer = new EGLFrameConsumer(4, 0); I set Fifolength = 4 , latency = 0.

When I just linked one camera, the nvvp profile like this It spent about 1ms or less . But when I linked more than 1 camera, such as 8 camera, the main code like this:

#include "stream.h"
#include <gst/gst.h>
#include <cuda_runtime.h>
#include "dbg.h"
#include <thread>
using namespace std;
using namespace std::chrono;

#define CAMERANUM  8

int main(int argc, char *argv[])
{   
    //thread *panoThread;
    gst_init(&argc, &argv);

    vector<Stream *> streams;
    for( int i = 0; i < CAMERANUM; i++ ) {
        Stream *pStream = new Stream(i);
        streams.push_back(pStream);
    }

    while(    !streams[0]->ready() || !streams[1]->ready()
           || !streams[2]->ready() || !streams[3]->ready()
           || !streams[4]->ready() || !streams[5]->ready()
           || !streams[6]->ready() || !streams[7]->ready() ) {
        std::this_thread::sleep_for(milliseconds(100));
    }

    vector<CUeglFrame *> vframes;
    vframes.resize(8);
    time_point<steady_clock, nanoseconds> timerPoint(steady_clock::now());
    int delta = 1000 / 25;
    while(1) {
        timerPoint += milliseconds(delta);
        std::this_thread::sleep_until(timerPoint);

        for( int i = 0; i < CAMERANUM; i++ ) {
            vframes[i] = streams[i]->fetchFrames();
        }
        std::this_thread::sleep_for(milliseconds(10));
        for( int i = 0; i < CAMERANUM; i++ ) {
            if(vframes[i] != nullptr)
            {
                dbgInfo("frames[%d] address is %x.\n", i, vframes[i]->frame.pPitch[0]);
            }
            streams[i]->releaseFrames();
        }
    }

    return 0;
}

and the result as previously, some cameras would spent long time.

Thanks

8 cameras can be overloading. Please run jetson_clocks.sh and check the loading via tegrastats.