Feature: Implement H.264 and AV1 hardware encoding for remote control
Remark: Need to update FFmpeg static libraries to take effort
This commit is contained in:
71
client/EncoderFactory.cpp
Normal file
71
client/EncoderFactory.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user