From 434323ec8d393d6a126cd647c03e8788f3f18d96 Mon Sep 17 00:00:00 2001
From: cbwu <504-wuchengbo@htsdfp.com>
Date: Thu, 14 Nov 2024 17:22:27 +0800
Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=8E=A8=E6=B5=81?=
 =?UTF-8?q?=E5=9C=B0=E5=9D=80=E5=88=87=E6=8D=A2=E4=B8=8D=E7=94=9F=E6=95=88?=
 =?UTF-8?q?=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 PayloadAPP.pro                 |  2 +-
 Src/GDDC/gddcdlg.cpp           |  1 +
 Src/Video/cffmpeg_decode.cpp   | 13 +++---
 Src/Video/ffmpegpushstream.cpp | 82 +++++++++++++++++++++++++++++++++-
 Src/Video/ffmpegpushstream.h   |  2 +
 Src/Video/ffmpegvideodlg.cpp   |  2 +-
 global.cpp                     |  2 +-
 mainwindow.cpp                 |  1 +
 8 files changed, 94 insertions(+), 11 deletions(-)

diff --git a/PayloadAPP.pro b/PayloadAPP.pro
index 225f98a..65a0fd4 100644
--- a/PayloadAPP.pro
+++ b/PayloadAPP.pro
@@ -14,7 +14,7 @@ QMAKE_PROJECT_DEPTH = 0
 # QMAKE_LFLAGS += /MANIFESTUAC:\"level=\'requireAdministrator\' uiAccess=\'false\'\"
 
 #程序版本
-VERSION = 1.0.2.2
+VERSION = 1.0.2.3
 #程序版本
 QMAKE_TARGET_COMPANY = "HTSDFP"
 
