|
@@ -154,22 +154,38 @@ bool RTSPClient::initialize_input() {
|
|
|
|
|
|
// 设置RTSP选项(Docker环境优化)
|
|
|
AVDictionary* options = nullptr;
|
|
|
- av_dict_set(&options, "rtsp_transport", "tcp", 0);
|
|
|
+ av_dict_set(&options, "rtsp_transport", "tcp", 0); // 强制使用TCP传输
|
|
|
|
|
|
- // 根据是否为Docker环境调整超时设置
|
|
|
+ // 根据是否为Docker环境调整超时和网络设置
|
|
|
if (debug_mode) {
|
|
|
- av_dict_set(&options, "timeout", "15000000", 0); // Docker环境:15秒连接超时
|
|
|
- av_dict_set(&options, "stimeout", "10000000", 0); // 10秒读取超时
|
|
|
- std::cout << "Docker环境超时配置: 连接15s, 读取50s" << std::endl;
|
|
|
+ // Docker环境专用设置
|
|
|
+ av_dict_set(&options, "timeout", "15000000", 0); // 15秒连接超时
|
|
|
+ av_dict_set(&options, "stimeout", "20000000", 0); // 20秒Socket超时
|
|
|
+ av_dict_set(&options, "rw_timeout", "10000000", 0); // 10秒读写超时
|
|
|
+ av_dict_set(&options, "listen_timeout", "5000000", 0); // 5秒监听超时
|
|
|
+
|
|
|
+ // 网络优化参数
|
|
|
+ av_dict_set(&options, "rtsp_flags", "listen", 0); // 启用监听模式
|
|
|
+ av_dict_set(&options, "fflags", "+discardcorrupt", 0); // 丢弃损坏的包
|
|
|
+ av_dict_set(&options, "flags", "+low_delay", 0); // 低延迟模式
|
|
|
+ av_dict_set(&options, "buffer_size", "1048576", 0); // 1MB缓冲区
|
|
|
+ av_dict_set(&options, "max_delay", "500000", 0); // 最大延迟500ms
|
|
|
+
|
|
|
+ // 设置更兼容的User-Agent
|
|
|
+ av_dict_set(&options, "user_agent", "LibVLC/3.0.0 (compatible; RTSP-Client)", 0);
|
|
|
+
|
|
|
+ std::cout << "Docker环境超时配置: 连接15s, Socket20s, 读写10s" << std::endl;
|
|
|
} else {
|
|
|
- av_dict_set(&options, "timeout", "10000000", 0); // 本地环境:10秒连接超时
|
|
|
- av_dict_set(&options, "stimeout", "5000000", 0); // 5秒读取超时
|
|
|
+ // 本地环境设置
|
|
|
+ av_dict_set(&options, "timeout", "10000000", 0); // 10秒连接超时
|
|
|
+ av_dict_set(&options, "stimeout", "8000000", 0); // 8秒Socket超时
|
|
|
+ av_dict_set(&options, "user_agent", "RTSP-Client", 0);
|
|
|
}
|
|
|
|
|
|
- av_dict_set(&options, "max_delay", "1000000", 0); // 最大延迟1秒
|
|
|
- av_dict_set(&options, "reorder_queue_size", "10", 0); // 减小缓冲队列
|
|
|
- av_dict_set(&options, "buffer_size", "65536", 0); // 设置缓冲区大小
|
|
|
- av_dict_set(&options, "user_agent", "RTSP-Client-Docker", 0); // 设置用户代理
|
|
|
+ // 通用网络优化设置
|
|
|
+ av_dict_set(&options, "reorder_queue_size", "10", 0); // 减小重排序队列
|
|
|
+ av_dict_set(&options, "analyzeduration", "2000000", 0); // 分析时长2秒
|
|
|
+ av_dict_set(&options, "probesize", "1048576", 0); // 探测大小1MB
|
|
|
|
|
|
// 设置超时时间(用于中断回调)
|
|
|
start_time_us_ = av_gettime();
|
|
@@ -184,7 +200,43 @@ bool RTSPClient::initialize_input() {
|
|
|
if (ret < 0) {
|
|
|
char error_buf[AV_ERROR_MAX_STRING_SIZE];
|
|
|
av_strerror(ret, error_buf, sizeof(error_buf));
|
|
|
- std::cerr << "无法打开RTSP流 " << config_.rtsp_url << ": " << error_buf << std::endl;
|
|
|
+
|
|
|
+ std::cerr << "===== RTSP连接失败详细信息 =====" << std::endl;
|
|
|
+ std::cerr << "RTSP URL: " << config_.rtsp_url << std::endl;
|
|
|
+ std::cerr << "FFmpeg错误码: " << ret << std::endl;
|
|
|
+ std::cerr << "FFmpeg错误信息: " << error_buf << std::endl;
|
|
|
+
|
|
|
+ // 根据具体错误类型提供诊断建议
|
|
|
+ switch (ret) {
|
|
|
+ case AVERROR(ECONNREFUSED):
|
|
|
+ std::cerr << "诊断: 连接被拒绝 - RTSP服务可能未运行或端口被防火墙阻止" << std::endl;
|
|
|
+ break;
|
|
|
+ case AVERROR(EHOSTUNREACH):
|
|
|
+ std::cerr << "诊断: 主机不可达 - 检查网络连接和路由配置" << std::endl;
|
|
|
+ break;
|
|
|
+ case AVERROR(ENETUNREACH):
|
|
|
+ std::cerr << "诊断: 网络不可达 - Docker网络配置可能有问题" << std::endl;
|
|
|
+ break;
|
|
|
+ case AVERROR_INVALIDDATA:
|
|
|
+ std::cerr << "诊断: 无效数据 - RTSP流可能不存在或格式不支持" << std::endl;
|
|
|
+ break;
|
|
|
+ case AVERROR(ETIMEDOUT):
|
|
|
+ std::cerr << "诊断: 连接超时 - 网络延迟过高或RTSP服务没有响应" << std::endl;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ std::cerr << "诊断: 未知错误 - 请检查RTSP流地址和网络连接" << std::endl;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加Docker环境特有的诊断建议
|
|
|
+ if (debug_mode) {
|
|
|
+ std::cerr << "\nDocker环境诊断建议:" << std::endl;
|
|
|
+ std::cerr << "1. 确认使用 network_mode: host" << std::endl;
|
|
|
+ std::cerr << "2. 检查容器内网络访问权限" << std::endl;
|
|
|
+ std::cerr << "3. 尝试在容器内执行: curl -v rtsp://" << config_.rtsp_url.substr(7) << std::endl;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::cerr << "=====================================" << std::endl;
|
|
|
|
|
|
// 根据错误类型判断是否为快速失败
|
|
|
if (ret == AVERROR(ECONNREFUSED) || ret == AVERROR(EHOSTUNREACH) ||
|