如何在动态管道中使用 splitmuxsink

发布于 2025-01-20 11:33:47 字数 3404 浏览 2 评论 0原文

在动态管道中使用 splitmuxsink 的正确方法是什么?

以前我使用filesink来记录(没有问题),但是需要将文件分段保存,所以我尝试在动态管道中使用splitmuxsink(记录中有异步时间)。这样做时,我遇到了两个问题:

  1. 当我尝试停止录制时,我使用空闲垫来阻止录制队列并启动回调函数来执行取消链接录制分支的步骤(发送 eos,在将 bin 记录为 NULL,然后将 bin 出队)。我已经设置了一个下游数据探针来通知我在尝试执行步骤 2 之前 eos 已到达 splitmuxsink 接收器..(将 elemets 设置为 null)

    但是,最终结果是我仍然有一个空的最后一个文件(o 字节)。管道似乎尚未关闭或出现问题。我做了一个解决方法,在录制停止时立即分割视频(尽管我丢失了几帧)

    如何在动态分支中停止?

  2. 当我尝试在开始录音时创建录音箱(在创建打击垫连接录音箱时利用打击垫添加的信号)。之前我已经按正常顺序创建了记录箱(不是在我创建的 glib 循环期间创建它们)。上一步工作正常,但当前步骤使 splitmuxsink 的 filesink 处于锁定状态

    我应该如何解决这个问题?是什么导致了锁定状态?

这是我的代码:

/// create record bin
static void
pad-added(GstElement * self,
               GstPad * new_pad,
               gpointer user_data)
{
    char* pad_name = gst_pad_get_name(new_pad);
    if(g_str_equal(pad_name,"src"))
    {
   
        //RECORD records;
        records.recording    = gst_bin_new("recording");
        records.queue       = gst_element_factory_make("queue","queue");
        records.enc         = gst_element_factory_make("vpuenc_h264","enc");
        records.parser       = gst_element_factory_make("h264parse","parser");
        records.sink        = gst_element_factory_make("splitmuxsink","sink");
  

        // Add it to the main pipeline
        gst_bin_add_many(GST_BIN(records.recording),
                                 records.queue,
                                 records.enc,
                                 records.parser,
                                 records.sink,NULL);

        // link up the recording elements queue
        gst_element_link_many(records.queue,
                                  records.enc,
                                  records.parser,
                                  records.sink,NULL)
    
        
        g_object_set(G_OBJECT(records.fsink),
                     //"location","video_%d.mp4",
                     "max-size-time", (guint64) 10L * GST_SECOND,
                     "async-handling", TRUE,
                     "async-finalize", TRUE,
                     NULL);

        records.queue_sink_pad = gst_element_get_static_pad (records.queue, "sink");
        records.ghost_pad = gst_ghost_pad_new ("sink", records.queue_sink_pad);
        gst_pad_set_active(records.ghost_pad, TRUE);

        gst_element_add_pad(GST_ELEMENT(records.recording),records.ghost_pad);

        g_signal_connect (records.sink, "format-location",
                         (GCallback)format_location_callback,
                         &records);
        
    }
}

gboolean cmd_loop()
{
   // other cmd not shown here

   if(RECORD)
   {
      //create tee sink pad
      // this step will trigger the pad-added function
      tee_sink_pad = gst_element_get_request_pad (tee,"src");

      // ....other function
   }
} 

int main()
{
   // add the pad-added signal response
   g_signal_connect(tee, "pad-added", G_CALLBACK(pad-added), NULL);

  // use to construct the loop (cycle every 1s)
   GSource* source = g_timeout_source_new(1000);

   // set function to watch for command 
   g_source_set_callback(source,
                          (GSourceFunc)cmd_loop,
                          NULL,
                          NULL);
}

在此处输入图像描述

What is the correct way of using splitmuxsink in a dynamic pipeline?

Previously I have used filesink to record (no problem what so ever) but there is requirement to save the file in segments so I have tried to use splitmuxsink in dynamic pipeline(there is async time in recording). In doing so I have faced two problems:

  1. When I tried to stop the recording, I use a idle pad to block the recording queue and launch a callback function to do steps to delink the recording branch (send eos, set elements in recording bin to NULL, then dequeue the bin). I have set a downstream data probe to notify me that the eos has reached the splitmuxsink sink before I tried to do step 2..(set elemets to null)

    However, the end result is that i still have an empty last file (o bytes). It seem that the pipe is not yet closed or having some problem. I did a workaround to split the video immediately when the record stop (though I lost a few frames)

    How should one stop in a dynamic branch?

  2. When I tried to create the recording bin when i start the recording(utilizing the pad-added signal when a pad is created to connect the recording bin). Previously I have created the recording bin in normal sequence (not creating them during the glib loop that I have created). The previous step work ok but the present step has the splitmuxsink's filesink in a locked state

    How should I workaround this? What causes the lock state?

Here is my code:

/// create record bin
static void
pad-added(GstElement * self,
               GstPad * new_pad,
               gpointer user_data)
{
    char* pad_name = gst_pad_get_name(new_pad);
    if(g_str_equal(pad_name,"src"))
    {
   
        //RECORD records;
        records.recording    = gst_bin_new("recording");
        records.queue       = gst_element_factory_make("queue","queue");
        records.enc         = gst_element_factory_make("vpuenc_h264","enc");
        records.parser       = gst_element_factory_make("h264parse","parser");
        records.sink        = gst_element_factory_make("splitmuxsink","sink");
  

        // Add it to the main pipeline
        gst_bin_add_many(GST_BIN(records.recording),
                                 records.queue,
                                 records.enc,
                                 records.parser,
                                 records.sink,NULL);

        // link up the recording elements queue
        gst_element_link_many(records.queue,
                                  records.enc,
                                  records.parser,
                                  records.sink,NULL)
    
        
        g_object_set(G_OBJECT(records.fsink),
                     //"location","video_%d.mp4",
                     "max-size-time", (guint64) 10L * GST_SECOND,
                     "async-handling", TRUE,
                     "async-finalize", TRUE,
                     NULL);

        records.queue_sink_pad = gst_element_get_static_pad (records.queue, "sink");
        records.ghost_pad = gst_ghost_pad_new ("sink", records.queue_sink_pad);
        gst_pad_set_active(records.ghost_pad, TRUE);

        gst_element_add_pad(GST_ELEMENT(records.recording),records.ghost_pad);

        g_signal_connect (records.sink, "format-location",
                         (GCallback)format_location_callback,
                         &records);
        
    }
}

gboolean cmd_loop()
{
   // other cmd not shown here

   if(RECORD)
   {
      //create tee sink pad
      // this step will trigger the pad-added function
      tee_sink_pad = gst_element_get_request_pad (tee,"src");

      // ....other function
   }
} 

int main()
{
   // add the pad-added signal response
   g_signal_connect(tee, "pad-added", G_CALLBACK(pad-added), NULL);

  // use to construct the loop (cycle every 1s)
   GSource* source = g_timeout_source_new(1000);

   // set function to watch for command 
   g_source_set_callback(source,
                          (GSourceFunc)cmd_loop,
                          NULL,
                          NULL);
}

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文