ZLMediaKit / ZLMediaKit

WebRTC/RTSP/RTMP/HTTP/HLS/HTTP-FLV/WebSocket-FLV/HTTP-TS/HTTP-fMP4/WebSocket-TS/WebSocket-fMP4/GB28181/SRT server and client framework based on C++11
https://docs.zlmediakit.com
Other
13.65k stars 3.37k forks source link

[BUG]ffmpeg播放rtsp流不平滑 #998

Closed zhang2349 closed 3 years ago

zhang2349 commented 3 years ago

bug现象 更新到最新代码https://github.com/ZLMediaKit/ZLMediaKit/commit/566a49e2278201fbe624705e9c654d06e4eb7166

我用ffmpeg 播放rtsp流不平滑了, av_read_frame 会一秒钟 读50帧 然后 卡一秒了

以前版本 大概跟6.0分支的代码差不多 是 av_read_frame 每秒读25帧

大概是跟前段时间的 时间戳有关

bug产生时的使用场景 接收ps流,用ffmpeg播放rtsp地址

bug是否可以复现,怎么复现 必现

zlm代码git commit hash值 566a49e2278201fbe624705e9c654d06e4eb7166

操作系统环境 windows linux都会出现

xia-chu commented 3 years ago

这个流是GB28181流吗? zlm最写了rtsp的时间戳机制,目的是为了实现精准的时间戳同步功能,并不会导致音视频卡顿的。 你是不是开启了时间戳覆盖功能?

zhang2349 commented 3 years ago

modifyStamp吗 是默认的0 接收GB28181流,只有视频流

早前的代码没这个问题 最新的代码才有这个问题

xia-chu commented 3 years ago

会用zlmediakit的dump功能吗?配置文件搜索下dumpDir,你dump出文件发给我, 我看看你数据时间戳是不是ok的

zhang2349 commented 3 years ago

gb_play_33032400001180005164_33032496021321207965.zip 时间戳应该是对的 解码出的pts间隔都是一样的 就是 一秒获取到50帧 一秒卡住

xia-chu commented 3 years ago

我这个播放rtsp正常

zhang2349 commented 3 years ago

你是指用vlc或ffplay播放正常吗 这是因为他做了缓存同步吧

我意思说用ffmpeg的av_read_frame 函数来读取rtsp流 会出现 一秒获取到50帧 一秒卡住的情况 以前的代码是 均匀的每秒25帧的情况

2秒的整体数据应该是正常的 只是为什么1秒就都给了

xia-chu commented 3 years ago

那是你发送端问题吧?我用test_rtp程序加载rtp文件 生成的流用test_player播放是平滑的。ffplay播放也正常。你设备如果一秒发50帧 那么zlm就会一秒转发50帧

发自我的iPhone

