我是gstreamer的新手。我正在尝试实现一个动态流程序,用户可以在同一管道中启动/停止多个ximagesrc到udpsink(以便我们将来都可以将alsasrc与ximagesrc混合使用,以便将来录制)。
测试程序尝试模拟用户的行为,它启动一个流,关闭它,然后再次启动它,但是在第二次“启动流”中,似乎没有流进入udpsink(有一个Web浏览器接收流并显示它)。请纠正我,非常欢迎您提出任何建议,谢谢。
#include <gst/gst.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <signal.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <pthread.h>
#include <errno.h>
#include <systemd/sd-bus.h>
#include <string.h>
#include <unistd.h>
using namespace std;
GstElement *pipeline=NULL;
static int startStreamScreen(string xid, int port)
{
/*
snprintf(str, sizeof(char)*sizeof(str),
"ximagesrc xid=\"%s\" use-damage=false ! " \
"video/x-raw,framerate=30/1 ! videoscale ! videoconvert ! " \
"vaapih264enc ! video/x-h264,stream-format=byte-stream ! h264parse ! " \
"tee name=\"videotee\" ! queue ! " \
"rtph264pay ! udpsink port=%d ",
xid.c_str(), port
);
*/
char vbinName[1024]={0}, srcName[1024]={0};
GstCaps *srcCap=NULL, *vencodeCap=NULL;
GstElement *vbin=NULL;
GstElement *src=NULL, *srcFitler=NULL, *vscale=NULL, *vconvert=NULL,
*vencode=NULL, *vencodeFilter=NULL, *vparse=NULL, *vtee=NULL,
*vqueue=NULL, *rtpplay=NULL, *udpsink=NULL;
gboolean linked;
uint64_t windowId;
windowId = atoi(xid.c_str());
snprintf(vbinName, sizeof(char)*sizeof(vbinName), "winowId_%s", xid.c_str());
snprintf(srcName, sizeof(char)*sizeof(srcName), "src_%s", xid.c_str());
vbin = gst_bin_new(vbinName);
src = gst_element_factory_make("ximagesrc", srcName);
srcFitler = gst_element_factory_make("capsfilter", NULL);
vscale = gst_element_factory_make("videoscale", NULL);
vconvert = gst_element_factory_make("videoconvert", NULL);
vencode = gst_element_factory_make("vaapih264enc", NULL);
vencodeFilter = gst_element_factory_make("capsfilter", NULL);
vparse = gst_element_factory_make("h264parse", NULL);
vtee = gst_element_factory_make("tee", "videotee");
vqueue = gst_element_factory_make("queue", NULL);
rtpplay = gst_element_factory_make("rtph264pay", NULL);
udpsink = gst_element_factory_make("udpsink", NULL);
if( !vbin || !src || !srcFitler || !vscale || !vconvert || !vencode ||
!vencodeFilter || !vparse || !vtee || !vqueue || !rtpplay || !udpsink){
fprintf(stderr, "[%s:%d]create element fail\n", __FILE__, __LINE__);
return 1;
}
// set property
g_object_set(src, "xid", windowId, "use-damage", FALSE, NULL);
g_object_set(udpsink, "port", port, NULL);
// set property for capsfilter
srcCap = gst_caps_new_simple("video/x-raw",
"framerate", GST_TYPE_FRACTION, 30, 1,
NULL);
g_object_set(srcFitler, "caps", srcCap, NULL);
vencodeCap = gst_caps_new_simple("video/x-h264",
"stream-format", G_TYPE_STRING, "byte-stream",
NULL);
g_object_set(vencodeFilter, "caps", vencodeCap, NULL);
// add & link
gst_bin_add_many(GST_BIN(vbin), src, srcFitler, vscale, vconvert,
vencode, vencodeFilter, vparse, vtee, vqueue, rtpplay, udpsink, NULL);
linked = gst_element_link_many(src, srcFitler, vscale, vconvert,
vencode, vencodeFilter, vparse, vtee, vqueue, rtpplay, udpsink, NULL);
if(!linked){
fprintf(stderr, "[%s:%d]link many fail\n", __FILE__, __LINE__);
}
if( pipeline == NULL){
fprintf(stderr, "[%s:%d] pipeline is null, we create a new one\n", __FILE__, __LINE__);
pipeline = gst_pipeline_new(NULL);
}
gst_bin_add_many(GST_BIN(pipeline), vbin, NULL);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
fprintf(stderr, "[%s:%d]start stream %s...\n", __FILE__, __LINE__, vbinName);
// unref caps
gst_caps_unref(srcCap);
gst_caps_unref(vencodeCap);
return 0;
}
static GstPadProbeReturn
stopStream_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data) {
GstElement *vbin = (GstElement*) user_data;
gchar *name=gst_object_get_name(GST_OBJECT(vbin));
fprintf(stderr, "[%s:%d]stop stream name=%s...\n", __FILE__, __LINE__, name);
g_free(name);
gst_bin_remove_many(GST_BIN(pipeline), vbin, NULL);
gst_element_set_state (vbin, GST_STATE_NULL);
gst_object_unref(vbin);
return GST_PAD_PROBE_REMOVE;
}
static int stopStreamScreen(string devName)
{
char vbinName[1024] = {0}, srcName[1024]={0};
GstElement *vbin=NULL, *src=NULL;
GstPad *srcPad=NULL;
uint64_t windowId;
windowId = atoi(devName.c_str());
snprintf(vbinName, sizeof(char)*sizeof(vbinName), "winowId_%s", devName.c_str());
snprintf(srcName, sizeof(char)*sizeof(srcName), "src_%s", devName.c_str());
vbin = gst_bin_get_by_name(GST_BIN(pipeline), vbinName);
if(!vbin){
fprintf(stderr, "[%s:%d]can not get vbin %s\n", __FILE__, __LINE__, vbinName);
}
src = gst_bin_get_by_name(GST_BIN(vbin), srcName);
if(!src){
fprintf(stderr, "[%s:%d]can not get src %s\n", __FILE__, __LINE__, srcName);
}
// get pad
srcPad = gst_element_get_static_pad(src, "src");
if(!srcPad){
fprintf(stderr, "[%s:%d]srcPad is null\n", __FILE__, __LINE__);
}
gst_pad_add_probe(srcPad, GST_PAD_PROBE_TYPE_IDLE, stopStream_cb, vbin, NULL);
gst_object_unref(vbin);
gst_object_unref(srcPad);
return 0;
}
int main(int argc, char** argv)
{
gst_init(&argc, &argv);
startStreamScreen("46137349", 8000); // screen 0
sleep(5);
stopStreamScreen("46137349"); // screen 0
sleep(5);
startStreamScreen("46137349", 8000); // screen 0
while(true){
sleep(1);
}
}