You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

GStreamer-1.0 视频帧时间戳与Linux单调时钟关联问题

我正在使用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时间戳和系统时钟无关,似乎是管道进入PLAYING状态时的GST特定纪元偏移量。我想找更优的方案替代“读取帧时同步取系统时钟计算差值”,比如:

  • 获取GST零时间戳对应的Linux单调时钟时间,将偏移量加到每个缓冲区时间戳上
  • 用某个未发现的函数直接将缓冲区时间戳转换为系统时间戳
  • 配置管道或元件使用系统单调时钟作为缓冲区时间戳

我尝试过几种无效方法:

  • 获取系统时钟(gst_system_clock_obtain)并设置clock-type为MONOTONIC
  • 调用gst_pipeline_use_clock将上述时钟设为管道时钟
  • 在v4l2src上调用gst_base_src_set_do_timestamp(尝试过true和false)

请问有什么解决方案?还是只能在从appsink取缓冲区时同步读取系统时钟自行计算差值?


解决方案

方法一:利用GStreamer时钟的时间转换功能

GStreamer内置了管道时间戳到系统时钟的转换接口,无需自行计算偏移:

  1. 获取管道绑定的时钟:
GstClock *clock = gst_pipeline_get_clock(GST_PIPELINE(pipeline));
  1. 将缓冲区PTS转换为Linux单调时钟时间(GST时间单位为纳秒):
GstClockTime buffer_pts = GST_BUFFER_PTS(buffer);
GstClockTime system_monotonic_time;
GstClockReturn ret = gst_clock_convert_time(clock, GST_CLOCK_TIME_NONE, buffer_pts, &system_monotonic_time);

转换后的system_monotonic_time就是对应Linux单调时钟的纳秒级时间戳,可直接与传感器时间关联。

方法二:配置管道使用系统单调时钟生成时间戳

如果想让GST缓冲区直接使用系统单调时钟纪元,需在管道进入PLAYING状态前完成配置:

  1. 获取并配置系统单调时钟:
GstClock *system_clock = gst_system_clock_obtain();
g_object_set(system_clock, "clock-type", GST_SYSTEM_CLOCK_MONOTONIC, NULL);
  1. 将该时钟绑定到管道:
gst_pipeline_use_clock(GST_PIPELINE(pipeline), system_clock);
gst_object_unref(system_clock);
  1. 开启v4l2src的时钟时间戳生成:
gst_base_src_set_do_timestamp(GST_BASE_SRC(v4l2src), TRUE);

此时GST_BUFFER_PTS(buffer)会直接对应Linux单调时钟的纳秒时间戳。之前尝试无效大概率是因为配置时机太晚,必须在管道启动前完成所有时钟设置。

备选方案:记录初始偏移量做转换

如果上述方法仍有问题,可在管道启动时记录GST纪元对应的系统时间,后续用偏移量转换:

  1. 监听管道状态变化,在进入PLAYING时记录偏移:
static void on_pipeline_state_changed(GstElement *pipeline, GstState old_state, GstState new_state, gpointer user_data) {
    if (new_state == GST_STATE_PLAYING) {
        GstClock *clock = gst_pipeline_get_clock(GST_PIPELINE(pipeline));
        GstClockTime gst_zero = gst_clock_get_time(clock);
        struct timespec monotonic_now;
        clock_gettime(CLOCK_MONOTONIC, &monotonic_now);
        guint64 system_zero = monotonic_now.tv_sec * 1000000000ULL + monotonic_now.tv_nsec;
        // 保存偏移量:系统时间 = 缓冲区PTS + (系统零点 - GST零点)
        *(guint64*)user_data = system_zero - gst_zero;
        gst_object_unref(clock);
    }
}
  1. 处理缓冲区时计算系统时间:
guint64 offset = *(guint64*)user_data;
guint64 system_time = GST_BUFFER_PTS(buffer) + offset;

内容的提问来源于stack exchange,提问作者David C.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 23:05:24