我正在使用 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_system_clock_obtain
),然后将其 clock-type
属性设置为 MONOTONICgst_pipeline_use_clock
将其设置为管道的时钟gst_base_src_set_do_timestamp
(尝试使用 true 和 false)有什么想法吗?或者是在我从应用程序接收器获取缓冲区并计算自己的增量的同时简单读取系统时钟的最佳方法?
我终于找到了解决办法。在内部,GST 元素保留一个
base_time
。每次生成缓冲区时,源元素都会读取其时钟(通常与管道的其余部分共享相同的时钟)并从中减去 base_time
。
当元素转换到
base_time
状态时,PLAYING
设置为时钟的当前值。因此,每个缓冲区的时间戳最终都是自元素开始播放以来经过的时间。
所以为了实现我的目标,需要两个步骤:
创建管道后,将其配置为使用系统单调时钟,而不是与操作系统时钟不同步的其他时钟。
假设
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)
管道转换到
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));
...
我可以知道如何在我的情况下使用以下管道获取时间戳吗
相机内:
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