首页 > 解决方案 > 连接到正在比赛的发球台

问题描述

我正在使用 gstreamer 将视频从相机流式传输到 HLS 接收器,并将该视频作为 MP4 记录到文件系统中。我使用 tee 将视频分成两条路径。如果我将它们全部连接起来并将状态切换为“播放”,我编写了一些代码并让它工作。但是当我开始流式传输并尝试将 splitmuxsink 动态连接到 tee 时,我录制的视频文件无效(至少 VLC 不会播放它们)。(网络流继续正常工作)

我已经将我的代码简化为一个简单的版本(如下),我从一个 splimuxsink 开始,睡一会儿,然后添加第二个。虽然第一个 splitmuxsink 效果很好,但新的从未生成可用的视频。为了进行过渡,我将播放管道切换为暂停,添加新元素(全部处于暂停状态)并将所有内容切换为播放。

按照gstream手册,我尝试了更复杂的切换程序;添加一个探针来阻止三通的新分支等,但结果是一样的。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <gst/gst.h>
#include <assert.h>

using namespace std;

int main()
{
    // Create a pipeline to write a file
    printf("starting\n");

    gst_init(NULL, NULL);

    // Create the pipeline to host the elements
    GstElement* pipeline = gst_pipeline_new("pipeline");
    assert(pipeline != nullptr);
    
    GstElement* camera = gst_element_factory_make("v4l2src", "v4l2src");
    assert(camera != nullptr);
    g_object_set(G_OBJECT(camera),
                 "device", "/dev/video2",
                 NULL);
    
    GstElement* caps = gst_element_factory_make("capsfilter", "capsfilter");
    assert(caps != nullptr);
    g_object_set(G_OBJECT(caps),
                 "caps", gst_caps_from_string("video/x-h264,width=640,height=480,framerate=30/1"),
                 NULL);

    GstElement* tee = gst_element_factory_make("tee", "tee");
    GstElement* queue1 = gst_element_factory_make("queue", "queue1");
    GstElement* h264parse1 = gst_element_factory_make("h264parse", "h264parse1");
    GstElement* splitmux1 = gst_element_factory_make("splitmuxsink", "splitmux1");
    g_object_set(G_OBJECT(splitmux1),
                 "location", "file%03d.mp4",
                 "max-size-time", 10000000000,
                 NULL);
    assert(tee != nullptr && queue1 != nullptr && h264parse1 != nullptr && splitmux1 != nullptr);

    // Attach them all to the pipeline
    gst_bin_add_many(GST_BIN (pipeline), camera, caps, tee, queue1, h264parse1, splitmux1, NULL);

    // Link the pieces
    assert(true == gst_element_link_many(camera, caps, tee, NULL));
    GstPad* srcpad = gst_element_get_request_pad(tee, "src_%u");
    assert(srcpad != nullptr);
    GstPad* dstpad = gst_element_get_static_pad (queue1, "sink");
    assert(dstpad != nullptr);
    assert(GST_PAD_LINK_OK == gst_pad_link(srcpad, dstpad));
    assert(true == gst_element_link_many (queue1, h264parse1, splitmux1, NULL));

    assert(GST_STATE_CHANGE_ASYNC == gst_element_set_state (pipeline, GST_STATE_PLAYING));

    sleep(35);

    printf("Attach the splitmuxsink\n");
    // Now attach another sink
    GstElement* queue2 = gst_element_factory_make("queue", "queue2");
    assert(nullptr != queue2);
    GstElement* h264parse2 = gst_element_factory_make("h264parse", "h264parse2");
    assert(nullptr != h264parse2);
    GstElement* splitmux2 = gst_element_factory_make("splitmuxsink", "splitmux2");
    assert(nullptr != splitmux2);
    g_object_set(G_OBJECT(splitmux2),
                 "location", "alt%03d.mp4",
                 "max-size-time", 10000000000,
                 NULL);

    // Set all the states to paused before attaching
    assert(GST_STATE_CHANGE_ASYNC == gst_element_set_state (splitmux2, GST_STATE_PAUSED));
    assert(GST_STATE_CHANGE_SUCCESS == gst_element_set_state (h264parse2, GST_STATE_PAUSED));
    assert(GST_STATE_CHANGE_SUCCESS == gst_element_set_state (queue2, GST_STATE_PAUSED));
    assert(GST_STATE_CHANGE_NO_PREROLL == gst_element_set_state (pipeline, GST_STATE_PAUSED));

    gst_bin_add_many (GST_BIN (pipeline), queue2, h264parse2, splitmux2, NULL);
    assert(true == gst_element_link_many (queue2, h264parse2, splitmux2, NULL));
    GstPad* srcpad2 = gst_element_get_request_pad(tee, "src_%u");
    assert(nullptr != srcpad2);
    GstPad* dstpad2 = gst_element_get_static_pad (queue2, "sink");
    assert(nullptr != dstpad2);
    assert(GST_PAD_LINK_OK == gst_pad_link(srcpad2, dstpad2));

    assert(GST_STATE_CHANGE_ASYNC == gst_element_set_state (pipeline, GST_STATE_PLAYING));
    sleep(65);
    printf("all done\n");
 }

标签: linuxgstreamervideo-processing

解决方案


推荐阅读