diff --git a/xilinx/src/lib.rs b/xilinx/src/lib.rs index dabf4cf1..f1135954 100644 --- a/xilinx/src/lib.rs +++ b/xilinx/src/lib.rs @@ -1,6 +1,10 @@ pub mod sys; pub use sys::*; +/*---- transcoder ----*/ +pub mod xlnx_transcoder_utils; +pub use xlnx_transcoder_utils::*; + /*---- decoder ----*/ pub mod xlnx_decoder; pub use xlnx_decoder::*; @@ -41,7 +45,7 @@ const XCLBIN_FILENAME: &[u8] = b"/opt/xilinx/xcdr/xclbins/transcode.xclbin\0"; /// pub fn xlnx_init_all_devices() -> Result { let mut xclbin_params = Vec::new(); - let device_count = unsafe { xclProbe() } as i32; + let device_count = unsafe { xclProbe() } as i32; for i in 0..device_count { xclbin_params.push(XmaXclbinParameter { xclbin_name: XCLBIN_FILENAME.as_ptr() as *mut i8, diff --git a/xilinx/src/xlnx_dec_utils.rs b/xilinx/src/xlnx_dec_utils.rs index ddef7abe..4b510bfd 100644 --- a/xilinx/src/xlnx_dec_utils.rs +++ b/xilinx/src/xlnx_dec_utils.rs @@ -85,7 +85,7 @@ fn xlnx_fill_dec_pool_props(cu_pool_prop: &mut xrmCuPoolProperty, dec_load: i32) Ok(()) } -pub(crate) fn xlnx_reserve_dec_resource(xlnx_dec_ctx: &mut XlnxDecoderXrmCtx) -> Result<(), SimpleError> { +pub fn xlnx_reserve_dec_resource(xlnx_dec_ctx: &mut XlnxDecoderXrmCtx) -> Result<(), SimpleError> { // a device has already been chosen, there is no need to assign a reserve id. if xlnx_dec_ctx.device_id >= 0 { return Ok(()); diff --git a/xilinx/src/xlnx_decoder.rs b/xilinx/src/xlnx_decoder.rs index 2d553dbe..c0bb4128 100644 --- a/xilinx/src/xlnx_decoder.rs +++ b/xilinx/src/xlnx_decoder.rs @@ -13,9 +13,6 @@ pub struct XlnxDecoder { impl XlnxDecoder { pub fn new(xma_dec_props: &mut XmaDecoderProperties, xlnx_dec_ctx: &mut XlnxDecoderXrmCtx) -> Result { - // reserve the required decoding resources and assign reserve ID - xlnx_reserve_dec_resource(xlnx_dec_ctx)?; - let dec_session = xlnx_create_dec_session(xma_dec_props, xlnx_dec_ctx)?; let mut frame_props: XmaFrameProperties = Default::default(); @@ -28,9 +25,9 @@ impl XlnxDecoder { let out_frame = unsafe { xma_frame_alloc(&mut frame_props, true) }; - // Loop through the planes. no buffer shouold be allocated yet. - // Since this will be used in a pipeline, xvbm will allocate the buffers. - // So we need to specify to use device buffers. + // Loop through the planes. no buffer shouold be allocated yet. + // Since this will be used in a pipeline, xvbm will allocate the buffers. + // So we need to specify to use device buffers. unsafe { for i in 0..2 { (*out_frame).data[i].buffer_type = XmaBufferType_XMA_DEVICE_BUFFER_TYPE; diff --git a/xilinx/src/xlnx_enc_utils.rs b/xilinx/src/xlnx_enc_utils.rs index 9e1041e5..1cef85c3 100644 --- a/xilinx/src/xlnx_enc_utils.rs +++ b/xilinx/src/xlnx_enc_utils.rs @@ -194,6 +194,7 @@ fn xlnx_enc_cu_alloc_reserve_id(xma_enc_props: &mut XmaEncoderProperties, xlnx_e } fn xlnx_enc_cu_alloc(xma_enc_props: &mut XmaEncoderProperties, xlnx_enc_ctx: &mut XlnxEncoderXrmCtx) -> Result<(), SimpleError> { + xlnx_enc_ctx.enc_load = xlnx_calc_enc_load(xlnx_enc_ctx.xrm_ctx, xma_enc_props)?; if xlnx_enc_ctx.device_id >= 0 { xlnx_enc_cu_alloc_device_id(xma_enc_props, xlnx_enc_ctx)?; } else { diff --git a/xilinx/src/xlnx_encoder.rs b/xilinx/src/xlnx_encoder.rs index 21986925..cfd995e5 100644 --- a/xilinx/src/xlnx_encoder.rs +++ b/xilinx/src/xlnx_encoder.rs @@ -9,8 +9,6 @@ pub struct XlnxEncoder { impl XlnxEncoder { pub fn new(xma_enc_props: &mut XmaEncoderProperties, xlnx_enc_ctx: &mut XlnxEncoderXrmCtx) -> Result { - xlnx_reserve_enc_resource(xlnx_enc_ctx)?; - let enc_session = xlnx_create_enc_session(xma_enc_props, xlnx_enc_ctx)?; let out_buffer = unsafe { xma_data_buffer_alloc(0, true) }; diff --git a/xilinx/src/xlnx_scaler.rs b/xilinx/src/xlnx_scaler.rs index 2cee497d..6e2b284a 100644 --- a/xilinx/src/xlnx_scaler.rs +++ b/xilinx/src/xlnx_scaler.rs @@ -14,7 +14,6 @@ pub struct XlnxScaler { impl XlnxScaler { pub fn new(xma_scal_props: &mut XmaScalerProperties, xlnx_scal_ctx: &mut XlnxScalerXrmCtx) -> Result { - xlnx_reserve_scal_resource(xlnx_scal_ctx)?; let scal_session = xlnx_create_scal_session(xma_scal_props, xlnx_scal_ctx)?; let mut out_frame_list = Vec::new(); diff --git a/xilinx/src/xlnx_transcoder_utils.rs b/xilinx/src/xlnx_transcoder_utils.rs new file mode 100644 index 00000000..f3778016 --- /dev/null +++ b/xilinx/src/xlnx_transcoder_utils.rs @@ -0,0 +1,139 @@ +use crate::{strcpy_to_arr_i8, sys::*, xlnx_dec_utils::*, xlnx_enc_utils::*, xlnx_scal_utils::*, xrm_precision_1000000_bitmask}; +use simple_error::{bail, SimpleError}; + +pub struct XlnxTranscodeLoad { + pub dec_load: i32, + pub scal_load: i32, + pub enc_load: i32, + pub enc_num: i32, +} + +pub struct XlnxTranscodeXrmCtx { + pub xrm_ctx: xrmContext, + pub transcode_load: XlnxTranscodeLoad, + pub reserve_idx: u64, +} + +impl XlnxTranscodeXrmCtx { + pub fn new() -> Self { + let xrm_ctx = unsafe {xrmCreateContext(XRM_API_VERSION_1)}; + + Self { + xrm_ctx, + transcode_load: XlnxTranscodeLoad { + dec_load: 0, + scal_load: 0, + enc_load: 0, + enc_num:0, + }, + reserve_idx: 0 + } + } +} + +pub fn xlnx_calc_transcode_load( + xlnx_transcode_xrm_ctx: &mut XlnxTranscodeXrmCtx, + xma_dec_props: &mut XmaDecoderProperties, + xma_scal_props: &mut XmaScalerProperties, + xma_enc_props_list: Vec<&mut XmaEncoderProperties>, + transcode_cu_pool_prop: &mut xrmCuPoolProperty, +) -> Result<(), SimpleError> { + xlnx_transcode_xrm_ctx.transcode_load.dec_load = xlnx_calc_dec_load(xlnx_transcode_xrm_ctx.xrm_ctx, xma_dec_props)?; + xlnx_transcode_xrm_ctx.transcode_load.scal_load = xlnx_calc_scal_load(xlnx_transcode_xrm_ctx.xrm_ctx, xma_scal_props)?; + for xma_enc_props in xma_enc_props_list { + xlnx_transcode_xrm_ctx.transcode_load.enc_load += xlnx_calc_enc_load(xlnx_transcode_xrm_ctx.xrm_ctx, xma_enc_props)?; + xlnx_transcode_xrm_ctx.transcode_load.enc_num += 1; + } + + xlnx_fill_transcode_pool_props(transcode_cu_pool_prop, &xlnx_transcode_xrm_ctx.transcode_load)?; + Ok(()) +} + +fn xlnx_fill_transcode_pool_props(transcode_cu_pool_prop: &mut xrmCuPoolProperty, transcode_load: &XlnxTranscodeLoad) -> Result<(), SimpleError> { + let mut cu_num = 0; + transcode_cu_pool_prop.cuListProp.sameDevice = true; + transcode_cu_pool_prop.cuListNum = 1; + + if transcode_load.dec_load > 0 { + strcpy_to_arr_i8(&mut transcode_cu_pool_prop.cuListProp.cuProps[cu_num].kernelName, "decoder")?; + strcpy_to_arr_i8(&mut transcode_cu_pool_prop.cuListProp.cuProps[cu_num].kernelAlias, "DECODER_MPSOC")?; + transcode_cu_pool_prop.cuListProp.cuProps[cu_num].devExcl = false; + transcode_cu_pool_prop.cuListProp.cuProps[cu_num].requestLoad = xrm_precision_1000000_bitmask(transcode_load.dec_load); + cu_num += 1; + + strcpy_to_arr_i8(&mut transcode_cu_pool_prop.cuListProp.cuProps[cu_num].kernelName, "kernel_vcu_decoder")?; + transcode_cu_pool_prop.cuListProp.cuProps[cu_num].devExcl = false; + transcode_cu_pool_prop.cuListProp.cuProps[cu_num].requestLoad = xrm_precision_1000000_bitmask(XRM_MAX_CU_LOAD_GRANULARITY_1000000 as i32); + cu_num += 1; + } + + if transcode_load.scal_load > 0 { + strcpy_to_arr_i8(&mut transcode_cu_pool_prop.cuListProp.cuProps[cu_num].kernelName, "scaler")?; + strcpy_to_arr_i8(&mut transcode_cu_pool_prop.cuListProp.cuProps[cu_num].kernelAlias, "SCALER_MPSOC")?; + transcode_cu_pool_prop.cuListProp.cuProps[cu_num].devExcl = false; + transcode_cu_pool_prop.cuListProp.cuProps[cu_num].requestLoad = xrm_precision_1000000_bitmask(transcode_load.scal_load); + cu_num += 1; + } + + if transcode_load.enc_load > 0 { + strcpy_to_arr_i8(&mut transcode_cu_pool_prop.cuListProp.cuProps[cu_num].kernelName, "encoder")?; + strcpy_to_arr_i8(&mut transcode_cu_pool_prop.cuListProp.cuProps[cu_num].kernelAlias, "ENCODER_MPSOC")?; + transcode_cu_pool_prop.cuListProp.cuProps[cu_num].devExcl = false; + transcode_cu_pool_prop.cuListProp.cuProps[cu_num].requestLoad = xrm_precision_1000000_bitmask(transcode_load.enc_load); + cu_num += 1; + + for _ in 0..transcode_load.enc_num { + strcpy_to_arr_i8(&mut transcode_cu_pool_prop.cuListProp.cuProps[cu_num].kernelName, "kernel_vcu_encoder")?; + strcpy_to_arr_i8(&mut transcode_cu_pool_prop.cuListProp.cuProps[cu_num].kernelAlias, "")?; + transcode_cu_pool_prop.cuListProp.cuProps[cu_num].devExcl = false; + transcode_cu_pool_prop.cuListProp.cuProps[cu_num].requestLoad = xrm_precision_1000000_bitmask(XRM_MAX_CU_LOAD_GRANULARITY_1000000 as i32); + cu_num += 1; + } + } + + transcode_cu_pool_prop.cuListProp.cuNum = cu_num as i32; + Ok(()) +} + +pub fn xlnx_reserve_transcode_resource( + xlnx_transcode_xrm_ctx: &mut XlnxTranscodeXrmCtx, + xma_dec_props: &mut XmaDecoderProperties, + xma_scal_props: &mut XmaScalerProperties, + xma_enc_props: Vec<&mut XmaEncoderProperties>, +) -> Result<(), SimpleError> { + let mut transcode_cu_pool_prop: xrmCuPoolProperty = Default::default(); + xlnx_calc_transcode_load( + xlnx_transcode_xrm_ctx, + xma_dec_props, + xma_scal_props, + xma_enc_props, + &mut transcode_cu_pool_prop, + )?; + unsafe { + let num_cu_pool = xrmCheckCuPoolAvailableNum(xlnx_transcode_xrm_ctx.xrm_ctx, &mut transcode_cu_pool_prop); + if num_cu_pool <= 0 { + bail!("no xilinx hardware resources avaliable for allocation") + } + xlnx_transcode_xrm_ctx.reserve_idx = xrmCuPoolReserve(xlnx_transcode_xrm_ctx.xrm_ctx, &mut transcode_cu_pool_prop); + if xlnx_transcode_xrm_ctx.reserve_idx == 0 { + bail!("failed to reserve encode cu pool") + } + } + + Ok(()) +} + +impl Drop for XlnxTranscodeXrmCtx { + fn drop(&mut self) { + if self.xrm_ctx.is_null() { + return; + } + unsafe { + if self.reserve_idx != 0 { + xrmCuPoolRelinquish(self.xrm_ctx, self.reserve_idx); + } + + xrmDestroyContext(self.xrm_ctx); + } + } +}