mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-04-02 18:06:34 +08:00
264 lines
7.2 KiB
Rust
264 lines
7.2 KiB
Rust
#![allow(non_upper_case_globals)]
|
|
#![allow(non_camel_case_types)]
|
|
#![allow(non_snake_case)]
|
|
|
|
use crate::common::DataFormat::{self, *};
|
|
use crate::ffmpeg::{
|
|
AVHWDeviceType::{self, *},
|
|
};
|
|
use serde_derive::{Deserialize, Serialize};
|
|
use std::ffi::c_int;
|
|
|
|
include!(concat!(env!("OUT_DIR"), "/ffmpeg_ram_ffi.rs"));
|
|
|
|
#[cfg(any(target_arch = "aarch64", target_arch = "arm", feature = "rkmpp"))]
|
|
pub mod decode;
|
|
|
|
// Provide a small stub on non-ARM builds so dependents can still compile, but decoder
|
|
// construction will fail (since the C++ RKMPP decoder isn't built/linked).
|
|
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm", feature = "rkmpp")))]
|
|
pub mod decode {
|
|
use crate::ffmpeg::AVPixelFormat;
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub struct DecodeContext {
|
|
pub name: String,
|
|
pub width: i32,
|
|
pub height: i32,
|
|
pub sw_pixfmt: AVPixelFormat,
|
|
pub thread_count: i32,
|
|
}
|
|
|
|
pub struct DecodeFrame {
|
|
pub data: Vec<u8>,
|
|
pub width: i32,
|
|
pub height: i32,
|
|
pub pixfmt: AVPixelFormat,
|
|
}
|
|
|
|
pub struct Decoder {
|
|
pub ctx: DecodeContext,
|
|
}
|
|
|
|
impl Decoder {
|
|
pub fn new(ctx: DecodeContext) -> Result<Self, ()> {
|
|
let _ = ctx;
|
|
Err(())
|
|
}
|
|
|
|
pub fn decode(&mut self, _data: &[u8]) -> Result<&mut Vec<DecodeFrame>, i32> {
|
|
Err(-1)
|
|
}
|
|
}
|
|
}
|
|
|
|
pub mod encode;
|
|
|
|
pub enum Priority {
|
|
Best = 0,
|
|
Good = 1,
|
|
Normal = 2,
|
|
Soft = 3,
|
|
Bad = 4,
|
|
}
|
|
|
|
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
|
|
pub struct CodecInfo {
|
|
pub name: String,
|
|
#[serde(skip)]
|
|
pub mc_name: Option<String>,
|
|
pub format: DataFormat,
|
|
pub priority: i32,
|
|
pub hwdevice: AVHWDeviceType,
|
|
}
|
|
|
|
impl Default for CodecInfo {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: Default::default(),
|
|
mc_name: Default::default(),
|
|
format: DataFormat::H264,
|
|
priority: Default::default(),
|
|
hwdevice: AVHWDeviceType::AV_HWDEVICE_TYPE_NONE,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CodecInfo {
|
|
pub fn software(format: DataFormat) -> Option<Self> {
|
|
match format {
|
|
H264 => Some(CodecInfo {
|
|
name: "libx264".to_owned(),
|
|
mc_name: Default::default(),
|
|
format: H264,
|
|
hwdevice: AV_HWDEVICE_TYPE_NONE,
|
|
priority: Priority::Soft as _,
|
|
}),
|
|
H265 => Some(CodecInfo {
|
|
name: "libx265".to_owned(),
|
|
mc_name: Default::default(),
|
|
format: H265,
|
|
hwdevice: AV_HWDEVICE_TYPE_NONE,
|
|
priority: Priority::Soft as _,
|
|
}),
|
|
VP8 => Some(CodecInfo {
|
|
name: "libvpx".to_owned(),
|
|
mc_name: Default::default(),
|
|
format: VP8,
|
|
hwdevice: AV_HWDEVICE_TYPE_NONE,
|
|
priority: Priority::Soft as _,
|
|
}),
|
|
VP9 => Some(CodecInfo {
|
|
name: "libvpx-vp9".to_owned(),
|
|
mc_name: Default::default(),
|
|
format: VP9,
|
|
hwdevice: AV_HWDEVICE_TYPE_NONE,
|
|
priority: Priority::Soft as _,
|
|
}),
|
|
AV1 => None,
|
|
}
|
|
}
|
|
|
|
pub fn prioritized(coders: Vec<CodecInfo>) -> CodecInfos {
|
|
let mut h264: Option<CodecInfo> = None;
|
|
let mut h265: Option<CodecInfo> = None;
|
|
let mut vp8: Option<CodecInfo> = None;
|
|
let mut vp9: Option<CodecInfo> = None;
|
|
let mut av1: Option<CodecInfo> = None;
|
|
|
|
for coder in coders {
|
|
match coder.format {
|
|
DataFormat::H264 => match &h264 {
|
|
Some(old) => {
|
|
if old.priority > coder.priority {
|
|
h264 = Some(coder)
|
|
}
|
|
}
|
|
None => h264 = Some(coder),
|
|
},
|
|
DataFormat::H265 => match &h265 {
|
|
Some(old) => {
|
|
if old.priority > coder.priority {
|
|
h265 = Some(coder)
|
|
}
|
|
}
|
|
None => h265 = Some(coder),
|
|
},
|
|
DataFormat::VP8 => match &vp8 {
|
|
Some(old) => {
|
|
if old.priority > coder.priority {
|
|
vp8 = Some(coder)
|
|
}
|
|
}
|
|
None => vp8 = Some(coder),
|
|
},
|
|
DataFormat::VP9 => match &vp9 {
|
|
Some(old) => {
|
|
if old.priority > coder.priority {
|
|
vp9 = Some(coder)
|
|
}
|
|
}
|
|
None => vp9 = Some(coder),
|
|
},
|
|
DataFormat::AV1 => match &av1 {
|
|
Some(old) => {
|
|
if old.priority > coder.priority {
|
|
av1 = Some(coder)
|
|
}
|
|
}
|
|
None => av1 = Some(coder),
|
|
},
|
|
}
|
|
}
|
|
CodecInfos {
|
|
h264,
|
|
h265,
|
|
vp8,
|
|
vp9,
|
|
av1,
|
|
}
|
|
}
|
|
|
|
pub fn soft() -> CodecInfos {
|
|
CodecInfos {
|
|
h264: CodecInfo::software(H264),
|
|
h265: CodecInfo::software(H265),
|
|
vp8: CodecInfo::software(VP8),
|
|
vp9: CodecInfo::software(VP9),
|
|
av1: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
|
|
pub struct CodecInfos {
|
|
pub h264: Option<CodecInfo>,
|
|
pub h265: Option<CodecInfo>,
|
|
pub vp8: Option<CodecInfo>,
|
|
pub vp9: Option<CodecInfo>,
|
|
pub av1: Option<CodecInfo>,
|
|
}
|
|
|
|
impl CodecInfos {
|
|
pub fn into_vec(self) -> Vec<CodecInfo> {
|
|
let mut codecs = Vec::new();
|
|
if let Some(codec) = self.h264 {
|
|
codecs.push(codec);
|
|
}
|
|
if let Some(codec) = self.h265 {
|
|
codecs.push(codec);
|
|
}
|
|
if let Some(codec) = self.vp8 {
|
|
codecs.push(codec);
|
|
}
|
|
if let Some(codec) = self.vp9 {
|
|
codecs.push(codec);
|
|
}
|
|
codecs
|
|
}
|
|
|
|
pub fn serialize(&self) -> Result<String, ()> {
|
|
match serde_json::to_string_pretty(self) {
|
|
Ok(s) => Ok(s),
|
|
Err(_) => Err(()),
|
|
}
|
|
}
|
|
|
|
pub fn deserialize(s: &str) -> Result<Self, ()> {
|
|
match serde_json::from_str(s) {
|
|
Ok(c) => Ok(c),
|
|
Err(_) => Err(()),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn ffmpeg_linesize_offset_length(
|
|
pixfmt: i32,
|
|
width: usize,
|
|
height: usize,
|
|
align: usize,
|
|
) -> Result<(Vec<i32>, Vec<i32>, i32), ()> {
|
|
let mut linesize = Vec::<c_int>::new();
|
|
linesize.resize(AV_NUM_DATA_POINTERS as _, 0);
|
|
let mut offset = Vec::<c_int>::new();
|
|
offset.resize(AV_NUM_DATA_POINTERS as _, 0);
|
|
let mut length = Vec::<c_int>::new();
|
|
length.resize(1, 0);
|
|
unsafe {
|
|
if ffmpeg_ram_get_linesize_offset_length(
|
|
pixfmt,
|
|
width as _,
|
|
height as _,
|
|
align as _,
|
|
linesize.as_mut_ptr(),
|
|
offset.as_mut_ptr(),
|
|
length.as_mut_ptr(),
|
|
) == 0
|
|
{
|
|
return Ok((linesize, offset, length[0]));
|
|
}
|
|
}
|
|
|
|
Err(())
|
|
}
|