Hey! I will grab the pipelining. I am actually pushing raw frames from my C++ application into gstreamer to send out through RTSP.
- Resolution: 640x480
- Framerate: 60fps
- Encoding: H264/H265
Our input frames into the gstreamer system are BGR images.
Here’s some raw code that we’re using to setup the pipeline:
src = gst_element_factory_make("appsrc", NULL);
g_object_set (src, "max-buffers", 60, NULL);
g_object_set(GST_OBJECT(src), "name", "source", NULL);
g_object_set(GST_OBJECT(src), "is-live", true, NULL);
g_object_set(GST_OBJECT(src), "block", true, NULL);
gst_app_src_set_caps(GST_APP_SRC(src), caps);
bgrconv = gst_element_factory_make("videoconvert", "videoconvert");
conv = gst_element_factory_make("nvvidconv", "conv");
encode = gst_element_factory_make("omxh265enc", NULL);
g_object_set(GST_OBJECT(encode), "bitrate", 102400, NULL);
//number of key frames required, lower number will cause more stutter but more correct frames
// higher number will cause more predictions, more "smearing"
g_object_set(GST_OBJECT(encode), "iframeinterval", 5, NULL);
g_object_set(GST_OBJECT(encode), "preset-level", 1, NULL);
g_object_set(GST_OBJECT(encode), "control-rate", 1, NULL);
// Qunatization range for P and I frame,
// Use string with values of Qunatization Range
// in MinQpP-MaxQpP:MinQpI-MaxQpP:MinQpB-MaxQpB order, to set the property.
g_object_set(GST_OBJECT(encode), "qp-range", "20,35:20,35:20,35", NULL);
parse = gst_element_factory_make("h265parse", NULL);
pay = gst_element_factory_make("rtph265pay", NULL);
g_object_set(GST_OBJECT(pay), "config-interval", 1, NULL);
//TODO when applying frame ids on udpsink directly
//callback fails to be called, we use identity as a workaround
identity = gst_element_factory_make("identity", NULL);
sink = gst_element_factory_make("udpsink", NULL);
g_object_set(G_OBJECT(sink), "sync", false, NULL);
g_object_set(G_OBJECT(sink), "async", false, NULL);
g_object_set(G_OBJECT(sink), "port", 1455, NULL);
g_object_set(G_OBJECT(sink), "host", "0.0.0.0", NULL);
GstElement *capsfilter0 = gst_element_factory_make("capsfilter", "capsfilter0");
GstElement *capsfilter1 = gst_element_factory_make("capsfilter", "capsfilter1");
GstElement *capsfilter2 = gst_element_factory_make("capsfilter", "capsfilter2");
std::string capsfilter_caps0_string = std::string("video/x-raw, format=(string)BGR, ")
+ std::string("width=(int)") + std::to_string(640) +
std::string(", ")
+ std::string("height=(int)") + std::to_string(480) +
std::string(", ")
+ std::string(
"framerate=(fraction)" + std::to_string(60) + "/1");
GstCaps *capsfilter_caps0 = gst_caps_from_string(capsfilter_caps0_string.c_str());
std::string capsfilter_caps1_string = std::string("video/x-raw, format=(string)BGRx, ")
+ std::string("width=(int)") + std::to_string(640) +
std::string(", ")
+ std::string("height=(int)") + std::to_string(480) +
std::string(", ")
+ std::string(
"framerate=(fraction)" + std::to_string(60) + "/1");
GstCaps *capsfilter_caps1 = gst_caps_from_string(capsfilter_caps1_string.c_str());
std::string capsfilter_caps2_string = std::string("video/x-raw(memory:NVMM), format=(string)I420, ")
+ std::string("width=(int)") + std::to_string(640) +
std::string(", ")
+ std::string("height=(int)") + std::to_string(480) +
std::string(", ")
+ std::string(
"framerate=(fraction)" + std::to_string(60) + "/1");
GstCaps *capsfilter_caps2 = gst_caps_from_string(capsfilter_caps2_string.c_str());
g_object_set(capsfilter0, "caps", capsfilter_caps0, NULL);
g_object_set(capsfilter1, "caps", capsfilter_caps1, NULL);
g_object_set(capsfilter2, "caps", capsfilter_caps2, NULL);
gst_bin_add_many(GST_BIN(app.pipeline), src, capsfilter0, bgrconv, capsfilter1, conv, capsfilter2, encode, parse, pay, identity, sink, NULL);