【问题标题】:mux klv data with h264 by mpegtsmuxmpegtsmux 使用 h264 复用 klv 数据
【发布时间】:2017-04-20 21:27:50
【问题描述】:

我需要将 klv 元数据复用到 h264 流中。我已经创建了应用程序。但是只有在插入 klv-data 时才会播放流。当我停止推送 klv-data 时,整个流停止。 mpegtsmux 复用异步 klv 数据的正确方法是什么?

Klv-data 需要插入以下工作管道:

v4l2src input-src=Camera ! videorate drop-only=true  ! 'video/x-raw, format=(string)NV12, width=1920, height=1088, framerate=25/1' ! ce_h264enc  target-bitrate=6000000 idrinterval=25 intraframe-interval=60 ! queue ! mpegtsmux  alignment=7 ! udpsink host=192.168.0.1 port=3000 -v

此管道收集在应用程序中。插入 klv-metedata 应用程序rc被创建:

appSrc = gst_element_factory_make("appsrc", nullptr);
gst_app_src_set_caps (GST_APP_SRC (appSrc), gst_caps_new_simple("meta/x-klv", "parsed", G_TYPE_BOOLEAN, TRUE, "sparse", G_TYPE_BOOLEAN, TRUE, nullptr));
g_object_set(appSrc, "format", GST_FORMAT_TIME, nullptr);

然后appsrc链接到管道:

gst_bin_add(GST_BIN(pipeline), appSrc);
gst_element_link(appSrc, mpegtsmux);

这里是推送功能:

void AppSrc::pushData(const std::string &data)
{
GstBuffer *buffer = gst_buffer_new_allocate(nullptr, data.size(), nullptr);
GstMapInfo map;
GstClock *clock;
GstClockTime abs_time, base_time;

gst_buffer_map (buffer, &map, GST_MAP_WRITE);
memcpy(map.data, data.data(), data.size());
gst_buffer_unmap (buffer, &map);

GST_OBJECT_LOCK (element);
clock = GST_ELEMENT_CLOCK (element);
base_time = GST_ELEMENT (element)->base_time;
gst_object_ref (clock);
GST_OBJECT_UNLOCK (element);
abs_time = gst_clock_get_time (clock);
gst_object_unref (clock);

GST_BUFFER_PTS (buffer) = abs_time - base_time;
GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int (1, GST_SECOND, 1);

gst_app_src_push_buffer(GST_APP_SRC(element), buffer);
}

Gstreamer 版本为 1.6.1。

我的代码有什么问题?非常感谢您的帮助。

我可以推送虚拟 klv 数据包来维护视频流。但我不想污染上行流,我相信应该有更微妙的解决方案。

我发现我可以使用GST_STREAM_FLAG_SPARSE 发送事件,这应该适合字幕。但结果我根本没有输出。

GstEvent* stream_start = gst_event_new_stream_start("klv-04");
gst_event_set_stream_flags(stream_start, GST_STREAM_FLAG_SPARSE);
GstPad* pad = gst_element_get_static_pad(GST_ELEMENT(element), "src"); 
gst_pad_push_event (pad, stream_start);

在调试时,我发现在将以下补丁应用到 gstreamer 并使用 GST_STREAM_FLAG_SPARSE 后,当 appsrc 停止推送数据包时,流不会停止。

diff --git a/libs/gst/base/gstcollectpads.c b/libs/gst/base/gstcollectpads.c
index 8edfe41..14f9926 100644
--- a/libs/gst/base/gstcollectpads.c
+++ b/libs/gst/base/gstcollectpads.c
@@ -1440,7 +1440,8 @@ gst_collect_pads_recalculate_waiting (GstCollectPads * pads)
   if (!GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_WAITING)) {
     /* start waiting */
     gst_collect_pads_set_waiting (pads, data, TRUE);
-        result = TRUE;
+      if (!GST_COLLECT_PADS_STATE_IS_SET (data, GST_COLLECT_PADS_STATE_LOCKED))
+          result = TRUE;
       }
     }
   }

无论如何,接收器在最后一个 klv 数据包后 10 秒停止更新屏幕。

【问题讨论】:

  • 如何在 mpegtsmux 和 appsrc 之间设置上限?只是一个想法 - 当您没有元数据时插入空缓冲区怎么样?我认为多路复用器正在尝试同步两个传入的流..也许如果你设置一些上限,它只是元数据,它将停止同步这两个..
  • @otopolsky Caps "meta/x-klv" 设置为appsrc,因此它们应该传播到mpegtsmux,但这没有帮助。而且我还认为 mux 正在尝试同步传入的流。事实上,我认为它必须同步它们,直到它被告知不应该进行同步。那么如何通知 mpegtsmux 不要等待元流上的数据呢?
  • 你有什么运气吗?

标签: gstreamer


【解决方案1】:

这是一个有点旧的线程,但是,

不过,根据我的经验,如果appsrc 和muxer 之间没有队列,你会得到这种行为。我会改变你的:

gst_element_link(appSrc, mpegtsmux);

到这里:

gst_element_link(appSrc, appSrcQueue);
gst_element_link(appSrcQueue, mpegtsmux);

我不确定 mpegtsmux 是否具有此功能,但我们使用的多路复用器有一个名为 do-timestamping 的属性,当它设置为 TRUE 时,我们有更好的体验。

我要给出的另一个提示是使用gst-inspect 工具查看每个元素有哪些选项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-01
    • 1970-01-01
    • 2012-12-17
    • 2016-01-01
    • 2012-03-07
    • 1970-01-01
    • 2015-04-30
    相关资源
    最近更新 更多