下述代码使用场景:
用于将接收到的视频数据,转发至本地端口,供其他进程使用
// 初始化 pipeline
// |--------------link---------------|--------------rtpbin----------------|-----------|
// | appsrc->h264parse->rtph264pay---|-->send_rtp_sink_0 send_rtp_src_0--|-->udpsink |
// |---------------------------------|------------------------------------|-----------|
bool init()
{
m_pipeline = gst_pipeline_new("pipeline");
if (!m_pipeline) {
g_printerr("[init], pipeline could be created.\n");
return false;
}
m_appsrc = gst_element_factory_make("appsrc", "appsrc");
if (!m_appsrc) {
g_printerr("[init], appsrc could be created.\n");
return false;
}
m_h264parse = gst_element_factory_make("h264parse", "h264parse");
if (!m_h264parse) {
g_printerr("[init], h264parse could be created.\n");
return false;
}
m_rtph264pay = gst_element_factory_make("rtph264pay", "rtph264pay");
if (!m_rtph264pay) {
g_printerr("[init], rtph264pay could be created.\n");
return false;
}
gst_bin_add_many(GST_BIN(m_pipeline), m_appsrc, m_h264parse, m_rtph264pay, nullptr);
if (gst_element_link_many(m_appsrc, m_h264parse, m_rtph264pay, nullptr) != TRUE) {
g_printerr("[init], pipeline link failed.\n");
gst_object_unref(m_pipeline);
m_pipeline = nullptr;
return false;
}
m_udpSink = gst_element_factory_make("udpsink", "udpsink");
if (!m_udpSink) {
g_printerr("[init], udpsink could be created.\n");
return false;
}
g_object_set(G_OBJECT(m_udpSink), "host", "127.0.0.1", nullptr);
g_object_set(G_OBJECT(m_udpSink), "port", 12345, nullptr);
g_object_set(G_OBJECT(m_udpSink), "sync", 0, nullptr);
gst_bin_add_many(GST_BIN(m_pipeline), m_udpSink, nullptr);
m_rtpbin = gst_element_factory_make("rtpbin", "rtpbin");
if (!m_rtpbin) {
g_printerr("[init], rtpbin could be created.\n");
return false;
}
gst_bin_add(GST_BIN(m_pipeline), m_rtpbin);
GstPad *rtpbin_sinkpad = gst_element_request_pad_simple(m_rtpbin, "send_rtp_sink_0");
GstPad *rtph264pay_srcpad = gst_element_get_static_pad(m_rtph264pay, "src");
if (gst_pad_link(rtph264pay_srcpad, rtpbin_sinkpad) != GST_PAD_LINK_OK) {
g_printerr("[init], link m_rtph264pay to m_rtpbin failed.\n");
return false;
}
gst_object_unref(rtph264pay_srcpad);
GstPad *rtpbin_srcpad = gst_element_get_static_pad(m_rtpbin, "send_rtp_src_0");
GstPad *udpSink_sinkpad = gst_element_get_static_pad(m_udpSink, "sink");
if (gst_pad_link(rtpbin_srcpad, udpSink_sinkpad) != GST_PAD_LINK_OK) {
g_printerr("[init], link m_rtpbin to m_udpSink failed.\n");
return false;
}
gst_object_unref(rtpbin_srcpad);
gst_object_unref(udpSink_sinkpad);
if (gst_element_set_state(m_pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
g_printerr("[init], failed to change the state to PLAYING.\n");
return false;
}
g_print("[init], init video player successfully.\n");
return true;
}
// push buffer to appsrc
bool pushData(void *data, int size)
{
if (!data || size <= 0) {
g_print("[pushData], parameter invalid.\n");
return false;
}
static GstClockTime timestamp = 0;
GstBuffer *buffer = gst_buffer_new_allocate(NULL, size, NULL);
GstMapInfo map;
gst_buffer_map(buffer, &map, GST_MAP_WRITE);
memcpy((guchar *)map.data, data, gst_buffer_get_size(buffer));
GST_BUFFER_PTS(buffer) = timestamp;
// 需要注意一下时间戳
GST_BUFFER_DURATION(buffer) = gst_util_uint64_scale_int(3, GST_SECOND, 1);
timestamp += GST_BUFFER_DURATION(buffer);
GstFlowReturn ret;
if (m_appsrc) {
g_signal_emit_by_name(m_appsrc, "push-buffer", buffer, &ret);
}
gst_buffer_unmap(buffer, &map);
gst_buffer_unref(buffer);
if (ret != GST_FLOW_OK) {
g_printerr("[pushData], push buffer failed.\n");
return false;
}
return true;
}