------------------ 原始邮件 ------------------ 发件人: zhang2349 @.> 发送时间: 2021年7月21日 17:22 收件人: ZLMediaKit/ZLMediaKit @.> 抄送: 夏楚 @.>, Comment @.> 主题: 回复:[ZLMediaKit/ZLMediaKit] [BUG]ffmpeg播放rtsp流不平滑 (#998)

你是指用vlc或ffplay播放正常吗 这是因为他做了缓存同步吧

我意思说用ffmpeg的av_read_frame 函数来读取rtsp流 会出现 秒获取到50帧 一秒卡住的情况 以前的代码是 均匀的每秒25帧的情况

2秒的整体数据应该是正常的 只是为什么1秒就都给了

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

zhang2349 commented 3 years ago

不是发送端问题 所有的摄像头都有这个问题 老的代码是没问题的

xia-chu commented 3 years ago

你是rtsp协议取流吗

发自我的iPhone

------------------ 原始邮件 ------------------ 发件人: zhang2349 @.> 发送时间: 2021年7月21日 17:41 收件人: ZLMediaKit/ZLMediaKit @.> 抄送: 夏楚 @.>, Comment @.> 主题: 回复:[ZLMediaKit/ZLMediaKit] [BUG]ffmpeg播放rtsp流不平滑 (#998)

不是发送端问题 所有的摄像头都有这个问题 老的代码是没问题的

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

zhang2349 commented 3 years ago

对 播的rtsp

xia-chu commented 3 years ago

你先用test_player播放测试下

发自我的iPhone

------------------ 原始邮件 ------------------ 发件人: zhang2349 @.> 发送时间: 2021年7月21日 18:00 收件人: ZLMediaKit/ZLMediaKit @.> 抄送: 夏楚 @.>, Comment @.> 主题: 回复:[ZLMediaKit/ZLMediaKit] [BUG]ffmpeg播放rtsp流不平滑 (#998)

AVDictionary *opts = NULL; av_dict_set(&amp;opts, "rtsp_transport", "tcp", 0); AVFormatContext *fmt_ctx = avformat_alloc_context(); int ret = avformat_open_input(&amp;fmt_ctx, rtsp_url, NULL, &amp;opts); std::cout << "avformat_open_input:" << ret << std::endl; ret = avformat_find_stream_info(fmt_ctx, NULL); std::cout << "avformat_find_stream_info:" << ret << std::endl; av_dump_format(fmt_ctx, 0, url, 0); AVPacket packet; AVFrame *frame = av_frame_alloc(); while (1) { ret = av_read_frame(fmt_ctx, &amp;packet); if (ret < 0) break; }
— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

zhang2349 commented 3 years ago

AVDictionary *opts = NULL; av_dict_set(&opts, "rtsp_transport", "tcp", 0);

AVFormatContext *fmt_ctx = avformat_alloc_context(); int ret = avformat_open_input(&fmt_ctx, rtsp_url, NULL, &opts); std::cout << "avformat_open_input:" << ret << std::endl;

ret = avformat_find_stream_info(fmt_ctx, NULL); std::cout << "avformat_find_stream_info:" << ret << std::endl;

av_dump_format(fmt_ctx, 0, url, 0);

AVPacket packet; AVFrame *frame = av_frame_alloc(); while (1) { ret = av_read_frame(fmt_ctx, &packet); std::cout << "av_read_frame:" << ret << std::endl; if (ret < 0) break; } av_read_frame 的输出会停一下 刷一下 停一下 刷一下

zhang2349 commented 3 years ago

https://user-images.githubusercontent.com/1287115/126492160-66259917-99eb-411a-a19f-3de9de4cb2b6.mp4

test_player也是一样的 看录屏 看时间停一下 快速跳一下 停一下 快速跳一下

zhang2349 commented 3 years ago

顺便报一下test_player的一个问题, ffmpeg硬解出来的yuv是nv12格式的 不是yuv420p 需要转换下 或者 sdl要根据类型创建texture

xia-chu commented 3 years ago

猜测你的设备就是这样发流的 因为这样叫合并写 可以提高系统调用效率和性能。 你的设备是tcp推流吧? 之前是udp吧? udp肯定是平滑的

xia-chu commented 3 years ago

这个问题不是bug 也没问题的。因为数据的速度不影响播放的流畅性,播放时用时间戳控制速度的,跟数据速度无关。 所以你的代码得改改,自己需要根据时间戳控制速度, 你不能指望zlm和设备能输出的很平滑,因为网络可能抖动,另外有些服务器出于提高性能的考虑,也会合并写,这样也会导致数据速度不平滑

xia-chu commented 3 years ago

issue我先关闭了,有什么问题在下面继续讨论。

zhang2349 commented 3 years ago

真不是设备问题 设备是udp推流的 你的意思是合并写造成的? 具体是哪里 我改回去试试

xia-chu commented 3 years ago

这里是合并写逻辑,你参考这样修改:

图片
zhang2349 commented 3 years ago

这里是合并写逻辑,你参考这样修改:

图片

但是我看了两个版本的代码 这里是一样的

这样返回的数据 其实是延迟了 貌似时间久了 会累积

zhang2349 commented 3 years ago

issue我先关闭了,有什么问题在下面继续讨论。

找到问题在哪里了,但是没看出来为什么。。。

原因是因为 以前测试的时候 我把这个max_frame_size改大成1024*1024了 https://github.com/ZLMediaKit/ZLMediaKit/blob/30840d82007292bf113283c792f0ff8a3a2eab4d/src/Rtp/GB28181Process.cpp#L129

然后最近这里修改使用getStampMS()了,老版本是直接用stamp的 https://github.com/ZLMediaKit/ZLMediaKit/blob/0e2770485974bc8667a8076e5f5f7bc949970072/src/Extension/CommonRtp.cpp#L31

测试发现 max_frame_size用1024 1024 stamp就用stamp 是正常的 max_frame_size用32 1024 stamp用getStampMS 也是正常的 max_frame_size用1024 * 1024 stamp用getStampMS 就出现这种情况了
真是奇怪 我打印了 stamp getStampMS 的值 变化也都是一样的。。

xia-chu commented 3 years ago

嗯 说明你的设备rtp时间戳不规范 一直为0吧?

发自我的iPhone

------------------ 原始邮件 ------------------ 发件人: zhang2349 @.> 发送时间: 2021年7月22日 15:21 收件人: ZLMediaKit/ZLMediaKit @.> 抄送: 夏楚 @.>, State change @.> 主题: 回复:[ZLMediaKit/ZLMediaKit] [BUG]ffmpeg播放rtsp流不平滑 (#998)

issue我先关闭了,有什么问题在下面继续讨论。

找到问题在哪里了,但是没看出来为什么。。。

原因是因为 以前测试的时候 我把这个max_frame_size改大成1024*1024了 https://github.com/ZLMediaKit/ZLMediaKit/blob/30840d82007292bf113283c792f0ff8a3a2eab4d/src/Rtp/GB28181Process.cpp#L129

然后最近这里修改使用getStampMS()了,老版本是直接用stamp的 https://github.com/ZLMediaKit/ZLMediaKit/blob/0e2770485974bc8667a8076e5f5f7bc949970072/src/Extension/CommonRtp.cpp#L31

测试发现 max_frame_size用10241024 stamp就用stamp 是正常的 max_frame_size用321024 stamp用getStampMS 也是正常的 max_frame_size用1024*1024 stamp用getStampMS 就出现这种情况了 真是奇怪

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub, or unsubscribe.

zhang2349 commented 3 years ago

是规范的呀 我也dump给你看了

zhang2349 commented 3 years ago

嗯 说明你的设备rtp时间戳不规范 一直为0吧? 发自我的iPhone ------------------ 原始邮件 ------------------ 发件人: zhang2349 @.> 发送时间: 2021年7月22日 15:21 收件人: ZLMediaKit/ZLMediaKit @.> 抄送: 夏楚 @.>, State change @.> 主题: 回复:[ZLMediaKit/ZLMediaKit] [BUG]ffmpeg播放rtsp流不平滑 (#998) issue我先关闭了,有什么问题在下面继续讨论。 找到问题在哪里了,但是没看出来为什么。。。 原因是因为 以前测试的时候 我把这个max_frame_size改大成10241024了 https://github.com/ZLMediaKit/ZLMediaKit/blob/30840d82007292bf113283c792f0ff8a3a2eab4d/src/Rtp/GB28181Process.cpp#L129 然后最近这里修改使用getStampMS()了,老版本是直接用stamp的 https://github.com/ZLMediaKit/ZLMediaKit/blob/0e2770485974bc8667a8076e5f5f7bc949970072/src/Extension/CommonRtp.cpp#L31 测试发现 max_frame_size用10241024 stamp就用stamp 是正常的 max_frame_size用321024 stamp用getStampMS 也是正常的 max_frame_size用10241024 stamp用getStampMS 就出现这种情况了 真是奇怪 — You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub, or unsubscribe.

如果都是0 那不管用stamp还是getStampMS 都是会不正常的吧 用stamp就正常 就看不懂了

xia-chu commented 3 years ago

https://github.com/ZLMediaKit/ZLMediaKit/blob/0e2770485974bc8667a8076e5f5f7bc949970072/src/Extension/CommonRtp.cpp#L31

改成

auto stamp = rtp->getStamp(); 

就行吗

zhang2349 commented 3 years ago

https://github.com/ZLMediaKit/ZLMediaKit/blob/0e2770485974bc8667a8076e5f5f7bc949970072/src/Extension/CommonRtp.cpp#L31

改成

auto stamp = rtp->getStamp(); 

就行吗

是的

xia-chu commented 3 years ago

嗯 我调试了 确实是zlmediakit的bug 正在修复

发自我的iPhone

------------------ 原始邮件 ------------------ 发件人: zhang2349 @.> 发送时间: 2021年7月22日 17:06 收件人: ZLMediaKit/ZLMediaKit @.> 抄送: 夏楚 @.>, State change @.> 主题: 回复:[ZLMediaKit/ZLMediaKit] [BUG]ffmpeg播放rtsp流不平滑 (#998)

https://github.com/ZLMediaKit/ZLMediaKit/blob/0e2770485974bc8667a8076e5f5f7bc949970072/src/Extension/CommonRtp.cpp#L31

改成 auto stamp = rtp->getStamp();

就行吗

是的

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub, or unsubscribe.

xia-chu commented 3 years ago

这个问题修复了 您看一下

zhang2349 commented 3 years ago

可以了