diff --git a/Src/GDDC/gddcdlg.cpp b/Src/GDDC/gddcdlg.cpp
index 2ac1ee3..0f6a960 100644
--- a/Src/GDDC/gddcdlg.cpp
+++ b/Src/GDDC/gddcdlg.cpp
@@ -516,6 +516,7 @@ void GDDCdlg::startPushURL() {
     ffmpegvideoDlg *videoDlg = ui->WgtffmpegVideo;
     videoDlg->setStreamIP(m_DlgGDDCSet->m_playURL1);
     videoDlg->setPushStreamIP(m_DlgGDDCSet->m_pushURL);
+    qDebug() << "DLG:" << m_DlgGDDCSet->m_pushURL;
     videoDlg->setPushStream(true);
     m_DlgGDDCSet->setPushStreamText("停止推送");
 
diff --git a/Src/Video/cffmpeg_decode.cpp b/Src/Video/cffmpeg_decode.cpp
index fcef312..340a31a 100644
--- a/Src/Video/cffmpeg_decode.cpp
+++ b/Src/Video/cffmpeg_decode.cpp
@@ -85,10 +85,10 @@ bool Cffmpeg_decode::open_input_file() {
   // 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", "ultrafast", 0); //   faster
-  av_dict_set(&avdic, "threads", "auto", 0);     // 自动开启线程数
+  // av_dict_set(&avdic, "threads", "auto", 0);     // 自动开启线程数
   // 设置最大重试时间为1s,解决avformat_open_input打开空流时间过长问题
   av_dict_set(&avdic, "max_interleave_delta", "1000000", 0);
 
@@ -154,6 +154,7 @@ bool Cffmpeg_decode::open_input_file() {
   // 设置加速解码
   decoderCtx->lowres = decoder->max_lowres;
   decoderCtx->flags2 |= AV_CODEC_FLAG2_FAST;
+  decoderCtx->thread_count = 8;
   // 打开解码器
   if (avcodec_open2(decoderCtx, decoder, NULL) < 0) {
     printf("Cannot open codec.\n");
@@ -325,10 +326,10 @@ void Cffmpeg_decode::run() {
             double elapsed_system_time = av_gettime() - first_frame_system_time;
             // 计算需要等待的时间(us)
             double wait_time = elapsed_pts_time - elapsed_system_time;
-            qDebug() << "pull stream sleep time:"
-                     << QString::number(wait_time / 1000.0);
-            if (wait_time > 0 && bPushStreamFlag) {
-              av_usleep(wait_time); // 延时以同步 PTS
+            // qDebug() << "pull stream sleep time:"
+            //          << QString::number(wait_time / 1000.0);
+            if (wait_time > 0 && bPushStreamFlag) { //
+              av_usleep(wait_time);                 // 延时以同步 PTS
               // sleepMsec(wait_time);
             }
             // 更新 previous_pts_time 为当前帧的 PTS
diff --git a/Src/Video/ffmpegpushstream.cpp b/Src/Video/ffmpegpushstream.cpp
index f750042..8b99584 100644
--- a/Src/Video/ffmpegpushstream.cpp
+++ b/Src/Video/ffmpegpushstream.cpp
@@ -25,6 +25,7 @@ int FFmpegPushStream::openNetworkStream(AVFormatContext *inputFormatCtx) {
     qDebug() << "Could not create output context.";
     return -1;
   }
+
   // 复制流信息
   for (unsigned int i = 0; i < inputFormatCtx->nb_streams; ++i) {
     // AVStream *stream = inputFormatCtx->streams[i];
@@ -47,6 +48,24 @@ int FFmpegPushStream::openNetworkStream(AVFormatContext *inputFormatCtx) {
       // outputStream->codecpar = inputStream->codecpar;
       outputStream->codecpar->codec_tag = 0;
       // outputStream->time_base.num = 1;
+
+      // if (outputFormatCtx->oformat->flags & AVFMT_GLOBALHEADER)
+      //     c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
+
+      // if (outputFormatCtx->oformat->flags & AVFMT_GLOBALHEADER) {
+      //   outputFormatCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
+      //   if (inputStream->codecpar->extradata_size > 0) {
+      //     int extra_size = (uint64_t)inputStream->codecpar->extradata_size +
+      //                      AV_INPUT_BUFFER_PADDING_SIZE;
+      //     outputStream->codecpar->extradata = (uint8_t
+      //     *)av_malloc(extra_size); memcpy(outputStream->codecpar->extradata,
+      //            inputStream->codecpar->extradata,
+      //            inputStream->codecpar->extradata_size);
+      //     outputStream->codecpar->extradata_size =
+      //         inputStream->codecpar->extradata_size;
+      //   }
+      // }
+
       break;
     }
   }
@@ -66,6 +85,7 @@ int FFmpegPushStream::openNetworkStream(AVFormatContext *inputFormatCtx) {
     qDebug() << "Error occurred when write_header into output file.\n";
     return -1;
   }
+  // sendSPS_PPS(inputFormatCtx, outputFormatCtx);
   mInitStatus = true;
   this->inputFormatCtx = inputFormatCtx;
   // startTime = av_gettime_relative();
@@ -96,6 +116,64 @@ int FFmpegPushStream::reconnect(int ret) {
   }
 }
 
+int FFmpegPushStream::sendSPS_PPS(AVFormatContext *input_format_context,
+                                  AVFormatContext *output_format_context) {
+  for (unsigned int i = 0; i < input_format_context->nb_streams; i++) {
+    AVStream *in_stream = input_format_context->streams[i];
+
+    if (in_stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+      AVStream *out_stream = output_format_context->streams[0];
+      // Send SPS and PPS for video
+      AVCodecContext *codec_context = avcodec_alloc_context3(nullptr);
+      if (!codec_context) {
+        qDebug() << "Could not allocate video codec context.";
+        return -1;
+      }
+
+      if (avcodec_parameters_to_context(codec_context, in_stream->codecpar) <
+          0) {
+        qDebug() << "Failed to copy codec parameters to context.";
+        return -1;
+      }
+
+      AVPacket sps_pps_packet;
+      av_init_packet(&sps_pps_packet);
+      sps_pps_packet.data = nullptr;
+      sps_pps_packet.size = 0;
+
+      if (avcodec_send_frame(codec_context, nullptr) < 0) {
+        qDebug() << "Failed to send a frame for SPS/PPS extraction.";
+        return -1;
+      }
+
+      while (avcodec_receive_packet(codec_context, &sps_pps_packet) == 0) {
+        if (sps_pps_packet.pts == AV_NOPTS_VALUE) {
+          sps_pps_packet.pts =
+              av_rescale_q_rnd(sps_pps_packet.dts, codec_context->time_base,
+                               out_stream->time_base, AV_ROUND_NEAR_INF);
+        }
+        sps_pps_packet.dts =
+            av_rescale_q_rnd(sps_pps_packet.dts, codec_context->time_base,
+                             out_stream->time_base, AV_ROUND_NEAR_INF);
+        sps_pps_packet.duration =
+            av_rescale_q(sps_pps_packet.duration, codec_context->time_base,
+                         out_stream->time_base);
+        sps_pps_packet.pos = -1;
+        sps_pps_packet.stream_index = out_stream->index;
+
+        if (av_interleaved_write_frame(output_format_context, &sps_pps_packet) <
+            0) {
+          qDebug() << "Error sending SPS/PPS packet.";
+          return -1;
+        }
+        av_packet_unref(&sps_pps_packet);
+      }
+
+      avcodec_free_context(&codec_context);
+    }
+  }
+}
+
 /**
  * @brief 推流
  * @param pkt: 未解码帧
@@ -149,7 +227,7 @@ int FFmpegPushStream::pushStream(AVPacket *pkt, int frm_cnt, int64_t startTime,
     // qDebug() << "****************PushStream sleep time:"
     //          << QString::number(delay / 1000);
     av_usleep(delay);
-    // sleepMsec(delay);
+    // sleepMsec(40);
   } else {
     // av_packet_unref(pkt);
     // return 1;
@@ -181,7 +259,7 @@ int FFmpegPushStream::pushStream(AVPacket *pkt, int frm_cnt, int64_t startTime,
   int ret = av_interleaved_write_frame(outputFormatCtx, pkt);
   if (ret < 0) {
     if (ret == -10053) {
-      qDebug() << "网络不稳定";
+      // qDebug() << "网络不稳定";
     }
     // if (ret == AVERROR(EPIPE) || ret == AVERROR(ECONNRESET)) {
     //   qDebug() << "网络不稳定1";
diff --git a/Src/Video/ffmpegpushstream.h b/Src/Video/ffmpegpushstream.h
index 0326e9e..9351c91 100644
--- a/Src/Video/ffmpegpushstream.h
+++ b/Src/Video/ffmpegpushstream.h
@@ -34,6 +34,8 @@ public slots:
 
 private:
   int reconnect(int ret);
+  int sendSPS_PPS(AVFormatContext *input_format_context,
+                  AVFormatContext *output_format_context);
 };
 
 #endif // FFMPEGPUSHSTREAM_H
diff --git a/Src/Video/ffmpegvideodlg.cpp b/Src/Video/ffmpegvideodlg.cpp
index f12c2ad..e8b579f 100644
--- a/Src/Video/ffmpegvideodlg.cpp
+++ b/Src/Video/ffmpegvideodlg.cpp
@@ -146,8 +146,8 @@ void ffmpegvideoDlg::setPushStream(bool bPush) {
     // 创建推流任务对象
     if (ffmpegPushStream == nullptr) {
       ffmpegPushStream = new FFmpegPushStream;
-      ffmpegPushStream->setRemoteIP(m_pushStreamIP); // 设置推流地址
     }
+    ffmpegPushStream->setRemoteIP(m_pushStreamIP); // 设置推流地址
     // 推流线程开启
     if (pushStreamThread == nullptr) {
       pushStreamThread = new QThread;
diff --git a/global.cpp b/global.cpp
index 7b5f66b..8c952b5 100644
--- a/global.cpp
+++ b/global.cpp
@@ -2,7 +2,7 @@
 
 global::global() {}
 
-QString g_SoftwareVersion = "版本号:V1.0.2.2_20241111";
+QString g_SoftwareVersion = "版本号:V1.0.2.3_20241114";
 
 QColor g_themeColor(51, 51, 51);
 QString g_PushBtnStyle = /**正常情况下样式**/
diff --git a/mainwindow.cpp b/mainwindow.cpp
index 5fd039a..9896f54 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -370,4 +370,5 @@ void MainWindow::initUAVIDMap() {
   for (int i = 8; i < 13; ++i) {
     g_mapAppName[i] = "jsyj";
   }
+  g_mapAppName[99] = "testyj";
 }