72 lines
2.6 KiB
C++
72 lines
2.6 KiB
C++
#include "EncoderFactory.h"
|
||
#include "common/config.h"
|
||
#include "common/logger.h"
|
||
#include "X264Encoder.h"
|
||
// 合规守护:DISABLE_FFMPEG_FOR_TEST=1 时硬编实现整体移出工程,仅保留 x264 软编路径
|
||
#if defined(_WIN64) && !DISABLE_FFMPEG_FOR_TEST
|
||
#include "CFFmpegH264Encoder.h"
|
||
#include "CFFmpegAV1Encoder.h"
|
||
#endif
|
||
|
||
namespace {
|
||
// 与 ScreenCapture::BitRateToCRF 同步:码率越高 CRF 越低(质量更好)。
|
||
// 仅 x264 软编路径用,硬编路径直接用 bitrate_kbps 走 CBR。
|
||
int BitRateToCRF(int bitRate) {
|
||
if (bitRate <= 0) return 23;
|
||
if (bitRate >= 3000) return 20;
|
||
if (bitRate >= 2000) return 20 + (3000 - bitRate) * 3 / 1000;
|
||
if (bitRate >= 800) return 23 + (2000 - bitRate) * 7 / 1200;
|
||
return 32;
|
||
}
|
||
}
|
||
|
||
std::unique_ptr<VideoEncoderBase> CreateEncoder(const EncoderRequest& req) {
|
||
EncoderParams p;
|
||
p.width = req.width;
|
||
p.height = req.height;
|
||
p.fps = req.fps;
|
||
|
||
#if defined(_WIN64) && !DISABLE_FFMPEG_FOR_TEST
|
||
// AV1 硬编路径(仅当客户端声明支持 AV1 解码)
|
||
// 硬件门槛高:仅 RTX 40+ / RX 7000+ / Intel Arc 才有 av1 encoder ASIC;
|
||
// 没合适硬件时 open() 全部失败,自然 fall through 到下面 H.264 路径。
|
||
if (req.encodeLevel >= LEVEL_AV1_HARD) {
|
||
auto enc = std::make_unique<CFFmpegAV1Encoder>();
|
||
p.rc = RateControl::BITRATE;
|
||
p.bitrate_kbps = req.bitrate_kbps;
|
||
if (enc->open(p)) {
|
||
Mprintf("=> encoder: %s (HW AV1, bitrate=%dk)\n", enc->backendName(), req.bitrate_kbps);
|
||
return enc;
|
||
}
|
||
Mprintf("=> all AV1 HW backends failed, falling back to H.264\n");
|
||
}
|
||
|
||
|
||
// H.264 硬编:CFFmpegH264Encoder 内部按 nvenc/qsv/amf/mf 顺序探
|
||
if (req.encodeLevel >= LEVEL_H264_HARD) {
|
||
auto enc = std::make_unique<CFFmpegH264Encoder>();
|
||
p.rc = RateControl::BITRATE;
|
||
p.bitrate_kbps = req.bitrate_kbps;
|
||
if (enc->open(p)) {
|
||
Mprintf("=> encoder: %s (HW, bitrate=%dk)\n", enc->backendName(), req.bitrate_kbps);
|
||
return enc;
|
||
}
|
||
Mprintf("=> all H.264 HW backends failed, falling back to x264\n");
|
||
}
|
||
#endif
|
||
|
||
// x264 软编兜底(无硬件 / 全失败 / 虚拟机 / 远程桌面会话场景)
|
||
if (req.encodeLevel >= LEVEL_H264_SOFT) {
|
||
auto enc = std::make_unique<CX264Encoder>();
|
||
p.rc = RateControl::CRF;
|
||
p.crf = BitRateToCRF(req.bitrate_kbps);
|
||
if (enc->open(p)) {
|
||
Mprintf("=> encoder: %s (SW, crf=%d)\n", enc->backendName(), p.crf);
|
||
return enc;
|
||
}
|
||
}
|
||
|
||
Mprintf("=> ERROR: no encoder could be opened\n");
|
||
return nullptr;
|
||
}
|