【发布时间】:2021-02-12 05:48:11
【问题描述】:
是否可以从 Axis 相机通过 RTSP 发送的 H.264 流中读取绝对时间戳?
有必要知道相机何时拍摄了帧。
谢谢 安德烈亚
【问题讨论】:
是否可以从 Axis 相机通过 RTSP 发送的 H.264 流中读取绝对时间戳?
有必要知道相机何时拍摄了帧。
谢谢 安德烈亚
【问题讨论】:
正如 Ralf 已经说过的 - RTP 时间戳是相对于随机时钟的 - 它们仅用于计算两个帧(或一般的 RTP 数据包)之间的差异。要将这些相对值同步到挂钟,您可以使用 RTCP 发送器 - 只需查看 Ralf 提供的链接即可。
对于使用 H.264 的 Axis 产品,这非常有效。如果您还使用 MPEG4,则 Axis 固件存在错误,并且 RTCP SR 中的绝对时间戳不可靠 - 在这种情况下,您必须将相对 RTP 时间戳同步到您的客户端挂钟。
【讨论】:
假设摄像头固件工作正常并且定期与 NTP 同步,您可以从 RTCP Sender Report 中提取绝对时间戳。但此功能在 FFMpeg 库 API 中不可用,您必须使用头文件 libavformat/rtsp.h 才能访问内部数据结构。然后你必须计算每一帧的 ntp 时间戳:
RTSPState* rtsp_state = (RTSPState*) pFormatCtx->priv_data;
RTSPStream* rtsp_stream = rtsp_state->rtsp_streams[0];
RTPDemuxContext* rtp_demux_context = (RTPDemuxContext*) rtsp_stream->transport_priv;
int32_t d_ts = rtp_demux_context->timestamp - rtp_demux_context->last_rtcp_timestamp;
uint64_t last_ntp_time = rtp_demux_context->last_rtcp_ntp_time;
uint32_t seconds = ((last_ntp_time >> 32) & 0xffffffff)-2208988800;
uint32_t fraction = (last_ntp_time & 0xffffffff);
double useconds = ((double) fraction / 0xffffffff);
double base_time = seconds+useconds;
double frame_ntp_time = base_time+d_ts/90000.0;
完整的例子是here。
【讨论】:
rtp_demux_context->last_rtcp_ntp_time 应该是不变的吗?在我的相机上,它总是-9223372036854775808。 first_rtcp_ntp_time 也是。 frame_ntp_time 给了我自直播开始以来的相对时间,而不是挂钟。
last_rtcp_ntp_time 应该定期更新。以我的经验,并非所有相机都以正确的方式实现该协议。我用大华和海康威视测试成功,但是用HiWatch和你的问题类似
时间戳包含在 RTP 流中。 RTSP 是一种可用于启动/控制 RTP 媒体会话的协议。我假设使用了 RTP,您可以查看 RTP 标头here。
【讨论】:
有一个名为openRTSP(Debian 上为livemedia-utils,Arch 上为live-media)的程序获取参数o:
openRTSP -r rtsp://109.98.78.106
[...]
o=- 1613080009143448 1 IN IP4 109.98.78.106
没有看源码,我认为是Sender Report RTCP PacketsIslam Sabyrgaliyev提到的NTS系统时间戳。
date -d@$( echo $(openRTSP -r rtsp://109.98.78.106 2>&1 | grep -Po '(?<=o=-\s)\d+' | head -n1 ) / 1000000 | bc )
Thu Feb 11 10:46:07 PM CET 2021
【讨论】: