本文主要讨论rtspdec.c 和 rtpdec.c两个模块
一: 函数增加
因为ffmpeg的rtsp没有Pause模块,所以需要手动添加
AVInputFormat ff_rtsp_demuxer = {
.name = "rtsp",
.long_name = NULL_IF_CONFIG_SMALL("RTSP input"),
.priv_data_size = sizeof(RTSPState),
.read_probe = rtsp_probe,
.read_header = rtsp_read_header,
.read_packet = rtsp_read_packet,
.read_close = rtsp_read_close,
.read_seek = rtsp_read_seek,
.flags = AVFMT_NOFILE,
.read_play = rtsp_read_play,
.read_resume = rtsp_read_resume,
.read_pause = rtsp_read_pause,
.priv_class = &rtsp_demuxer_class,
};
这两个文件的先后顺序是rtspdec先执行,rtpdec后执行。
先执行的会归零操作,具体的时间戳是在rtpdec里面的final**函数,pts=。这个即反应显示的时间轴,中间有个简单90k的换算。
ffmpeg的rtsp从0到2.6.1版本,是没有resume处理的,只有play,因此,需要再rtspdec.c中最下面添加一个注册模块,并在相应的头文件中加上。
(补充代码)
添加完resume函数后,接下来分析这个时间戳。
rtsp计算时间戳的方法不复杂:当你执行seek的时候,先把时间戳归零,还有一些seq等都归零,然后将暂停和seek的时间轴发给rtsp服务器,rtsp服务器会回应一个ts,也就是时间戳给你,你计算的时候加上这个偏差即可。详细见rtpdec.c
(补充代码)
如果是暂停再恢复,可能处理起来相对复杂,因为要自己实现,否则进度条会显示不对,为什么呢?因为进度条是取自ts,也就是rtpdec中的pts。
首先时间戳就不能归零,一归零进度条也归零。
(补充代码)
大概意思讲明白了,现在说说几个问题。
1:有些摄像头可能ts不是往上累加的,比如摄像头发生重启了,时间戳中途归零了,怎么办?
我的分析是,只要是同一个录像,就要保证ts是一直累加的,否则播了一半就播不动。
可以用ts矫正来做,判断如果ts突然到0了就强制用上一次的备份ts赋值,
但如果ts不是0,是一个随机值呢?可能比之前的大,也可能小。
比如我跑到12345了,这时候跳到54321,或者1234,怎么办?
如果是1234那好办,判断不是递增的,就强行递增。如果是54321,那你就不能用12346来代替了,直接用54321,也能播,只是可能花屏。
具体判断是再rtpdec里面,计算pts之前,要做个backup ts,然后如果ts不正确时做处理。
2:如果我手动赋值了12346,但是这时候又往回seek,会不会出错?
前面说了,seek操作是会重新计算ts的,先归零,再计算offset,然后加在一起。
总之就是保证你seek的点正确,然后数据流也是seek点的数据,这样就不会卡住,也不会花屏。
所以,按理是不会出错的。
(后续待整理)