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.
