GStreamer mp4mux 使用自定义 appsrc

问题描述

我有一个用 C++ 编写的管道,如下所示:

appsrc do-timestamp=TRUE is-live=TRUE caps=
“video/x-h264,stream-format=(string)byte-stream,alignment=(string)none,framerate=(fraction)0/1” min-latency=300000000 ! h264parse ! video/x-h264,stream-format=(string)avc,alignment=(string)au ! tee name=t \
t. ! queue ! valve drop=FALSE ! decodebin ! glupload ! glcolorconvert ! qtsink sync=FALSE \
t. ! queue ! valve drop=FALSE ! mp4mux reserved-max-duration=3600000000000 reserved-moov-update-period=10000000000 ! filesink sync=FALSE location=”....../out.mp4”

appsrc 将来自无人机的 USB 无线视频接收器的视频注入管道。

更多上下文:

  • USB 接收器硬件为我们提供了 512 字节的无时间戳块 原始附件 B h.264 视频
  • 帧率应该是 60 fps,但在 练习它很少跟上它,并根据 信号强度(因此帧率=(分数)0/1”,这就是 qtsink 和 filesink 都没有同步到管道的原因 (sync=FALSE))
  • 硬件引入了至少 300 毫秒的延迟, 在 appsrc 中设置
  • appsrc 自动为我的缓冲区添加时间戳 (do-timestamp=TRUE)
  • 我正在使用 mp4mux reserved-max-duration 和 reserved-moov-update-period 以防止应用程序崩溃破坏 mp4 文件
  • 我使用的是适用于 Android 的 GStreamer 1.18.4

当无人机不在空中时,视频录制工作正常。但是当它起飞时,经过大约 15 秒的正确视频录制后,mp4mux 元素失败并显示消息“Buffer has no PTS”。不幸的是,这一直被一些用户报告,但我无法重现它(因为它需要驾驶我没有的无人机),这没有多大意义。到目前为止,我的猜测是,在那个特定时刻,无线视频链路中可能存在一些拥塞,并且一些视频数据包可能会延迟几毫秒,这可能会造成一些麻烦。

这是创建 appsrc 的(简化)代码

   _pAppSrc = gst_element_factory_make("appsrc","artosyn_source");
    gpointer pAppSrc = static_cast<gpointer>(_pAppSrc);

    // Retain one more ref,so the source is destroyed
    // in a controlled way
    gst_object_ref(_pAppSrc);

    pCaps = gst_caps_from_string("video/x-h264,alignment=none,framerate=(fraction)0/1"));
    g_object_set(G_OBJECT(pAppSrc),"caps",pCaps,"is-live",TRUE,"min-latency",G_GINT64_CONSTANT(300000000),"format",GST_FORMAT_TIME,"do-timestamp",nullptr);

   _pBufferPool = gst_buffer_pool_new();

   pConfig = gst_buffer_pool_get_config (_pBufferPool);

   static const guint kBufferSize  = 512;
   static const guint kPoolSize    = 0x400000;
   static const guint kPoolSizeMax = 0x600000;

    qsizetype nBuffersMin = kPoolSize / kBufferSize;
    qsizetype nBuffersMax = kPoolSizeMax / kBufferSize;

    gst_buffer_pool_config_set_params(pConfig,kBufferSize,nBuffersMin,nBuffersMax);

   gst_buffer_pool_set_config(_pBufferPool,pConfig);
   gst_buffer_pool_set_active(_pBufferPool,TRUE);

   gst_caps_unref(GST_CAPS(pCaps));

一个新的缓冲区被 USB 驱动程序填满时,它会像这样被推入管道:

bool unref = false;

gst_buffer_unmap(b->pBuffer,&b->mapInfo);
gst_buffer_set_size(b->pBuffer,xfer.pXfer->actual_length);

if(result == LIBUSB_TRANSFER_COMPLETED)
{
    //-- DROP DATA IF NOT IN PLAYING STATE --
    GstState st,pend;
    GstStateChangeReturn scr = gst_element_get_state(GST_ELEMENT(_pAppSrc),&st,&pend,GST_CLOCK_TIME_NONE);
    Q_UNUSED(scr)
    bool drop = (st != GST_STATE_PLAYING);

    if(!drop)
    {
        GstFlowReturn ret = GST_FLOW_OK;

        // Push into pipeline
        ret = gst_app_src_push_buffer(GST_APP_SRC(_pAppSrc),b->pBuffer);

        if(ret != GST_FLOW_OK)
            qCDebug(MMCVideoLog()) << "Can't push buffer to the pipeline (" << ret << ")";
        else
            unref = false;  // Don't unref since gst_app_src_push_buffer() steals one reference and takes ownership
    }
} else if(result == LIBUSB_TRANSFER_CANCELLED)
{
    qCDebug(MMCVideoLog()) << "! Buffer canceled";
} else {
    qCDebug(MMCVideoLog()) << "? Buffer result = " << result;
}    

if(unref)
    gst_buffer_unref(b->pBuffer);

这是我从受影响机器上的 Android logcat 得到的:

[07-22 18:37:45.753 17414:18734 E/QGroundControl]
VideoReceiverLog: GStreamer error: [element ' "mp4mux0" ']  Could not multiplex stream.

[07-22 18:37:45.753 17414:18734 E/QGroundControl]
VideoReceiverLog: Details:  ../gst/isomp4/gstqtmux.c(5010): gst_qt_mux_add_buffer (): /GstPipeline:receiver/GstBin:sinkbin/GstMP4Mux:mp4mux0:
Buffer has no PTS.

我尝试过的:

  • 将 GstBaseParser pts_interpolation 设置为 TRUE,将 infer_ts 设置为 TRUE

所以我的问题是:

  • 你能看出我的代码有什么问题吗?我遗漏了什么?
  • 我可以依靠 matroskamux 来暂时避免这个问题,直到我找到真正的答案吗? 原因?

编辑:我设法在打印出每个缓冲区的 PTS 和 DTS 的同时使用连接到我的 T 恤元件的水槽垫的探针“原位”复制它,并发现有问题的缓冲区没有 DTS 和 PTS。也许我的 h264parse 或 capsfilter 在我的 appsrc 和我的 tee 之间做了一些令人讨厌的事情?

07-28 17:54:49.025  1932  2047 D : PTS:  295659241497 DTS:  295659241497
07-28 17:54:49.026  1932  2047 D : PTS:  295682488791 DTS:  295682488791
07-28 17:54:49.053  1932  2047 D : PTS:  295710463127 DTS:  295710463127
07-28 17:54:49.054  1932  2047 D : PTS:  18446744073709551615  DTS:  18446744073709551615
07-28 17:54:49.054  1932  2047 E : ************** NO PTS
07-28 17:54:49.054  1932  2047 E : ************** NO DTS
07-28 17:54:49.110  1932  2047 D : PTS:  295738607214 DTS:  295738607214
07-28 17:54:49.111  1932  2199 E : GStreamer error: [element ' "mp4mux1" ']  Could not multiplex stream.
07-28 17:54:49.111  1932  2199 E : Details:  ../gst/isomp4/gstqtmux.c(5010): gst_qt_mux_add_buffer (): /GstPipeline:receiver/GstBin:sinkbin/GstMP4Mux:mp4mux1:
07-28 17:54:49.111  1932  2199 E : Buffer has no PTS.

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)