mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-01-29 09:01:54 +08:00
refactor(hwcodec): 简化 hwcodec 库以适配 IP-KVM 场景
移除 IP-KVM 场景不需要的功能模块: - 移除 VRAM 模块 (GPU 显存直接编解码) - 移除 Mux 模块 (视频混流) - 移除 macOS/Android 平台支持 - 移除外部 SDK 依赖 (~9MB) - 移除开发工具和示例程序 简化解码器为仅支持 MJPEG (采集卡输出格式) 简化 NVIDIA 检测代码 (使用 dlopen 替代 SDK) 更新版本号至 0.8.0 更新相关技术文档
This commit is contained in:
@@ -35,7 +35,7 @@
|
||||
每个检测到的硬件编码器都会进行实际编码测试:
|
||||
|
||||
```rust
|
||||
// libs/hwcodec/src/ffmpeg_ram/encode.rs:358-450
|
||||
// libs/hwcodec/src/ffmpeg_ram/encode.rs
|
||||
|
||||
// 生成测试用 YUV 数据
|
||||
let yuv = Encoder::dummy_yuv(ctx.clone())?;
|
||||
@@ -47,7 +47,7 @@ match Encoder::new(c) {
|
||||
match encoder.encode(&yuv, 0) {
|
||||
Ok(frames) => {
|
||||
let elapsed = start.elapsed().as_millis();
|
||||
// 验证: 必须产生 1 帧且为关键帧,且在 1 秒内完成
|
||||
// 验证: 必须产生 1 帧且为关键帧,且在超时时间内完成
|
||||
if frames.len() == 1 && frames[0].key == 1
|
||||
&& elapsed < TEST_TIMEOUT_MS {
|
||||
res.push(codec);
|
||||
@@ -64,27 +64,35 @@ match Encoder::new(c) {
|
||||
|
||||
### 2.1 检测机制 (Linux)
|
||||
|
||||
使用简化的动态库检测方法,无需 CUDA SDK 依赖:
|
||||
|
||||
```cpp
|
||||
// libs/hwcodec/cpp/common/platform/linux/linux.cpp:57-73
|
||||
// libs/hwcodec/cpp/common/platform/linux/linux.cpp
|
||||
|
||||
int linux_support_nv() {
|
||||
CudaFunctions *cuda_dl = NULL;
|
||||
NvencFunctions *nvenc_dl = NULL;
|
||||
CuvidFunctions *cvdl = NULL;
|
||||
// 检测 CUDA 运行时库
|
||||
void *handle = dlopen("libcuda.so.1", RTLD_LAZY);
|
||||
if (!handle) {
|
||||
handle = dlopen("libcuda.so", RTLD_LAZY);
|
||||
}
|
||||
if (!handle) {
|
||||
LOG_TRACE("NVIDIA: libcuda.so not found");
|
||||
return -1;
|
||||
}
|
||||
dlclose(handle);
|
||||
|
||||
// 加载 CUDA 动态库
|
||||
if (cuda_load_functions(&cuda_dl, NULL) < 0)
|
||||
throw "cuda_load_functions failed";
|
||||
// 检测 NVENC 编码库
|
||||
handle = dlopen("libnvidia-encode.so.1", RTLD_LAZY);
|
||||
if (!handle) {
|
||||
handle = dlopen("libnvidia-encode.so", RTLD_LAZY);
|
||||
}
|
||||
if (!handle) {
|
||||
LOG_TRACE("NVIDIA: libnvidia-encode.so not found");
|
||||
return -1;
|
||||
}
|
||||
dlclose(handle);
|
||||
|
||||
// 加载 NVENC 动态库
|
||||
if (nvenc_load_functions(&nvenc_dl, NULL) < 0)
|
||||
throw "nvenc_load_functions failed";
|
||||
|
||||
// 加载 CUVID (解码) 动态库
|
||||
if (cuvid_load_functions(&cvdl, NULL) < 0)
|
||||
throw "cuvid_load_functions failed";
|
||||
|
||||
// 全部成功则支持 NVIDIA 硬件加速
|
||||
LOG_TRACE("NVIDIA: driver support detected");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
@@ -127,16 +135,15 @@ av_opt_set(priv_data, "rc", "cbr", 0); // 或 "vbr"
|
||||
|
||||
### 2.4 依赖库
|
||||
|
||||
- `libcuda.so` - CUDA 运行时
|
||||
- `libnvidia-encode.so` - NVENC 编码器
|
||||
- `libnvcuvid.so` - NVDEC 解码器
|
||||
- `libcuda.so` / `libcuda.so.1` - CUDA 运行时
|
||||
- `libnvidia-encode.so` / `libnvidia-encode.so.1` - NVENC 编码器
|
||||
|
||||
## 3. AMD AMF
|
||||
|
||||
### 3.1 检测机制 (Linux)
|
||||
|
||||
```cpp
|
||||
// libs/hwcodec/cpp/common/platform/linux/linux.cpp:75-91
|
||||
// libs/hwcodec/cpp/common/platform/linux/linux.cpp
|
||||
|
||||
int linux_support_amd() {
|
||||
#if defined(__x86_64__) || defined(__aarch64__)
|
||||
@@ -186,26 +193,12 @@ av_opt_set(priv_data, "rc", "vbr_latency", 0); // 低延迟 VBR
|
||||
|
||||
- `libamfrt64.so.1` (64位) 或 `libamfrt32.so.1` (32位)
|
||||
|
||||
### 3.4 外部 SDK
|
||||
|
||||
```
|
||||
externals/AMF_v1.4.35/
|
||||
├── amf/
|
||||
│ ├── public/common/ # 公共代码
|
||||
│ │ ├── AMFFactory.cpp
|
||||
│ │ ├── Thread.cpp
|
||||
│ │ └── TraceAdapter.cpp
|
||||
│ └── public/include/ # 头文件
|
||||
│ ├── components/ # 组件定义
|
||||
│ └── core/ # 核心定义
|
||||
```
|
||||
|
||||
## 4. Intel QSV/MFX
|
||||
|
||||
### 4.1 检测机制 (Linux)
|
||||
|
||||
```cpp
|
||||
// libs/hwcodec/cpp/common/platform/linux/linux.cpp:93-107
|
||||
// libs/hwcodec/cpp/common/platform/linux/linux.cpp
|
||||
|
||||
int linux_support_intel() {
|
||||
const char *libs[] = {
|
||||
@@ -262,18 +255,7 @@ c->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL;
|
||||
### 4.3 限制
|
||||
|
||||
- QSV 不支持 `YUV420P` 像素格式,必须使用 `NV12`
|
||||
- 仅在 Windows 平台完全支持
|
||||
|
||||
### 4.4 外部 SDK
|
||||
|
||||
```
|
||||
externals/MediaSDK_22.5.4/
|
||||
├── api/
|
||||
│ ├── include/ # MFX 头文件
|
||||
│ ├── mfx_dispatch/ # MFX 调度器
|
||||
│ └── mediasdk_structures/ # 数据结构
|
||||
└── samples/sample_common/ # 示例代码
|
||||
```
|
||||
- 在 One-KVM 简化版中仅 Windows 平台完全支持
|
||||
|
||||
## 5. VAAPI (Linux)
|
||||
|
||||
@@ -362,17 +344,20 @@ avcodec_receive_packet(c_, pkt_) // 获取编码数据
|
||||
### 6.1 检测机制
|
||||
|
||||
```cpp
|
||||
// libs/hwcodec/cpp/common/platform/linux/linux.cpp:122-137
|
||||
// libs/hwcodec/cpp/common/platform/linux/linux.cpp
|
||||
|
||||
int linux_support_rkmpp() {
|
||||
// 检测 MPP 服务设备
|
||||
if (access("/dev/mpp_service", F_OK) == 0) {
|
||||
LOG_TRACE("RKMPP: Found /dev/mpp_service");
|
||||
return 0; // MPP 可用
|
||||
}
|
||||
// 备用: 检测 RGA 设备
|
||||
if (access("/dev/rga", F_OK) == 0) {
|
||||
LOG_TRACE("RKMPP: Found /dev/rga");
|
||||
return 0; // MPP 可能可用
|
||||
}
|
||||
LOG_TRACE("RKMPP: No Rockchip MPP device found");
|
||||
return -1; // MPP 不可用
|
||||
}
|
||||
```
|
||||
@@ -395,7 +380,7 @@ int linux_support_rkmpp() {
|
||||
### 7.1 检测机制
|
||||
|
||||
```cpp
|
||||
// libs/hwcodec/cpp/common/platform/linux/linux.cpp:139-163
|
||||
// libs/hwcodec/cpp/common/platform/linux/linux.cpp
|
||||
|
||||
int linux_support_v4l2m2m() {
|
||||
const char *m2m_devices[] = {
|
||||
@@ -409,10 +394,12 @@ int linux_support_v4l2m2m() {
|
||||
int fd = open(m2m_devices[i], O_RDWR | O_NONBLOCK);
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
LOG_TRACE("V4L2 M2M: Found device " + m2m_devices[i]);
|
||||
return 0; // V4L2 M2M 可用
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_TRACE("V4L2 M2M: No M2M device found");
|
||||
return -1;
|
||||
}
|
||||
```
|
||||
@@ -429,75 +416,9 @@ int linux_support_v4l2m2m() {
|
||||
- 通用 ARM SoC (Allwinner, Amlogic 等)
|
||||
- 支持 V4L2 M2M API 的设备
|
||||
|
||||
## 8. Apple VideoToolbox
|
||||
## 8. 硬件加速优先级
|
||||
|
||||
### 8.1 检测机制 (macOS)
|
||||
|
||||
```rust
|
||||
// libs/hwcodec/src/common.rs:57-87
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub(crate) fn get_video_toolbox_codec_support() -> (bool, bool, bool, bool) {
|
||||
extern "C" {
|
||||
fn checkVideoToolboxSupport(
|
||||
h264_encode: *mut i32,
|
||||
h265_encode: *mut i32,
|
||||
h264_decode: *mut i32,
|
||||
h265_decode: *mut i32,
|
||||
) -> c_void;
|
||||
}
|
||||
|
||||
let mut h264_encode = 0;
|
||||
let mut h265_encode = 0;
|
||||
let mut h264_decode = 0;
|
||||
let mut h265_decode = 0;
|
||||
|
||||
unsafe {
|
||||
checkVideoToolboxSupport(&mut h264_encode, &mut h265_encode,
|
||||
&mut h264_decode, &mut h265_decode);
|
||||
}
|
||||
|
||||
(h264_encode == 1, h265_encode == 1,
|
||||
h264_decode == 1, h265_decode == 1)
|
||||
}
|
||||
```
|
||||
|
||||
### 8.2 编码配置
|
||||
|
||||
```cpp
|
||||
// libs/hwcodec/cpp/common/util.cpp
|
||||
|
||||
// VideoToolbox 低延迟配置
|
||||
if (name.find("videotoolbox") != std::string::npos) {
|
||||
av_opt_set_int(priv_data, "realtime", 1, 0);
|
||||
av_opt_set_int(priv_data, "prio_speed", 1, 0);
|
||||
}
|
||||
|
||||
// 强制硬件编码
|
||||
if (name.find("videotoolbox") != std::string::npos) {
|
||||
av_opt_set_int(priv_data, "allow_sw", 0, 0);
|
||||
}
|
||||
```
|
||||
|
||||
### 8.3 限制
|
||||
|
||||
- H.264 编码不稳定,已禁用
|
||||
- 仅支持 H.265 编码
|
||||
- 完全支持 H.264/H.265 解码
|
||||
|
||||
### 8.4 依赖框架
|
||||
|
||||
```
|
||||
CoreFoundation
|
||||
CoreVideo
|
||||
CoreMedia
|
||||
VideoToolbox
|
||||
AVFoundation
|
||||
```
|
||||
|
||||
## 9. 硬件加速优先级
|
||||
|
||||
### 9.1 优先级定义
|
||||
### 8.1 优先级定义
|
||||
|
||||
```rust
|
||||
pub enum Priority {
|
||||
@@ -509,7 +430,7 @@ pub enum Priority {
|
||||
}
|
||||
```
|
||||
|
||||
### 9.2 各编码器优先级
|
||||
### 8.2 各编码器优先级
|
||||
|
||||
| 优先级 | 编码器 |
|
||||
|--------|--------|
|
||||
@@ -517,10 +438,10 @@ pub enum Priority {
|
||||
| Good (1) | vaapi, v4l2m2m |
|
||||
| Soft (3) | x264, x265, libvpx |
|
||||
|
||||
### 9.3 选择策略
|
||||
### 8.3 选择策略
|
||||
|
||||
```rust
|
||||
// libs/hwcodec/src/ffmpeg_ram/mod.rs:49-117
|
||||
// libs/hwcodec/src/ffmpeg_ram/mod.rs
|
||||
|
||||
pub fn prioritized(coders: Vec<CodecInfo>) -> CodecInfos {
|
||||
// 对于每种格式,选择优先级最高的编码器
|
||||
@@ -537,9 +458,9 @@ pub fn prioritized(coders: Vec<CodecInfo>) -> CodecInfos {
|
||||
}
|
||||
```
|
||||
|
||||
## 10. 故障排除
|
||||
## 9. 故障排除
|
||||
|
||||
### 10.1 NVIDIA
|
||||
### 9.1 NVIDIA
|
||||
|
||||
```bash
|
||||
# 检查 NVIDIA 驱动
|
||||
@@ -553,7 +474,7 @@ ldconfig -p | grep cuda
|
||||
ldconfig -p | grep nvidia-encode
|
||||
```
|
||||
|
||||
### 10.2 AMD
|
||||
### 9.2 AMD
|
||||
|
||||
```bash
|
||||
# 检查 AMD 驱动
|
||||
@@ -563,7 +484,7 @@ lspci | grep AMD
|
||||
ldconfig -p | grep amf
|
||||
```
|
||||
|
||||
### 10.3 Intel
|
||||
### 9.3 Intel
|
||||
|
||||
```bash
|
||||
# 检查 Intel 驱动
|
||||
@@ -574,7 +495,7 @@ ldconfig -p | grep mfx
|
||||
ldconfig -p | grep vpl
|
||||
```
|
||||
|
||||
### 10.4 VAAPI
|
||||
### 9.4 VAAPI
|
||||
|
||||
```bash
|
||||
# 安装 vainfo
|
||||
@@ -593,7 +514,7 @@ vainfo
|
||||
# ...
|
||||
```
|
||||
|
||||
### 10.5 Rockchip MPP
|
||||
### 9.5 Rockchip MPP
|
||||
|
||||
```bash
|
||||
# 检查 MPP 设备
|
||||
@@ -604,7 +525,7 @@ ls -la /dev/rga
|
||||
ldconfig -p | grep rockchip_mpp
|
||||
```
|
||||
|
||||
### 10.6 V4L2 M2M
|
||||
### 9.6 V4L2 M2M
|
||||
|
||||
```bash
|
||||
# 列出 V4L2 设备
|
||||
@@ -613,3 +534,28 @@ v4l2-ctl --list-devices
|
||||
# 检查设备能力
|
||||
v4l2-ctl -d /dev/video10 --all
|
||||
```
|
||||
|
||||
## 10. 性能优化建议
|
||||
|
||||
### 10.1 编码器选择
|
||||
|
||||
1. **优先使用硬件编码**: NVENC > AMF > QSV > VAAPI > V4L2 M2M > 软件
|
||||
2. **ARM 设备**: 优先检测 RKMPP,其次 V4L2 M2M
|
||||
3. **x86 设备**: 根据 GPU 厂商自动选择
|
||||
|
||||
### 10.2 低延迟配置
|
||||
|
||||
所有硬件编码器都启用了低延迟优化:
|
||||
|
||||
| 编码器 | 配置 |
|
||||
|--------|------|
|
||||
| NVENC | `delay=0` |
|
||||
| AMF | `query_timeout=1000` |
|
||||
| QSV | `async_depth=1` |
|
||||
| VAAPI | `async_depth=1` |
|
||||
| libvpx | `deadline=realtime`, `cpu-used=6` |
|
||||
|
||||
### 10.3 码率控制
|
||||
|
||||
- **实时流**: 推荐 CBR 模式,保证稳定码率
|
||||
- **GOP 大小**: 建议 30-60 帧 (1-2秒),平衡延迟和压缩效率
|
||||
|
||||
Reference in New Issue
Block a user