如何将 GStreamer 缓冲区时间戳与 Linux 系统时钟相关联

问题描述 投票:0回答:2

我正在使用 GStreamer-1.0 管道(除其他外)通过

v4l2src
元素从摄像机读取实时视频,并将数据输入到
appsink
元素中。我们对 appsink 生成的图像进行一些图像处理,生成有关图像内容的数据。

应用程序的另一部分从传感器(例如加速度计)读取数据。

我们需要关联两个来源的数据的时间戳。我们的传感器数据带有 Linux 单调时钟时间戳。我们现在需要将其与同时处理的视频帧生成的数据关联起来。

在我们的视频处理线程中,我们可以通过以下方式获取缓冲区的时间戳:

...
g_signal_emit_by_name(appsink, "pull-sample", &sample);
buffer = gst_sample_get_buffer(sample);
timestamp = GST_BUFFER_PTS(buffer);
...

但是 GST 时间戳与系统时钟无关。它们似乎是自 GST 特定纪元以来的时间偏移(我认为是当管道过渡到“播放”时)。

当然,我可以在读取帧并计算差异的同时获取系统时钟,但我希望有更好的方法来做到这一点。也许其中之一:

  • 获取GST的零时间戳对应的Linux系统单调时钟时间。所以我可以将此偏移量添加到每个缓冲区的时间戳中。
  • 使用一个函数(我在阅读文档时一定错过了)将缓冲区时间戳转换为系统时间戳。
  • 配置管道或其元素以使用系统单调时钟作为缓冲区时间戳。

我尝试了几种不同的方法但没有成功,包括:

  • 获取系统时钟 (
    gst_system_clock_obtain
    ),然后将其
    clock-type
    属性设置为 MONOTONIC
  • 执行上述操作,然后调用
    gst_pipeline_use_clock
    将其设置为管道的时钟
  • 在 v4l2src 对象上调用
    gst_base_src_set_do_timestamp
    (尝试使用 true 和 false)

有什么想法吗?或者是在我从应用程序接收器获取缓冲区并计算自己的增量的同时简单读取系统时钟的最佳方法?

linux gstreamer v4l2
2个回答
4
投票

我终于找到了解决办法。在内部,GST 元素保留一个

base_time
。每次生成缓冲区时,源元素都会读取其时钟(通常与管道的其余部分共享相同的时钟)并从中减去
base_time

当元素转换到

base_time
状态时,
PLAYING
设置为时钟的当前值。因此,每个缓冲区的时间戳最终都是自元素开始播放以来经过的时间。

所以为了实现我的目标,需要两个步骤:

  1. 创建管道后,将其配置为使用系统单调时钟,而不是与操作系统时钟不同步的其他时钟。

    假设

    pipe
    是指向管道的指针,这会将其时钟设置为系统单调:

    GstClock *clock = gst_system_clock_obtain();
    g_object_set(clock,
                 "clock-type", GST_CLOCK_TYPE_MONOTONIC,
                 NULL);
    gst_pipeline_use_clock(GST_PIPELINE_CAST(pipe), clock);
    gst_object_unref(clock)
    
  2. 管道转换到

    PLAYING
    状态后,获取源元素的
    base_time
    值,该值将是与缓冲时间零对应的系统单调值。

    假设

    vsrc
    是指向管道起始处的
    v4l2src
    对象的指针,那么以下代码(在
    gst_element_set_state
    成功将管道设置为
    PLAYING
    状态后执行)将获取源的
    base_time
    :

    GstClockTime base_time;
    
    base_time = gst_element_get_base_time(vsrc);
    

有了这个值,我现在可以将 base_time 添加到每个缓冲区的时间戳中,以获得与缓冲区创建相对应的单调时间:

...
g_signal_emit_by_name(appsink, "pull-sample", &sample);
buffer = gst_sample_get_buffer(sample);
buffer_ts = GST_BUFFER_PTS(buffer);
monotonic_ts = buffer_ts + base_time;

printf("Buffer TS: %" GST_TIME_FORMAT
       " is monotonic TS: %" GST_TIME_FORMAT "\n",
       GST_TIME_ARGS(buffer_ts),
       GST_TIME_ARGS(monotonic_ts));
...

0
投票

我可以知道如何在我的情况下使用以下管道获取时间戳吗

相机内:

gst-launch-1.0 v4l2src 设备=/dev/video3 !图像/jpeg,宽度=1920,高度=1080,帧率=60/1! rtpjpegpay mtu=65500 ! udpsink主机=192.168.1.126端口=5006同步=假-v

在主机中: gst-launch-1.0 udpsrc port=5005 caps="application/x-rtp,encoding-name=(string)JPEG, payload=(int)96" ! rtpjpeg支付!解码器! fpsdisplaysink 视频接收器=xvimagesink 文本覆盖=假同步=假-v

© www.soinside.com 2019 - 2024. All rights reserved.