#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 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(); 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(); 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(); 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; }