|
|
@@ -2,13 +2,14 @@
|
|
|
#include <QDebug>
|
|
|
#include <QThread>
|
|
|
#include "threadpool.h"
|
|
|
+#include "low_latency_config.h"
|
|
|
|
|
|
using AVTool::Decoder;
|
|
|
|
|
|
Decoder::Decoder()
|
|
|
: m_fmtCtx(nullptr)
|
|
|
- , m_maxFrameQueueSize(6)
|
|
|
- , m_maxPacketQueueSize(12)
|
|
|
+ , m_maxFrameQueueSize(LowLatencyConfig::BALANCED_FRAME_QUEUE_SIZE) // 使用配置文件中的帧队列大小
|
|
|
+ , m_maxPacketQueueSize(LowLatencyConfig::BALANCED_PACKET_QUEUE_SIZE) // 使用配置文件中的包队列大小
|
|
|
, m_audioIndex(-1)
|
|
|
, m_videoIndex(-1)
|
|
|
, m_exit(0)
|
|
|
@@ -34,11 +35,12 @@ AVTool::MediaInfo* Decoder::detectMediaInfo(const QString& url)
|
|
|
|
|
|
//用于获取流时长
|
|
|
AVDictionary* formatOpts = nullptr;
|
|
|
- av_dict_set(&formatOpts, "probesize", "32", 0);
|
|
|
- av_dict_set(&formatOpts, "analyzeduration", "0", 0);
|
|
|
- av_dict_set(&formatOpts, "rtsp_transport", "tcp", 0);
|
|
|
- av_dict_set(&formatOpts, "fflags", "nobuffer", 0);
|
|
|
- av_dict_set(&formatOpts, "max_delay", "0", 0);
|
|
|
+ av_dict_set(&formatOpts, "probesize", LowLatencyConfig::PROBE_SIZE, 0); // 使用配置文件中的探测大小
|
|
|
+ av_dict_set(&formatOpts, "analyzeduration", LowLatencyConfig::ANALYZE_DURATION, 0); // 使用配置文件中的分析时长
|
|
|
+ av_dict_set(&formatOpts, "rtsp_transport", LowLatencyConfig::RTSP_TRANSPORT, 0);
|
|
|
+ av_dict_set(&formatOpts, "fflags", LowLatencyConfig::FFLAGS, 0); // 使用配置文件中的标志
|
|
|
+ av_dict_set(&formatOpts, "max_delay", LowLatencyConfig::MAX_DELAY, 0); // 使用配置文件中的最大延迟
|
|
|
+ av_dict_set(&formatOpts, "buffer_size", LowLatencyConfig::BUFFER_SIZE, 0); // 使用配置文件中的缓冲区大小
|
|
|
|
|
|
ret = avformat_open_input(&fmtCtx, url.toUtf8().constData(), nullptr, &formatOpts);
|
|
|
if (ret < 0) {
|
|
|
@@ -50,10 +52,12 @@ AVTool::MediaInfo* Decoder::detectMediaInfo(const QString& url)
|
|
|
return Q_NULLPTR;
|
|
|
}
|
|
|
|
|
|
- // 低延迟:关闭内部缓冲
|
|
|
+ // 低延迟:关闭内部缓冲,但保持稳定性
|
|
|
if (fmtCtx) {
|
|
|
fmtCtx->flags |= AVFMT_FLAG_NOBUFFER;
|
|
|
- fmtCtx->max_delay = 0;
|
|
|
+ fmtCtx->max_delay = 500000; // 500ms,类似VLC
|
|
|
+ fmtCtx->probesize = 32768; // 32KB
|
|
|
+ fmtCtx->max_analyze_duration = 1000000; // 1秒
|
|
|
}
|
|
|
|
|
|
ret = avformat_find_stream_info(fmtCtx, nullptr);
|
|
|
@@ -243,11 +247,11 @@ int Decoder::decode(const QString& url)
|
|
|
|
|
|
//用于获取流时长
|
|
|
AVDictionary* formatOpts = nullptr;
|
|
|
- av_dict_set(&formatOpts, "probesize", "32", 0);
|
|
|
- av_dict_set(&formatOpts, "analyzeduration", "0", 0);
|
|
|
- av_dict_set(&formatOpts, "rtsp_transport", "tcp", 0);
|
|
|
- av_dict_set(&formatOpts, "fflags", "nobuffer", 0);
|
|
|
- av_dict_set(&formatOpts, "max_delay", "0", 0);
|
|
|
+ av_dict_set(&formatOpts, "probesize", LowLatencyConfig::PROBE_SIZE, 0);
|
|
|
+ av_dict_set(&formatOpts, "analyzeduration", LowLatencyConfig::ANALYZE_DURATION, 0);
|
|
|
+ av_dict_set(&formatOpts, "rtsp_transport", LowLatencyConfig::RTSP_TRANSPORT, 0);
|
|
|
+ av_dict_set(&formatOpts, "fflags", LowLatencyConfig::FFLAGS, 0);
|
|
|
+ av_dict_set(&formatOpts, "max_delay", LowLatencyConfig::MAX_DELAY, 0);
|
|
|
|
|
|
ret = avformat_open_input(&m_fmtCtx, url.toUtf8().constData(), nullptr, &formatOpts);
|
|
|
if (ret < 0) {
|
|
|
@@ -318,13 +322,19 @@ int Decoder::decode(const QString& url)
|
|
|
}
|
|
|
m_audioPktDecoder.codecCtx->codec_id = audioCodec->id;
|
|
|
|
|
|
- // 低延迟解码设置(音频)
|
|
|
+ // 平衡的解码设置(音频)
|
|
|
m_audioPktDecoder.codecCtx->flags |= AV_CODEC_FLAG_LOW_DELAY;
|
|
|
m_audioPktDecoder.codecCtx->flags2 |= AV_CODEC_FLAG2_FAST;
|
|
|
+ m_audioPktDecoder.codecCtx->thread_count = LowLatencyConfig::DECODER_THREAD_COUNT; // 使用配置文件中的线程数
|
|
|
m_audioPktDecoder.codecCtx->thread_type = FF_THREAD_SLICE;
|
|
|
- m_audioPktDecoder.codecCtx->thread_count = 1;
|
|
|
-
|
|
|
- ret = avcodec_open2(m_audioPktDecoder.codecCtx, audioCodec, nullptr);
|
|
|
+
|
|
|
+ // H.264平衡优化
|
|
|
+ AVDictionary* codecOpts = nullptr;
|
|
|
+ av_dict_set(&codecOpts, "preset", LowLatencyConfig::CODEC_PRESET, 0); // 使用配置文件中的预设
|
|
|
+ av_dict_set(&codecOpts, "tune", LowLatencyConfig::CODEC_TUNE, 0);
|
|
|
+
|
|
|
+ ret = avcodec_open2(m_audioPktDecoder.codecCtx, audioCodec, &codecOpts);
|
|
|
+ av_dict_free(&codecOpts);
|
|
|
if (ret < 0) {
|
|
|
av_strerror(ret, m_errBuf, sizeof(m_errBuf));
|
|
|
qDebug() << "error info_avcodec_open2:" << m_errBuf;
|
|
|
@@ -356,13 +366,19 @@ int Decoder::decode(const QString& url)
|
|
|
}
|
|
|
m_videoPktDecoder.codecCtx->codec_id = videoCodec->id;
|
|
|
|
|
|
- // 低延迟解码设置(视频)
|
|
|
+ // 平衡的解码设置(视频)
|
|
|
m_videoPktDecoder.codecCtx->flags |= AV_CODEC_FLAG_LOW_DELAY;
|
|
|
m_videoPktDecoder.codecCtx->flags2 |= AV_CODEC_FLAG2_FAST;
|
|
|
+ m_videoPktDecoder.codecCtx->thread_count = LowLatencyConfig::DECODER_THREAD_COUNT; // 使用配置文件中的线程数
|
|
|
m_videoPktDecoder.codecCtx->thread_type = FF_THREAD_SLICE;
|
|
|
- m_videoPktDecoder.codecCtx->thread_count = 1;
|
|
|
-
|
|
|
- ret = avcodec_open2(m_videoPktDecoder.codecCtx, videoCodec, nullptr);
|
|
|
+
|
|
|
+ // H.264平衡优化
|
|
|
+ AVDictionary* videoCodecOpts = nullptr;
|
|
|
+ av_dict_set(&videoCodecOpts, "preset", LowLatencyConfig::CODEC_PRESET, 0); // 使用配置文件中的预设
|
|
|
+ av_dict_set(&videoCodecOpts, "tune", LowLatencyConfig::CODEC_TUNE, 0);
|
|
|
+
|
|
|
+ ret = avcodec_open2(m_videoPktDecoder.codecCtx, videoCodec, &videoCodecOpts);
|
|
|
+ av_dict_free(&videoCodecOpts);
|
|
|
if (ret < 0) {
|
|
|
av_strerror(ret, m_errBuf, sizeof(m_errBuf));
|
|
|
qDebug() << "error info_avcodec_open2:" << m_errBuf;
|