Hi @dusty_nv,
Thanks for the suggestions and relevant links. I was able to write a simple pipeline in C and have provided my code below.
#include <stdio.h>
#include <string.h>
#include <fstream>
#include <unistd.h>
#include <stdlib.h>
#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
typedef struct {
GstPipeline* pipeline;
// GstElement* src;
GstAppSrc* src;
GstElement* filter;
GstElement* encoder;
GstElement* sink;
GstClockTime timestamp;
guint sourceid;
} gst_app_t;
static gst_app_t gst_app;
int main() {
gst_app_t* app = &gst_app;
GstStateChangeReturn state_ret;
gst_init(NULL, NULL); //Initialize Gstreamer
app->timestamp = 0; //Set timestamp to 0
//Create pipeline, and pipeline elements
app->pipeline = (GstPipeline*)gst_pipeline_new("mypipeline");
app->src = (GstAppSrc*) gst_element_factory_make("appsrc", "mysrc");
app->filter = gst_element_factory_make ("capsfilter", "myfilter");
app->encoder = gst_element_factory_make ("nvjpegenc", "myjpeg");
app->sink = gst_element_factory_make ("filesink" , NULL);
if (!app->pipeline ||
!app->src || !app->filter ||
!app->encoder ||
!app->sink) {
printf("Error creating pipeline elements!\n");
return -1;
}
//Attach elements to pipeline
gst_bin_add_many(
GST_BIN(app->pipeline),
(GstElement*) app->src,
app->filter,
app->encoder,
app->sink,
NULL);
//Set pipeline element attributes
// g_object_set (app->src, "num-buffers", 1, NULL);
GstCaps* filtercaps = gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, "I420",
"width", G_TYPE_INT, 640,
"height", G_TYPE_INT, 360,
"framerate", GST_TYPE_FRACTION, 1, 1,
NULL);
g_object_set (G_OBJECT (app->filter), "caps", filtercaps, NULL);
g_object_set (G_OBJECT (app->sink), "location", "output.jpg", NULL);
//Link elements together
g_assert( gst_element_link_many(
(GstElement*) app->src,
app->filter,
app->encoder,
app->sink,
NULL ) );
//Play the pipeline
state_ret = gst_element_set_state((GstElement*)app->pipeline, GST_STATE_PLAYING);
g_assert(state_ret != GST_STATE_CHANGE_FAILURE);
// get pointer to input file
FILE* fp = fopen("test.yuv", "rb");
g_assert(fp != NULL);
// memory allocation and error check
size_t fsize = 640*360*1.5;
char* filebuf = (char*)malloc(fsize);
if (filebuf == NULL) {
printf("memory error\n");
return -1;
}
// read to buffer
size_t bytesread = fread(filebuf, 1, fsize, fp);
// Actual databuffer
GstBuffer *pushbuffer;
GstFlowReturn ret;
// Wrap the data
pushbuffer = gst_buffer_new_wrapped(filebuf, fsize);
ret = gst_app_src_push_buffer( app->src, pushbuffer); //Push data into pipeline
g_assert(ret == GST_FLOW_OK);
GstBus* bus = gst_element_get_bus((GstElement*) app->pipeline);
GstMessage* msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, (GstMessageType)(GST_MESSAGE_ERROR | GST_MESSAGE_EOS));
/* Parse message */
if (msg != NULL) {
GError *err;
gchar *debug_info;
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_ERROR:
gst_message_parse_error (msg, &err, &debug_info);
g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);
g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
g_clear_error (&err);
g_free (debug_info);
break;
case GST_MESSAGE_EOS:
g_print ("End-Of-Stream reached.\n");
break;
default:
/* We should not reach here because we only asked for ERRORs and EOS */
g_printerr ("Unexpected message received.\n");
break;
}
gst_message_unref (msg);
}
// declare EOS
gst_app_src_end_of_stream (GST_APP_SRC (app->src));
// free resources
gst_object_unref(bus);
gst_element_set_state((GstElement*)app->pipeline, GST_STATE_NULL);
gst_object_unref(app->pipeline);
return 0;
}
I generated the test.yuv file by using the following command.
gst-launch-1.0 videotestsrc num-buffers=1 ! 'video/x-raw, width=(int)640, height=(int)480, format=(string)I420, framerate=(fraction)1/1' ! filesink location=test.yuv -e
The code successfully writes the output to disk but it never ends unless I press ^c. (Maybe I am missing some checks/conditions?)
Moreover, as I had mentioned in my question, I want to utilize this in my detectnet script. So perhaps, I can add a class to replicate the same functionality and pass imgCPU/imgCUDA instead of ‘filebuf’ in the code above? (from https://github.com/dusty-nv/jetson-inference/blob/8ed492bfdc9e1b98f7711cd5ae224ce588635656/detectnet-camera/detectnet-camera.cpp#L178.)
In my gstreamer rtsp pipeline for detectnet, I am using NV12 format and I notice that nvjpegenc does not support ‘NV12’ if the data is not on (memory:NVMM). Is there any alternative that you would suggest?
I hope I am able to explain myself clearly. Looking forward to the suggestions.
Many thanks!