Hi Wayne,
I am attaching code below to clarify how frames are loaded into cv::Mat and later used for processing.
- I am draining data off of “sink” using a callback ( gst_app_sink_pull_sample ).
- I get segfault with my code when -
sink = gst_element_factory_make ("appsink", "sink");
and there is no segfault when
sink = gst_element_factory_make ("nvoverlaysink", "sink");
The segfault happens at imshow(), call.
Thanks,
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv/cv.h"
#include <gst/gst.h>
#include <gst/app/gstappsink.h>
#include <gst/gstelement.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
using namespace cv;
GstSample* buffer;
cv::Mat frame;
int sampleno = 0;
GstFlowReturn CaptureGstBuffer(GstAppSink *sink, gpointer user_data)
{
//prog_data* pd = (prog_data*)user_data;
GstSample* sample = gst_app_sink_pull_sample(sink);
if(sample == NULL) {
return GST_FLOW_ERROR;
}
GstBuffer* buffer = gst_sample_get_buffer(sample);
//GstMemory* memory = gst_buffer_get_all_memory(buffer);
GstMapInfo map_info;
if (!gst_buffer_map ((buffer), &map_info, GST_MAP_READ)) {
gst_buffer_unmap ((buffer), &map_info);
gst_sample_unref(sample);
return GST_FLOW_ERROR;
}
//render using map_info.data
frame = cv::Mat(1080, 1920, CV_8UC3, (char *)map_info.data, cv::Mat::AUTO_STEP);
memcpy(frame.data,map_info.data,map_info.size);
if (!frame.empty())
imshow("test-gstreamer-video",frame);
waitKey(1);
gst_buffer_unmap ((buffer), &map_info);
//gst_memory_unmap(memory, &map_info);
//gst_memory_unref(memory);
gst_sample_unref(sample);
fprintf(stderr,"Got sample no %d\n",sampleno++);
return GST_FLOW_OK;
}
int main(int argc, char *argv[]) {
GstElement *pipeline, *source, *caps, *sink, *fsink;
GstBus *bus;
GstCaps *filtercaps;
GstElement *tee, *encoder_q,*encoder_qmux, *vq1, *vq2;
GstElement *encoder;
GstElement *parser;
GstElement *mux;
GstMessage *msg;
GstBin *recorder;
GstStateChangeReturn ret;
GstPad *srcpad,*sinkpad;
/* Initialize GStreamer */
gst_init (&argc, &argv);
/* Create the elements */
source = gst_element_factory_make ("nvcamerasrc", "source");
sink = gst_element_factory_make ("nvoverlaysink", "sink");
tee = gst_element_factory_make ("tee", "videotee");
encoder_q = gst_element_factory_make ("queue", "encoderq");
encoder_qmux = gst_element_factory_make ("queue", "muxq");
vq1 = gst_element_factory_make ("queue", "q1");
vq2 = gst_element_factory_make ("queue", "q2");
encoder = gst_element_factory_make ("omxh265enc" , "h265encoder");
parser = gst_element_factory_make ("h265parse", "parser-h265");
mux = gst_element_factory_make ("matroskamux", "muxer");
fsink = gst_element_factory_make ("filesink", "destination");
recorder = GST_BIN(gst_bin_new("recording-bin"));
/* Create the empty pipeline */
pipeline = gst_pipeline_new ("test-pipeline");
if (!pipeline || !source || !sink || !tee || !encoder_q || !vq1 || !vq2|| !encoder || !parser || !mux || !fsink) {
g_printerr ("Not all elements could be created.\n");
return -1;
}
caps = gst_element_factory_make ("capsfilter", "filter");
g_assert (caps != NULL); /* should always exist */
filtercaps = gst_caps_from_string("video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, format=(string)I420, framerate=(fraction)30/1 ");
g_object_set (G_OBJECT (caps), "caps", filtercaps, NULL);
gst_caps_unref (filtercaps);
/* Modify the source's properties */
//g_object_set (source, "pattern", 0, NULL);
g_object_set (sink, "drop" , TRUE, NULL);
g_object_set (sink, "emit-signals" , TRUE, NULL);
g_object_set (sink, "max-buffers" , 1, NULL);
g_object_set (encoder, "iframeinterval" , 24, "bitrate" , 10000000, NULL);
g_object_set (mux, "name" , "mux", NULL);
g_object_set (fsink, "location", "/home/ubuntu/cameracapture2.mkv", NULL);
g_object_set (encoder_qmux, "name", "queenc", NULL);
/* connect appsink signals */
/*if(g_signal_connect(sink, "new-sample", G_CALLBACK(CaptureGstBuffer), NULL) <= 0)
{
g_printerr("Could not connect signal handler.\n");
exit(1);
}*/
GstAppSinkCallbacks* appsink_callbacks = (GstAppSinkCallbacks*)malloc(sizeof(GstAppSinkCallbacks));
appsink_callbacks->eos = NULL;
appsink_callbacks->new_preroll = NULL;
appsink_callbacks->new_sample = CaptureGstBuffer;
gst_app_sink_set_callbacks(GST_APP_SINK(sink), appsink_callbacks, (gpointer)NULL, free);
/* Build the pipeline */
gst_bin_add_many (GST_BIN (pipeline), source, caps, tee, vq1, sink , encoder_q, encoder, parser, mux, fsink, NULL);
//if (gst_element_link_many (source,caps,tee, vq1, sink, NULL) != TRUE) {
if (gst_element_link_many (source,caps,tee, NULL) != TRUE) {
g_printerr ("Elements could not be linked1.\n");
gst_object_unref (pipeline);
return -1;
}
srcpad = gst_element_get_request_pad(tee,"src_%u");
sinkpad = gst_element_get_static_pad(encoder_q,"sink");
gst_pad_link(srcpad,sinkpad);
srcpad = gst_element_get_request_pad(tee,"src_%u");
sinkpad = gst_element_get_static_pad(vq1,"sink");
gst_pad_link(srcpad,sinkpad);
gst_element_link(vq1,sink);
if (gst_element_link_many (encoder_q,encoder, parser, NULL) != TRUE) {
g_printerr ("Elements could not be linked1.\n");
gst_object_unref (pipeline);
return -1;
}
if (!gst_element_link_pads(parser, "src", mux, "video_%u")) {
g_printerr ("Elements could not be linked2.\n");
gst_object_unref (pipeline);
return -1;
}
if (gst_element_link_many (mux,fsink ,NULL) != TRUE) {
g_printerr ("Elements could not be linked3.\n");
gst_object_unref (pipeline);
return -1;
}
/* Start playing */
ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
if (ret == GST_STATE_CHANGE_FAILURE) {
g_printerr ("Unable to set the pipeline to the playing state.\n");
gst_object_unref (pipeline);
return -1;
}
/* Wait until error or EOS */
bus = gst_element_get_bus (pipeline);
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);
}
/* Free resources */
gst_object_unref (bus);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
return 0;
}