diff --git a/libs/scrap/src/common/aom.rs b/libs/scrap/src/common/aom.rs index 2d750c8d2..40026b240 100644 --- a/libs/scrap/src/common/aom.rs +++ b/libs/scrap/src/common/aom.rs @@ -6,7 +6,8 @@ include!(concat!(env!("OUT_DIR"), "/aom_ffi.rs")); -use crate::{codec::EncoderApi, EncodeFrame, ImageFormat, ImageRgb, STRIDE_ALIGN}; +use crate::{codec::EncoderApi, EncodeFrame, STRIDE_ALIGN}; +use crate::{common::GoogleImage, generate_call_macro, generate_call_ptr_macro, Error, Result}; use hbb_common::{ anyhow::{anyhow, Context}, bytes::Bytes, @@ -15,6 +16,9 @@ use hbb_common::{ }; use std::{ptr, slice}; +generate_call_macro!(call_aom); +generate_call_ptr_macro!(call_aom_ptr); + impl Default for aom_codec_enc_cfg_t { fn default() -> Self { unsafe { std::mem::zeroed() } @@ -33,60 +37,6 @@ impl Default for aom_image_t { } } -#[derive(Debug)] -pub enum Error { - FailedCall(String), - BadPtr(String), -} - -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> { - write!(f, "{:?}", self) - } -} - -impl std::error::Error for Error {} - -pub type Result = std::result::Result; - -macro_rules! call_aom { - ($x:expr) => {{ - let result = unsafe { $x }; // original expression - let result_int = unsafe { std::mem::transmute::<_, i32>(result) }; - if result_int != 0 { - return Err(Error::FailedCall(format!( - "errcode={} {}:{}:{}:{}", - result_int, - module_path!(), - file!(), - line!(), - column!() - )) - .into()); - } - result - }}; -} - -macro_rules! call_aom_ptr { - ($x:expr) => {{ - let result = unsafe { $x }; // original expression - let result_int = unsafe { std::mem::transmute::<_, isize>(result) }; - if result_int == 0 { - return Err(Error::BadPtr(format!( - "errcode={} {}:{}:{}:{}", - result_int, - module_path!(), - file!(), - line!(), - column!() - )) - .into()); - } - result - }}; -} - #[derive(Clone, Copy, Debug)] pub struct AomEncoderConfig { pub width: u32, @@ -508,16 +458,6 @@ impl Image { self.0.is_null() } - #[inline] - pub fn width(&self) -> usize { - self.inner().d_w as _ - } - - #[inline] - pub fn height(&self) -> usize { - self.inner().d_h as _ - } - #[inline] pub fn format(&self) -> aom_img_fmt_t { self.inner().fmt @@ -527,90 +467,27 @@ impl Image { pub fn inner(&self) -> &aom_image_t { unsafe { &*self.0 } } +} +impl GoogleImage for Image { #[inline] - pub fn stride(&self, iplane: usize) -> i32 { - self.inner().stride[iplane] + fn width(&self) -> usize { + self.inner().d_w as _ } #[inline] - pub fn get_bytes_per_row(w: usize, fmt: ImageFormat, stride: usize) -> usize { - let bytes_per_pixel = match fmt { - ImageFormat::Raw => 3, - ImageFormat::ARGB | ImageFormat::ABGR => 4, - }; - // https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L128 - // https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L129 - (w * bytes_per_pixel + stride - 1) & !(stride - 1) - } - - // rgb [in/out] fmt and stride must be set in ImageRgb - pub fn to(&self, rgb: &mut ImageRgb) { - rgb.w = self.width(); - rgb.h = self.height(); - let bytes_per_row = Self::get_bytes_per_row(rgb.w, rgb.fmt, rgb.stride()); - rgb.raw.resize(rgb.h * bytes_per_row, 0); - let img = self.inner(); - unsafe { - match rgb.fmt() { - ImageFormat::Raw => { - super::I420ToRAW( - img.planes[0], - img.stride[0], - img.planes[1], - img.stride[1], - img.planes[2], - img.stride[2], - rgb.raw.as_mut_ptr(), - bytes_per_row as _, - self.width() as _, - self.height() as _, - ); - } - ImageFormat::ARGB => { - super::I420ToARGB( - img.planes[0], - img.stride[0], - img.planes[1], - img.stride[1], - img.planes[2], - img.stride[2], - rgb.raw.as_mut_ptr(), - bytes_per_row as _, - self.width() as _, - self.height() as _, - ); - } - ImageFormat::ABGR => { - super::I420ToABGR( - img.planes[0], - img.stride[0], - img.planes[1], - img.stride[1], - img.planes[2], - img.stride[2], - rgb.raw.as_mut_ptr(), - bytes_per_row as _, - self.width() as _, - self.height() as _, - ); - } - } - } + fn height(&self) -> usize { + self.inner().d_h as _ } #[inline] - pub fn data(&self) -> (&[u8], &[u8], &[u8]) { - unsafe { - let img = self.inner(); - let h = (img.d_h as usize + 1) & !1; - let n = img.stride[0] as usize * h; - let y = slice::from_raw_parts(img.planes[0], n); - let n = img.stride[1] as usize * (h >> 1); - let u = slice::from_raw_parts(img.planes[1], n); - let v = slice::from_raw_parts(img.planes[2], n); - (y, u, v) - } + fn stride(&self) -> Vec { + self.inner().stride.iter().map(|x| *x as i32).collect() + } + + #[inline] + fn planes(&self) -> Vec<*mut u8> { + self.inner().planes.iter().map(|p| *p as *mut u8).collect() } } diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index a54921482..03e8a19a2 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -12,6 +12,7 @@ use crate::mediacodec::{ }; use crate::{ aom::{self, AomDecoder, AomDecoderConfig, AomEncoder, AomEncoderConfig}, + common::GoogleImage, vpxcodec::{self, VpxDecoder, VpxDecoderConfig, VpxEncoder, VpxEncoderConfig, VpxVideoCodecId}, CodecName, ImageRgb, }; diff --git a/libs/scrap/src/common/mod.rs b/libs/scrap/src/common/mod.rs index 3780c268a..15e0f5147 100644 --- a/libs/scrap/src/common/mod.rs +++ b/libs/scrap/src/common/mod.rs @@ -1,5 +1,6 @@ pub use self::vpxcodec::*; use hbb_common::message_proto::{video_frame, VideoFrame}; +use std::slice; cfg_if! { if #[cfg(quartz)] { @@ -185,3 +186,151 @@ impl ToString for CodecFormat { } } } + +#[derive(Debug)] +pub enum Error { + FailedCall(String), + BadPtr(String), +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> { + write!(f, "{:?}", self) + } +} + +impl std::error::Error for Error {} + +pub type Result = std::result::Result; + +#[macro_export] +macro_rules! generate_call_macro { + ($func_name:ident) => { + macro_rules! $func_name { + ($x:expr) => {{ + let result = unsafe { $x }; + let result_int = unsafe { std::mem::transmute::<_, i32>(result) }; + if result_int != 0 { + return Err(crate::Error::FailedCall(format!( + "errcode={} {}:{}:{}:{}", + result_int, + module_path!(), + file!(), + line!(), + column!() + )) + .into()); + } + result + }}; + } + }; +} + +#[macro_export] +macro_rules! generate_call_ptr_macro { + ($func_name:ident) => { + macro_rules! $func_name { + ($x:expr) => {{ + let result = unsafe { $x }; + let result_int = unsafe { std::mem::transmute::<_, isize>(result) }; + if result_int == 0 { + return Err(crate::Error::BadPtr(format!( + "errcode={} {}:{}:{}:{}", + result_int, + module_path!(), + file!(), + line!(), + column!() + )) + .into()); + } + result + }}; + } + }; +} + +pub trait GoogleImage { + fn width(&self) -> usize; + fn height(&self) -> usize; + fn stride(&self) -> Vec; + fn planes(&self) -> Vec<*mut u8>; + fn get_bytes_per_row(w: usize, fmt: ImageFormat, stride: usize) -> usize { + let bytes_per_pixel = match fmt { + ImageFormat::Raw => 3, + ImageFormat::ARGB | ImageFormat::ABGR => 4, + }; + // https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L128 + // https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L129 + (w * bytes_per_pixel + stride - 1) & !(stride - 1) + } + // rgb [in/out] fmt and stride must be set in ImageRgb + fn to(&self, rgb: &mut ImageRgb) { + rgb.w = self.width(); + rgb.h = self.height(); + let bytes_per_row = Self::get_bytes_per_row(rgb.w, rgb.fmt, rgb.stride()); + rgb.raw.resize(rgb.h * bytes_per_row, 0); + let stride = self.stride(); + let planes = self.planes(); + unsafe { + match rgb.fmt() { + ImageFormat::Raw => { + super::I420ToRAW( + planes[0], + stride[0], + planes[1], + stride[1], + planes[2], + stride[2], + rgb.raw.as_mut_ptr(), + bytes_per_row as _, + self.width() as _, + self.height() as _, + ); + } + ImageFormat::ARGB => { + super::I420ToARGB( + planes[0], + stride[0], + planes[1], + stride[1], + planes[2], + stride[2], + rgb.raw.as_mut_ptr(), + bytes_per_row as _, + self.width() as _, + self.height() as _, + ); + } + ImageFormat::ABGR => { + super::I420ToABGR( + planes[0], + stride[0], + planes[1], + stride[1], + planes[2], + stride[2], + rgb.raw.as_mut_ptr(), + bytes_per_row as _, + self.width() as _, + self.height() as _, + ); + } + } + } + } + fn data(&self) -> (&[u8], &[u8], &[u8]) { + unsafe { + let stride = self.stride(); + let planes = self.planes(); + let h = (self.height() as usize + 1) & !1; + let n = stride[0] as usize * h; + let y = slice::from_raw_parts(planes[0], n); + let n = stride[1] as usize * (h >> 1); + let u = slice::from_raw_parts(planes[1], n); + let v = slice::from_raw_parts(planes[2], n); + (y, u, v) + } + } +} diff --git a/libs/scrap/src/common/vpxcodec.rs b/libs/scrap/src/common/vpxcodec.rs index 21d88ef0c..817971c60 100644 --- a/libs/scrap/src/common/vpxcodec.rs +++ b/libs/scrap/src/common/vpxcodec.rs @@ -6,14 +6,18 @@ use hbb_common::anyhow::{anyhow, Context}; use hbb_common::message_proto::{EncodedVideoFrame, EncodedVideoFrames, Message, VideoFrame}; use hbb_common::ResultType; -use crate::STRIDE_ALIGN; -use crate::{codec::EncoderApi, ImageFormat, ImageRgb}; +use crate::codec::EncoderApi; +use crate::{GoogleImage, STRIDE_ALIGN}; use super::vpx::{vp8e_enc_control_id::*, vpx_codec_err_t::*, *}; +use crate::{generate_call_macro, generate_call_ptr_macro, Error, Result}; use hbb_common::bytes::Bytes; use std::os::raw::{c_int, c_uint}; use std::{ptr, slice}; +generate_call_macro!(call_vpx); +generate_call_ptr_macro!(call_vpx_ptr); + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum VpxVideoCodecId { VP8, @@ -37,60 +41,6 @@ pub struct VpxDecoder { ctx: vpx_codec_ctx_t, } -#[derive(Debug)] -pub enum Error { - FailedCall(String), - BadPtr(String), -} - -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> { - write!(f, "{:?}", self) - } -} - -impl std::error::Error for Error {} - -pub type Result = std::result::Result; - -macro_rules! call_vpx { - ($x:expr) => {{ - let result = unsafe { $x }; // original expression - let result_int = unsafe { std::mem::transmute::<_, i32>(result) }; - if result_int != 0 { - return Err(Error::FailedCall(format!( - "errcode={} {}:{}:{}:{}", - result_int, - module_path!(), - file!(), - line!(), - column!() - )) - .into()); - } - result - }}; -} - -macro_rules! call_vpx_ptr { - ($x:expr) => {{ - let result = unsafe { $x }; // original expression - let result_int = unsafe { std::mem::transmute::<_, isize>(result) }; - if result_int == 0 { - return Err(Error::BadPtr(format!( - "errcode={} {}:{}:{}:{}", - result_int, - module_path!(), - file!(), - line!(), - column!() - )) - .into()); - } - result - }}; -} - impl EncoderApi for VpxEncoder { fn new(cfg: crate::codec::EncoderCfg) -> ResultType where @@ -495,16 +445,6 @@ impl Image { self.0.is_null() } - #[inline] - pub fn width(&self) -> usize { - self.inner().d_w as _ - } - - #[inline] - pub fn height(&self) -> usize { - self.inner().d_h as _ - } - #[inline] pub fn format(&self) -> vpx_img_fmt_t { // VPX_IMG_FMT_I420 @@ -515,90 +455,27 @@ impl Image { pub fn inner(&self) -> &vpx_image_t { unsafe { &*self.0 } } +} +impl GoogleImage for Image { #[inline] - pub fn stride(&self, iplane: usize) -> i32 { - self.inner().stride[iplane] + fn width(&self) -> usize { + self.inner().d_w as _ } #[inline] - pub fn get_bytes_per_row(w: usize, fmt: ImageFormat, stride: usize) -> usize { - let bytes_per_pixel = match fmt { - ImageFormat::Raw => 3, - ImageFormat::ARGB | ImageFormat::ABGR => 4, - }; - // https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L128 - // https://github.com/lemenkov/libyuv/blob/6900494d90ae095d44405cd4cc3f346971fa69c9/source/convert_argb.cc#L129 - (w * bytes_per_pixel + stride - 1) & !(stride - 1) - } - - // rgb [in/out] fmt and stride must be set in ImageRgb - pub fn to(&self, rgb: &mut ImageRgb) { - rgb.w = self.width(); - rgb.h = self.height(); - let bytes_per_row = Self::get_bytes_per_row(rgb.w, rgb.fmt, rgb.stride()); - rgb.raw.resize(rgb.h * bytes_per_row, 0); - let img = self.inner(); - unsafe { - match rgb.fmt() { - ImageFormat::Raw => { - super::I420ToRAW( - img.planes[0], - img.stride[0], - img.planes[1], - img.stride[1], - img.planes[2], - img.stride[2], - rgb.raw.as_mut_ptr(), - bytes_per_row as _, - self.width() as _, - self.height() as _, - ); - } - ImageFormat::ARGB => { - super::I420ToARGB( - img.planes[0], - img.stride[0], - img.planes[1], - img.stride[1], - img.planes[2], - img.stride[2], - rgb.raw.as_mut_ptr(), - bytes_per_row as _, - self.width() as _, - self.height() as _, - ); - } - ImageFormat::ABGR => { - super::I420ToABGR( - img.planes[0], - img.stride[0], - img.planes[1], - img.stride[1], - img.planes[2], - img.stride[2], - rgb.raw.as_mut_ptr(), - bytes_per_row as _, - self.width() as _, - self.height() as _, - ); - } - } - } + fn height(&self) -> usize { + self.inner().d_h as _ } #[inline] - pub fn data(&self) -> (&[u8], &[u8], &[u8]) { - unsafe { - let img = self.inner(); - let h = (img.d_h as usize + 1) & !1; - let n = img.stride[0] as usize * h; - let y = slice::from_raw_parts(img.planes[0], n); - let n = img.stride[1] as usize * (h >> 1); - let u = slice::from_raw_parts(img.planes[1], n); - let v = slice::from_raw_parts(img.planes[2], n); - (y, u, v) - } + fn stride(&self) -> Vec { + self.inner().stride.iter().map(|x| *x as i32).collect() + } + + #[inline] + fn planes(&self) -> Vec<*mut u8> { + self.inner().planes.iter().map(|p| *p as *mut u8).collect() } }