I am trying to build the following pipeline in c++:
gst-launch-1.0 \
v4l2src device=/dev/video0 ! \
jpegdec ! videoconvert ! tee name=t \
t. ! queue ! videocrop top=0 left=0 right=0 bottom=200 ! \
videoscale ! video/x-raw,width=1280,height=720 ! autovideosink \
t. ! queue ! autovideosink
I managed to get both of my videosink to display without error the video stream.
However when I try to implement this as code in an application, I get an error for the queue that contains the cropping and scaling. I get the following error message :
gst_video_frame_copy: assertion 'dinfo->width == sinfo->width && dinfo->height == sinfo->height' failed
And the autovideosink display a green screen.
This is the code I use for the videoscale/videocrop part:
bool StreamThread::create_transformed_queue() {
std::lock_guard<std::mutex> lock(pipeline_mutex);
GstElement *sink = gst_bin_get_by_name(GST_BIN(pipeline), "sink");
GstPadTemplate *templ =
gst_element_class_get_pad_template(GST_ELEMENT_GET_CLASS(sink), "src_%u");
if (!templ) {
g_printerr("Pad template not found.\n");
return FALSE;
}
GstPad *sinkpad = gst_element_request_pad(sink, templ, NULL, NULL);
if (!sinkpad) {
g_printerr("Failed to request pad.\n");
return FALSE;
}
// Create the bin to encapsulate the elements
bin_transform = gst_bin_new("transformation_bin");
// Create the elements for queue, scaling, cropping, and caps filtering
queue_transform = gst_element_factory_make("queue", "transform_queue");
videoscale = gst_element_factory_make("videoscale", "transform_videoscale");
videocrop = gst_element_factory_make("videocrop", "transform_videocrop");
capsfilter_transform =
gst_element_factory_make("capsfilter", "capsfilter_transform");
autovideo_transform =
gst_element_factory_make("autovideosink", "autovideo_transform");
if (!queue_transform || !videoscale || !videocrop || !capsfilter_transform ||
!autovideo_transform) {
g_printerr("Not all elements could be created.\n");
return false;
}
// Add the queue as the first element of the bin
gst_bin_add_many(GST_BIN(pipeline), queue_transform, videoscale,
capsfilter_transform, videocrop, autovideo_transform, NULL);
// set the caps for videoscale
GstCaps *caps =
gst_caps_new_simple("video/x-raw", "width", G_TYPE_INT, videoSource.width,
"height", G_TYPE_INT, videoSource.height, "format", G_TYPE_STRING, "I420", NULL);
g_object_set(capsfilter_transform, "caps", caps, NULL);
gst_caps_unref(caps);
// Set crop properties
g_object_set(videocrop, "left", videoSource.crop[0][0], "right",
videoSource.crop[0][1], "top", videoSource.crop[1][0], "bottom",
videoSource.crop[1][1], NULL);
if (gst_element_link_many(queue_transform, videoscale, capsfilter_transform,
autovideo_transform, videocrop, NULL) != TRUE) {
g_printerr("Elements could not be linked.\n");
gst_object_unref(pipeline);
return FALSE;
}
gst_element_sync_state_with_parent(queue_transform);
gst_element_sync_state_with_parent(videoscale);
gst_element_sync_state_with_parent(capsfilter_transform);
gst_element_sync_state_with_parent(videocrop);
gst_element_sync_state_with_parent(autovideo_transform);
GstPad *srcpad = gst_element_get_static_pad(queue_transform, "sink");
if (!srcpad) {
g_printerr("Failed to get static pad from queue.\n");
return FALSE;
}
if (gst_pad_link(sinkpad, srcpad) != GST_PAD_LINK_OK) {
g_printerr("Failed to link pads\n");
gst_object_unref(srcpad);
return FALSE;
}
gst_object_unref(srcpad);
return true;
}
A normal autovideosink without cropping/scaling works well. Also my videocrop/videoscale works well if I build the pipeline with an rtsp stream. It seems the cause stems from videocrop.
Note the dataflow function only connects a fakesink to get the data flowing to a real sink. I didn’t find a better way to get my tee up and running…