#![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, pub width: i32, pub height: i32, pub pixfmt: AVPixelFormat, } pub struct Decoder { pub ctx: DecodeContext, } impl Decoder { pub fn new(ctx: DecodeContext) -> Result { let _ = ctx; Err(()) } pub fn decode(&mut self, _data: &[u8]) -> Result<&mut Vec, 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, 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 { 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) -> CodecInfos { let mut h264: Option = None; let mut h265: Option = None; let mut vp8: Option = None; let mut vp9: Option = None; let mut av1: Option = 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, pub h265: Option, pub vp8: Option, pub vp9: Option, pub av1: Option, } impl CodecInfos { pub fn into_vec(self) -> Vec { 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 { match serde_json::to_string_pretty(self) { Ok(s) => Ok(s), Err(_) => Err(()), } } pub fn deserialize(s: &str) -> Result { 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, Vec, i32), ()> { let mut linesize = Vec::::new(); linesize.resize(AV_NUM_DATA_POINTERS as _, 0); let mut offset = Vec::::new(); offset.resize(AV_NUM_DATA_POINTERS as _, 0); let mut length = Vec::::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(()) }