use crate::error::{MppError, MppResult};
use std::ffi::c_void;
use std::sync::Arc;
pub(crate) const MPP_CTX_ENC: u32 = 1;
pub(crate) const MPP_VIDEO_CODING_AVC: u32 = 7;
#[allow(dead_code)]
pub(crate) const MPP_VIDEO_CODING_HEVC: u32 = 0x1000_0001;
pub(crate) const MPP_FMT_YUV420SP: u32 = 0;
#[allow(dead_code)]
pub(crate) const MPP_FMT_YUV420P: u32 = 1;
pub(crate) const MPP_ENC_SET_CFG: u32 = 0x14_00_01_00;
#[allow(dead_code)]
pub(crate) const MPP_ENC_GET_CFG: u32 = 0x14_00_01_01;
pub(crate) type MppCtx = *mut c_void;
pub(crate) type MppFrame = *mut c_void;
pub(crate) type MppPacket = *mut c_void;
pub(crate) type MppBuffer = *mut c_void;
pub(crate) type MppEncCfg = *mut c_void;
pub(crate) type FnMppApiNoArg = unsafe extern "C" fn(MppCtx) -> i32;
pub(crate) type FnMppApiControl = unsafe extern "C" fn(MppCtx, u32, *mut c_void) -> i32;
pub(crate) type FnMppApiEncodePutFrame = unsafe extern "C" fn(MppCtx, MppFrame) -> i32;
pub(crate) type FnMppApiEncodeGetPacket = unsafe extern "C" fn(MppCtx, *mut MppPacket) -> i32;
pub(crate) type FnMppApiDecodePutPacket = unsafe extern "C" fn(MppCtx, MppPacket) -> i32;
pub(crate) type FnMppApiDecodeGetFrame = unsafe extern "C" fn(MppCtx, *mut MppFrame) -> i32;
#[repr(C)]
pub(crate) struct MppApi {
pub(crate) size: u32,
pub(crate) version: u32,
pub(crate) decode: *const c_void,
pub(crate) decode_put_packet: FnMppApiDecodePutPacket,
pub(crate) decode_get_frame: FnMppApiDecodeGetFrame,
pub(crate) encode: *const c_void,
pub(crate) encode_put_frame: FnMppApiEncodePutFrame,
pub(crate) encode_get_packet: FnMppApiEncodeGetPacket,
pub(crate) reserve0: *const c_void,
pub(crate) poll: *const c_void,
pub(crate) dequeue: *const c_void,
pub(crate) enqueue: *const c_void,
pub(crate) reset: FnMppApiNoArg,
pub(crate) control: FnMppApiControl,
pub(crate) reserved: [*const c_void; 8],
}
const _: () = {
assert!(std::mem::size_of::<MppApi>() == 8 + 12 * 8 + 8 * 8);
};
pub(crate) type FnMppCreate = unsafe extern "C" fn(*mut MppCtx, *mut MppApi) -> i32;
pub(crate) type FnMppInit = unsafe extern "C" fn(MppCtx, u32, u32) -> i32;
pub(crate) type FnMppDestroy = unsafe extern "C" fn(MppCtx) -> i32;
pub(crate) type FnMppFrameInit = unsafe extern "C" fn(*mut MppFrame) -> i32;
pub(crate) type FnMppFrameDeinit = unsafe extern "C" fn(*mut MppFrame) -> i32;
pub(crate) type FnMppFrameSetWidth = unsafe extern "C" fn(MppFrame, u32);
pub(crate) type FnMppFrameSetHeight = unsafe extern "C" fn(MppFrame, u32);
pub(crate) type FnMppFrameSetHorStride = unsafe extern "C" fn(MppFrame, u32);
pub(crate) type FnMppFrameSetVerStride = unsafe extern "C" fn(MppFrame, u32);
pub(crate) type FnMppFrameSetFmt = unsafe extern "C" fn(MppFrame, u32);
pub(crate) type FnMppFrameSetBuffer = unsafe extern "C" fn(MppFrame, MppBuffer);
pub(crate) type FnMppPacketDeinit = unsafe extern "C" fn(*mut MppPacket) -> i32;
pub(crate) type FnMppPacketGetData = unsafe extern "C" fn(MppPacket) -> *mut u8;
pub(crate) type FnMppPacketGetLength = unsafe extern "C" fn(MppPacket) -> usize;
pub(crate) type FnMppEncCfgInit = unsafe extern "C" fn(*mut MppEncCfg) -> i32;
pub(crate) type FnMppEncCfgDeinit = unsafe extern "C" fn(MppEncCfg) -> i32;
pub(crate) type FnMppEncCfgSetS32 = unsafe extern "C" fn(MppEncCfg, *const u8, i32) -> i32;
pub(crate) type FnMppBufferImportFromFd = unsafe extern "C" fn(*mut MppBuffer, i32, usize) -> i32;
pub(crate) type FnMppBufferPutWithCaller = unsafe extern "C" fn(MppBuffer, *const u8) -> i32;
pub(crate) struct MppLib {
pub(crate) handle: *mut c_void,
pub(crate) mpp_create: FnMppCreate,
pub(crate) mpp_init: FnMppInit,
pub(crate) mpp_destroy: FnMppDestroy,
pub(crate) frame_init: FnMppFrameInit,
pub(crate) frame_deinit: FnMppFrameDeinit,
pub(crate) frame_set_width: FnMppFrameSetWidth,
pub(crate) frame_set_height: FnMppFrameSetHeight,
pub(crate) frame_set_hor_stride: FnMppFrameSetHorStride,
pub(crate) frame_set_ver_stride: FnMppFrameSetVerStride,
pub(crate) frame_set_fmt: FnMppFrameSetFmt,
pub(crate) frame_set_buffer: FnMppFrameSetBuffer,
pub(crate) packet_deinit: FnMppPacketDeinit,
pub(crate) packet_get_data: FnMppPacketGetData,
pub(crate) packet_get_length: FnMppPacketGetLength,
pub(crate) enc_cfg_init: FnMppEncCfgInit,
pub(crate) enc_cfg_deinit: FnMppEncCfgDeinit,
pub(crate) enc_cfg_set_s32: FnMppEncCfgSetS32,
pub(crate) buffer_import_from_fd: FnMppBufferImportFromFd,
pub(crate) buffer_put: FnMppBufferPutWithCaller,
}
unsafe impl Send for MppLib {}
unsafe impl Sync for MppLib {}
impl Drop for MppLib {
fn drop(&mut self) {
if !self.handle.is_null() {
unsafe { libc::dlclose(self.handle) };
}
}
}
#[cfg(target_os = "linux")]
pub(crate) fn probe_library() -> bool {
let handle = unsafe { libc::dlopen(c"librockchip_mpp.so".as_ptr(), libc::RTLD_LAZY) };
if handle.is_null() {
return false;
}
unsafe { libc::dlclose(handle) };
true
}
pub(crate) fn load_library() -> MppResult<Arc<MppLib>> {
let handle = unsafe { libc::dlopen(c"librockchip_mpp.so".as_ptr(), libc::RTLD_LAZY) };
if handle.is_null() {
return Err(MppError::LibraryNotFound);
}
macro_rules! sym {
($name:expr, $ty:ty) => {{
let ptr = unsafe { libc::dlsym(handle, $name.as_ptr().cast()) };
if ptr.is_null() {
unsafe { libc::dlclose(handle) };
return Err(MppError::SymbolMissing(stringify!($name)));
}
unsafe { std::mem::transmute_copy::<*mut c_void, $ty>(&ptr) }
}};
}
let lib = MppLib {
handle,
mpp_create: sym!(b"mpp_create\0", FnMppCreate),
mpp_init: sym!(b"mpp_init\0", FnMppInit),
mpp_destroy: sym!(b"mpp_destroy\0", FnMppDestroy),
frame_init: sym!(b"mpp_frame_init\0", FnMppFrameInit),
frame_deinit: sym!(b"mpp_frame_deinit\0", FnMppFrameDeinit),
frame_set_width: sym!(b"mpp_frame_set_width\0", FnMppFrameSetWidth),
frame_set_height: sym!(b"mpp_frame_set_height\0", FnMppFrameSetHeight),
frame_set_hor_stride: sym!(b"mpp_frame_set_hor_stride\0", FnMppFrameSetHorStride),
frame_set_ver_stride: sym!(b"mpp_frame_set_ver_stride\0", FnMppFrameSetVerStride),
frame_set_fmt: sym!(b"mpp_frame_set_fmt\0", FnMppFrameSetFmt),
frame_set_buffer: sym!(b"mpp_frame_set_buffer\0", FnMppFrameSetBuffer),
packet_deinit: sym!(b"mpp_packet_deinit\0", FnMppPacketDeinit),
packet_get_data: sym!(b"mpp_packet_get_data\0", FnMppPacketGetData),
packet_get_length: sym!(b"mpp_packet_get_length\0", FnMppPacketGetLength),
enc_cfg_init: sym!(b"mpp_enc_cfg_init\0", FnMppEncCfgInit),
enc_cfg_deinit: sym!(b"mpp_enc_cfg_deinit\0", FnMppEncCfgDeinit),
enc_cfg_set_s32: sym!(b"mpp_enc_cfg_set_s32\0", FnMppEncCfgSetS32),
buffer_import_from_fd: sym!(b"mpp_buffer_import_with_tag\0", FnMppBufferImportFromFd),
buffer_put: sym!(b"mpp_buffer_put_with_caller\0", FnMppBufferPutWithCaller),
};
Ok(Arc::new(lib))
}