支持v4l2编码,arm机器原生构建,docker镜像换archlinux,允许初始化时禁用HID

This commit is contained in:
a15355447898a
2026-01-23 17:11:19 +08:00
parent e7d8c93bff
commit 89072ad58d
9 changed files with 107 additions and 50 deletions

View File

@@ -361,10 +361,11 @@ mod ffmpeg {
// RKMPP decode only exists on ARM builds where FFmpeg is compiled with RKMPP support.
// Avoid compiling this file on x86/x64 where `AV_HWDEVICE_TYPE_RKMPP` doesn't exist.
// Also check if RKMPP is available in the current FFmpeg environment to avoid compilation errors on non-Rockchip ARM (e.g. RPi).
let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default();
let enable_rkmpp = matches!(target_arch.as_str(), "aarch64" | "arm")
|| std::env::var_os("CARGO_FEATURE_RKMPP").is_some();
if enable_rkmpp {
let is_arm = matches!(target_arch.as_str(), "aarch64" | "arm");
if is_arm {
builder.file(ffmpeg_ram_dir.join("ffmpeg_ram_decode.cpp"));
} else {
println!(

View File

@@ -107,10 +107,19 @@ int linux_support_rkmpp() {
// Returns 0 if a M2M capable device is found, -1 otherwise
int linux_support_v4l2m2m() {
// Check common V4L2 M2M device paths used by various ARM SoCs
// /dev/video10 - Standard on many SoCs
// /dev/video11 - Standard on many SoCs (often decoder)
// /dev/video0 - Some platforms (like RPi) might use this
// /dev/video1 - Alternate RPi path
// /dev/video2 - Alternate path
// /dev/video32 - Some Allwinner/Rockchip legacy
const char *m2m_devices[] = {
"/dev/video10", // Common M2M encoder device
"/dev/video11", // Common M2M decoder device
"/dev/video0", // Some SoCs use video0 for M2M
"/dev/video10",
"/dev/video11",
"/dev/video0",
"/dev/video1",
"/dev/video2",
"/dev/video32",
};
for (size_t i = 0; i < sizeof(m2m_devices) / sizeof(m2m_devices[0]); i++) {

View File

@@ -10,11 +10,19 @@ extern "C" {
#include "common.h"
#include "common.h"
#define LOG_MODULE "UTIL"
#include "log.h"
#ifndef FF_PROFILE_H264_BASELINE
#define FF_PROFILE_H264_BASELINE 66
#endif
#ifndef FF_PROFILE_H264_HIGH
#define FF_PROFILE_H264_HIGH 100
#endif
#ifndef FF_PROFILE_HEVC_MAIN
#define FF_PROFILE_HEVC_MAIN 1
#endif
namespace {
// Helper function: check if encoder is software H264 (libx264)
@@ -147,11 +155,11 @@ bool set_lantency_free(void *priv_data, const std::string &name) {
// V4L2 M2M hardware encoder - minimize buffer latency
if (name.find("v4l2m2m") != std::string::npos) {
// Minimize number of output buffers for lower latency
if ((ret = av_opt_set_int(priv_data, "num_output_buffers", 2, 0)) < 0) {
if ((ret = av_opt_set_int(priv_data, "num_output_buffers", 4, 0)) < 0) {
LOG_WARN(std::string("v4l2m2m set num_output_buffers failed, ret = ") + av_err2str(ret));
// Not fatal
}
if ((ret = av_opt_set_int(priv_data, "num_capture_buffers", 2, 0)) < 0) {
if ((ret = av_opt_set_int(priv_data, "num_capture_buffers", 4, 0)) < 0) {
LOG_WARN(std::string("v4l2m2m set num_capture_buffers failed, ret = ") + av_err2str(ret));
// Not fatal
}

View File

@@ -55,7 +55,11 @@ public:
callback_ = callback;
if (name_.find("rkmpp") != std::string::npos) {
#ifdef AV_HWDEVICE_TYPE_RKMPP
hw_device_type_ = AV_HWDEVICE_TYPE_RKMPP;
#else
set_last_error("RKMPP support not compiled in FFmpeg");
#endif
}
}

View File

@@ -353,40 +353,43 @@ impl Encoder {
let mut passed = false;
let mut last_err: Option<i32> = None;
let max_attempts = 1;
let max_attempts = if codec.name.contains("v4l2m2m") {
5
} else {
1
};
for attempt in 0..max_attempts {
encoder.request_keyframe();
let pts = (attempt as i64) * 33; // 33ms is an approximation for 30 FPS (1000 / 30)
let start = std::time::Instant::now();
match encoder.encode(&yuv, pts) {
Ok(frames) => {
let elapsed = start.elapsed().as_millis();
if frames.len() == 1 {
if frames[0].key == 1 && elapsed < TEST_TIMEOUT_MS as _ {
debug!(
"Encoder {} test passed on attempt {}",
codec.name,
attempt + 1
);
res.push(codec.clone());
passed = true;
break;
} else {
debug!(
"Encoder {} test failed on attempt {} - key: {}, timeout: {}ms",
codec.name,
attempt + 1,
frames[0].key,
elapsed
);
}
} else {
if frames.len() >= 1 && elapsed < TEST_TIMEOUT_MS as _ {
debug!(
"Encoder {} test failed on attempt {} - wrong frame count: {}",
"Encoder {} test passed on attempt {} (frames: {})",
codec.name,
attempt + 1,
frames.len()
);
res.push(codec.clone());
passed = true;
break;
} else if frames.is_empty() {
debug!(
"Encoder {} test produced no output on attempt {}",
codec.name,
attempt + 1
);
} else {
debug!(
"Encoder {} test failed on attempt {} - frames: {}, timeout: {}ms",
codec.name,
attempt + 1,
frames.len(),
elapsed
);
}
}
Err(err) => {