【问题标题】:gstreamer: Switch recording from one file to anothergstreamer:将录制从一个文件切换到另一个文件
【发布时间】:2019-12-09 14:17:15
【问题描述】:

我正在编写一个应用程序,它将传入的视频记录到一个文件中,每隔 't' 秒,保存该文件并记录到一个新文件中。 splitmuxsink 似乎确实做到了这一点,但没有达到我的目的,因为 -

  • 它不允许连续文件之间重叠。我希望一个文件的最后几秒钟也出现在下一个文件中。
  • splitmuxsink 还存在其他奇怪的问题(与普通文件接收器相比延迟巨大、不记录音频以及文件接收器、文件时间戳不正确等)

所以,我想让应用程序每隔 't' 秒触发一次基于时间的回调。在我的管道中,我有一个多路复用器,我通过它同时写入两个文件一段时间(取决于重叠),然后基于另一个计时器回调,断开旧文件接收器。

我有以下问题 -

  1. 上述方案是个好主意吗?有更好的想法吗?
  2. 如何注册定时器回调?只是操作系统系统调用还是 gstreamer 提供任何 API?
  3. 断开旧文件接收器的安全方法是什么?是不是应该先断开再发送EOS信号?我在这里有点困惑。
  4. 为新文件更改管道中的时间。 splitmuxsink 中的一个问题是文件带有管道运行时间的时间戳,但这实际上应该在每次创建新文件时重置。 (我不介意目前还没有得到答案;这应该完全是一个单独的问题。)

为了了解所涉及的时间,每个文件的持续时间可能是 5 分钟,重叠可能是 1%,3 秒。

【问题讨论】:

    标签: gstreamer


    【解决方案1】:

    我会实施以下解决方案

    1. 使用tee 元素将视频拆分为2 个动态(在运行时)创建的源(src pad),muxfilesink 作为每个src 的下游元素

    1. 根据您的逻辑动态添加/删除tee src pads 1 和 2(以及附加的元素 src->mux->filesink)。在您的情况下,您需要以标准方式为您的环境实施 2 个计时器。

    2. 正如您所说,“旧文件接收器”有一种安全的断开连接方式。在建议的解决方案中,您需要通过在要删除的tee src 垫上注册阻塞probe 来断开/删除管道的“旧” src->mux->filesink 部分。例如,安全删除 src1 及其下游元素可以这样实现

      GstElement* videoTee = gst_bin_get_by_name(GST_BIN(pipeline), "tee");
      GstPad* srcPad = gst_element_get_static_pad(videoTee, "src_1");
      gst_pad_add_probe(srcPad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, remove_video_tee_block_probe_cb, &user_data, NULL);
      gst_object_unref(srcPad);
      gst_object_unref(videoTee);
      

      然后,在remove_video_tee_block_probe_cb回调中,src pad和连接的mux和filesink可以被移除

      GstPadProbeReturn remove_video_tee_block_probe_cb(GstPad* pad, GstPadProbeInfo* info, gpointer user_data) {
          /*user_data should contain reference to pipeline*/
          StreamData* streamData = (StreamData*)user_data;
      
          GstElement* videoTee = gst_bin_get_by_name(GST_BIN(streamData->pipeline), "videoTee");
          /*video tee src pad is blocked now and it can be safely removed*/
          gst_element_release_request_pad(videoTee, pad);
      
          GstElement* mux = gst_bin_get_by_name(GST_BIN(streamData->pipeline),  "mux1");
          GstElement* fileSink =gst_bin_get_by_name(GST_BIN(streamData->pipeline), "sink1");
          /* set state of element from PLAYING to NULL */
          gst_element_set_state(mux, GST_STATE_NULL);
          gst_element_set_state(fileSink, GST_STATE_NULL);
          /* remove elements from pipeline */
          gst_bin_remove(GST_BIN(streamData->pipeline), mux);
          gst_bin_remove(GST_BIN(streamData->pipeline), fileSink);
      
          gst_object_unref(videoTee);
      
         /* remove the probe*/
         gst_pad_remove_probe(pad, GST_PAD_PROBE_INFO_ID(info));
      
         return GST_PAD_PROBE_OK;
      }
      

    此解决方案将允许您通过根据您的逻辑在计时器回调中添加/删除管道的 src->mux->filesink 部分来控制运行时文件接收器的存在。

    【讨论】:

    • 谢谢。我有几个后续问题 - 1. 看起来我错过了提到我也有音频并且应该同步录制视频+音频。执行此操作的最简单方法是在 mux 元素之后添加 tee。例如 - 视频+音频编码 -> matroskamux -> tee -> 两个文件接收器。这样做的问题是当接收到关键帧时应该发生阻塞。任何建议如何做到这一点? 2.当一个三通垫被挡住时,它不会以任何方式影响另一垫吗?
    • @RajatRao, 1. 如果存在音频,您需要在输入文件被解复用后添加一个“音频”三通(视频和音频)。如果存在音频,该解决方案看起来会稍微复杂一些,但想法将保持不变。 2.如果tee上有2个src pads,如果你挡住了一个,其他的将继续工作而不会中断。
    • 您还想通过录制队列发送 EOS 以完成文件接收器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-15
    • 2018-01-22
    • 2013-11-24
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    相关资源
    最近更新 更多