gstreamer将多个添加/删除容器添加到同一管道

时间:2019-01-30 11:34:12

标签: c++ c gstreamer gstreamer-1.0

我是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);
    }

}

0 个答案:

没有答案