From 112e3c499c8eaf82a3620df60e01a87f49f892d6 Mon Sep 17 00:00:00 2001 From: wanghaoyu <1580258873@qq.com> Date: Thu, 24 Oct 2024 20:57:02 +0800 Subject: [PATCH] =?UTF-8?q?[merge]=E5=90=88=E5=B9=B6=E6=8B=89=E6=B5=81?= =?UTF-8?q?=E4=B8=8E=E5=9F=9F=E5=90=8D=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Src/Video/cffmpeg_decode.cpp | 10 ++++--- Src/Video/ffmpegpushstream.cpp | 49 ++++++++++++++++++++++++++++++---- Src/Video/ffmpegpushstream.h | 4 +++ global.cpp | 2 +- 4 files changed, 55 insertions(+), 10 deletions(-) diff --git a/Src/Video/cffmpeg_decode.cpp b/Src/Video/cffmpeg_decode.cpp index 9e16a43..484bc70 100644 --- a/Src/Video/cffmpeg_decode.cpp +++ b/Src/Video/cffmpeg_decode.cpp @@ -80,24 +80,26 @@ bool Cffmpeg_decode::open_input_file() { // 0);//注:设置tcp会导致吊舱拉流中断 // av_dict_set(&avdic, "rtsp_transport", "udp", 0); // 设置缓存大小,1080p可将值调大 - av_dict_set(&avdic, "buffer_size", "2048000", 0); + av_dict_set(&avdic, "buffer_size", "4096000", 0); // 设置超时断开连接时间,单位微秒//listen_timeout // av_dict_set(&avdic, "listen_timeout", "200000", 0); av_dict_set(&avdic, "stimeout", "5000000", 0); // 设置超时5秒 - av_dict_set(&avdic, "max_delay", "300000", 0); // 设置最大时延300ms + // av_dict_set(&avdic, "max_delay", "300000", 0); // 设置最大时延300ms av_dict_set(&avdic, "tune", "zerolatency", 0); // 实时编码 av_dict_set(&avdic, "preset", "faster", 0); // ultrafast av_dict_set(&avdic, "threads", "auto", 0); // 自动开启线程数 // 设置最大重试时间为1s,解决avformat_open_input打开空流时间过长问题 av_dict_set(&avdic, "max_interleave_delta", "1000000", 0); - // av_dict_set(&avdic, "reconnect", "1", 0); // 开启自动重连 + // av_dict_set(&avdic, "reconnect", "1", 0); // 开启自动重连 // av_dict_set(&avdic, "reconnect_streamed", "1", 0); // 对于流媒体自动重连 - // av_dict_set(&avdic, "reconnect_delay_max", "5", 0); // 最大重连延时 5 秒 + av_dict_set(&avdic, "reconnect_delay_max", "5", + 0); // 最大重连延时 5 秒f'f'f'f'f'f'f'f'f'f'f // av_dict_set(&avdic, "rtsp_flags", "prefer_tcp", 0); // 保持TCP连接 // av_dict_set(&avdic, "timeout", "500000", 0); // 超时时间设置为500ms // av_dict_set(&avdic, "probesize", "50000000", 0); // 增加探针大小,1MB // av_dict_set(&avdic, "analyzeduration", "5000000", 0); // + // av_dict_set(&avdic, "keepalive", "1", 0); // 增加分析持续时间,5秒 // 打开输入流之前,设置非阻塞模式 diff --git a/Src/Video/ffmpegpushstream.cpp b/Src/Video/ffmpegpushstream.cpp index 7ce0bcf..6d08075 100644 --- a/Src/Video/ffmpegpushstream.cpp +++ b/Src/Video/ffmpegpushstream.cpp @@ -9,6 +9,7 @@ FFmpegPushStream::FFmpegPushStream(QObject *parent) : QObject{parent} {} void FFmpegPushStream::setRemoteIP(QString url) { pushStreamIP = url; } int FFmpegPushStream::openNetworkStream(AVFormatContext *inputFormatCtx) { + mInitStatus = false; if (pushStreamIP.isEmpty()) return -1; @@ -67,10 +68,34 @@ int FFmpegPushStream::openNetworkStream(AVFormatContext *inputFormatCtx) { } mInitStatus = true; this->inputFormatCtx = inputFormatCtx; - startTime = av_gettime_relative(); + // startTime = av_gettime_relative(); return 1; } +int FFmpegPushStream::reconnect(int ret) { + if (ret == AVERROR(EPIPE) || ret == AVERROR(ECONNRESET)) { + // int nRetryCount = 0; + for (int nRetryCount = 0; nRetryCount < MAXCONNECT; ++nRetryCount) { + // 关闭输出 + if (outputFormatCtx && !(outputFormatCtx->flags & AVFMT_NOFILE)) { + avio_close(outputFormatCtx->pb); + } + // Try to reconnect + ret = avformat_write_header(outputFormatCtx, nullptr); + if (ret < 0) { + qDebug() << "Failed to reconnect" << QString::number(nRetryCount + 1); + // nRetryCount++; + av_usleep(5 * 1000000); + } else { + mInitStatus = true; + return ret; + } + } + mInitStatus = false; + return -1; + } +} + /** * @brief 推流 * @param pkt: 未解码帧 @@ -81,11 +106,16 @@ int FFmpegPushStream::openNetworkStream(AVFormatContext *inputFormatCtx) { */ int FFmpegPushStream::pushStream(AVPacket *pkt, int frm_cnt, int64_t startTime, int64_t firstDts) { - if (!mInitStatus) + // qDebug() << "receive packet"; + if (!mInitStatus) { + av_packet_unref(pkt); return -1; + } - if (pkt->dts <= 0) + if (pkt->dts <= 0) { + av_packet_unref(pkt); return -1; + } // qDebug() << "******推流" << QString::number(frm_cnt++); int inputStreamIndex = pkt->stream_index; int outputStreamIndex = 0; @@ -115,8 +145,8 @@ int FFmpegPushStream::pushStream(AVPacket *pkt, int frm_cnt, int64_t startTime, auto now_time = av_gettime() - startTime; // 获取差值 int64_t delay = streamTime - now_time; if (delay > 0) { - // qDebug() << "****************sleep time:" << QString::number(delay / - // 1000); + qDebug() << "****************PushStream sleep time:" + << QString::number(delay / 1000); av_usleep(delay); } @@ -137,6 +167,7 @@ int FFmpegPushStream::pushStream(AVPacket *pkt, int frm_cnt, int64_t startTime, (int64_t)av_rescale_q(pkt->duration, istream_base, ostream_base); pkt->pos = -1; if (pkt->pts < pkt->dts) { + av_packet_unref(pkt); return 1; } @@ -144,6 +175,14 @@ int FFmpegPushStream::pushStream(AVPacket *pkt, int frm_cnt, int64_t startTime, pkt->stream_index = 0; int ret = av_interleaved_write_frame(outputFormatCtx, pkt); if (ret < 0) { + // if (ret == -10053) { + // qDebug() << "网络不稳定"; + // } + // if (ret == AVERROR(EPIPE) || ret == AVERROR(ECONNRESET)) { + // qDebug() << "网络不稳定1"; + // } + // reconnect(ret); + av_packet_unref(pkt); return ret; } // 数据包写入成功,现在可以释放pkt diff --git a/Src/Video/ffmpegpushstream.h b/Src/Video/ffmpegpushstream.h index 94270c4..b06610b 100644 --- a/Src/Video/ffmpegpushstream.h +++ b/Src/Video/ffmpegpushstream.h @@ -23,11 +23,15 @@ private: QString pushStreamIP; // 推流地址 bool mInitStatus = false; int64_t startTime; + int MAXCONNECT = 12; public slots: int pushStream(AVPacket *pkt, int frm_cnt, int64_t startTime, int64_t firstDts); void stopPush(); int openNetworkStream(AVFormatContext *inputFormatCtx); + +private: + int reconnect(int ret); }; #endif // FFMPEGPUSHSTREAM_H diff --git a/global.cpp b/global.cpp index 322282a..01fad35 100644 --- a/global.cpp +++ b/global.cpp @@ -2,7 +2,7 @@ global::global() {} -QString g_SoftwareVersion = "版本号:V1.0.0.1014"; +QString g_SoftwareVersion = "版本号:V1.0.2.1024"; QColor g_themeColor(51, 51, 51); QString g_PushBtnStyle = /**正常情况下样式**/