From 494a05ab48b9c946f17d0040619b4f402d09a26f Mon Sep 17 00:00:00 2001 From: Jacob Kiesel Date: Tue, 7 Jan 2025 19:30:09 -0700 Subject: [PATCH] draft: implement proper lifetimes for xilinx structs --- xilinx/src/lib.rs | 4 +++ xilinx/src/xlnx_dec_utils.rs | 38 ++++++++++++++--------------- xilinx/src/xlnx_decoder.rs | 12 ++++++--- xilinx/src/xlnx_enc_utils.rs | 32 ++++++++++++------------ xilinx/src/xlnx_encoder.rs | 14 +++++++---- xilinx/src/xlnx_scal_utils.rs | 34 +++++++++++++------------- xilinx/src/xlnx_scaler.rs | 12 ++++++--- xilinx/src/xlnx_transcoder_utils.rs | 38 ++++++++++++----------------- xilinx/src/xrm_context.rs | 35 ++++++++++++++++++++++++++ 9 files changed, 132 insertions(+), 87 deletions(-) create mode 100644 xilinx/src/xrm_context.rs diff --git a/xilinx/src/lib.rs b/xilinx/src/lib.rs index 37a3fdc8..f481fed1 100644 --- a/xilinx/src/lib.rs +++ b/xilinx/src/lib.rs @@ -1,6 +1,10 @@ pub mod sys; pub use sys::*; +/*---- context ----*/ +pub mod xrm_context; +pub use xrm_context::*; + /*---- transcoder ----*/ pub mod xlnx_transcoder_utils; pub use xlnx_transcoder_utils::*; diff --git a/xilinx/src/xlnx_dec_utils.rs b/xilinx/src/xlnx_dec_utils.rs index 836719a6..b2b8b8ef 100644 --- a/xilinx/src/xlnx_dec_utils.rs +++ b/xilinx/src/xlnx_dec_utils.rs @@ -3,7 +3,7 @@ use std::{ffi::CString, os::raw::c_char, str::from_utf8}; use libloading::{Library, Symbol}; use simple_error::{bail, SimpleError}; -use crate::{strcpy_to_arr_i8, sys::*, xrm_precision_1000000_bitmask}; +use crate::{strcpy_to_arr_i8, sys::*, xrm_precision_1000000_bitmask, XrmContext}; const DEC_PLUGIN_NAME: &[u8] = b"xrmU30DecPlugin\0"; @@ -14,17 +14,17 @@ pub struct XlnxDecBuffer<'a> { pub allocated: usize, } -pub struct XlnxDecoderXrmCtx { +pub struct XlnxDecoderXrmCtx<'a> { pub xrm_reserve_id: Option, pub device_id: Option, pub dec_load: i32, pub(crate) decode_res_in_use: bool, - pub(crate) xrm_ctx: xrmContext, + pub(crate) xrm_ctx: &'a XrmContext, pub(crate) cu_list_res: Box, } -impl XlnxDecoderXrmCtx { - pub fn new(xrm_ctx: xrmContext, device_id: Option, reserve_id: Option, dec_load: i32) -> Self { +impl<'a> XlnxDecoderXrmCtx<'a> { + pub fn new(xrm_ctx: &'a XrmContext, device_id: Option, reserve_id: Option, dec_load: i32) -> Self { Self { xrm_reserve_id: reserve_id, device_id, @@ -38,7 +38,7 @@ impl XlnxDecoderXrmCtx { /// Calculates the decoder load uing the xrmU30Dec plugin. #[allow(clippy::not_unsafe_ptr_arg_deref)] -pub fn xlnx_calc_dec_load(xrm_ctx: xrmContext, xma_dec_props: *mut XmaDecoderProperties) -> Result { +pub fn xlnx_calc_dec_load(xrm_ctx: &XrmContext, xma_dec_props: *mut XmaDecoderProperties) -> Result { let func_id = 0; let mut plugin_param: xrmPluginFuncParam = Default::default(); unsafe { @@ -59,7 +59,7 @@ pub fn xlnx_calc_dec_load(xrm_ctx: xrmContext, xma_dec_props: *mut XmaDecoderPro } unsafe { - let ret = xrmExecPluginFunc(xrm_ctx, DEC_PLUGIN_NAME.as_ptr() as *mut i8, func_id, &mut plugin_param); + let ret = xrmExecPluginFunc(xrm_ctx.raw(), DEC_PLUGIN_NAME.as_ptr() as *mut i8, func_id, &mut plugin_param); if ret != XRM_SUCCESS as i32 { bail!("XRM decoder plugin failed to calculate decoder load. error: {}", ret); } @@ -107,18 +107,18 @@ fn xlnx_fill_dec_pool_props(cu_pool_prop: &mut xrmCuPoolPropertyV2, dec_load: i3 Ok(()) } -pub 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> { let mut cu_pool_prop: Box = Box::new(Default::default()); let mut cu_pool_res_infor: Box = Box::new(Default::default()); xlnx_fill_dec_pool_props(&mut cu_pool_prop, xlnx_dec_ctx.dec_load, xlnx_dec_ctx.device_id)?; unsafe { - let num_cu_pool = xrmCheckCuPoolAvailableNumV2(xlnx_dec_ctx.xrm_ctx, cu_pool_prop.as_mut()); + let num_cu_pool = xrmCheckCuPoolAvailableNumV2(xlnx_dec_ctx.xrm_ctx.raw(), cu_pool_prop.as_mut()); if num_cu_pool <= 0 { bail!("no decoder resources available for allocation") } - let xrm_reserve_id = xrmCuPoolReserveV2(xlnx_dec_ctx.xrm_ctx, cu_pool_prop.as_mut(), cu_pool_res_infor.as_mut()); + let xrm_reserve_id = xrmCuPoolReserveV2(xlnx_dec_ctx.xrm_ctx.raw(), cu_pool_prop.as_mut(), cu_pool_res_infor.as_mut()); if xrm_reserve_id == 0 { bail!("failed to reserve decode cu pool") } @@ -129,7 +129,7 @@ pub fn xlnx_reserve_dec_resource(xlnx_dec_ctx: &mut XlnxDecoderXrmCtx) -> Result } /// Allocates decoder CU -fn xlnx_dec_cu_alloc(xma_dec_props: &mut XmaDecoderProperties, xlnx_dec_ctx: &mut XlnxDecoderXrmCtx) -> Result<(), SimpleError> { +fn xlnx_dec_cu_alloc(xma_dec_props: &mut XmaDecoderProperties, xlnx_dec_ctx: &mut XlnxDecoderXrmCtx<'_>) -> Result<(), SimpleError> { // Allocate xrm decoder let mut decode_cu_list_prop = Box::new(xrmCuListPropertyV2 { cuNum: 2, @@ -169,7 +169,7 @@ fn xlnx_dec_cu_alloc(xma_dec_props: &mut XmaDecoderProperties, xlnx_dec_ctx: &mu } } - if unsafe { xrmCuListAllocV2(xlnx_dec_ctx.xrm_ctx, decode_cu_list_prop.as_mut(), xlnx_dec_ctx.cu_list_res.as_mut()) } != XRM_SUCCESS as _ { + if unsafe { xrmCuListAllocV2(xlnx_dec_ctx.xrm_ctx.raw(), decode_cu_list_prop.as_mut(), xlnx_dec_ctx.cu_list_res.as_mut()) } != XRM_SUCCESS as _ { bail!( "failed to allocate decode cu list from reserve id {:?} and device id {:?}", xlnx_dec_ctx.xrm_reserve_id, @@ -194,7 +194,7 @@ fn xlnx_dec_cu_alloc(xma_dec_props: &mut XmaDecoderProperties, xlnx_dec_ctx: &mu /// Attempts to create decoder session pub(crate) fn xlnx_create_dec_session( xma_dec_props: &mut XmaDecoderProperties, - xlnx_dec_ctx: &mut XlnxDecoderXrmCtx, + xlnx_dec_ctx: &mut XlnxDecoderXrmCtx<'_>, ) -> Result<*mut XmaDecoderSession, SimpleError> { xlnx_dec_cu_alloc(xma_dec_props, xlnx_dec_ctx)?; @@ -206,17 +206,17 @@ pub(crate) fn xlnx_create_dec_session( Ok(dec_session) } -impl Drop for XlnxDecoderXrmCtx { +impl<'a> Drop for XlnxDecoderXrmCtx<'a> { fn drop(&mut self) { - if self.xrm_ctx.is_null() { - return; - } unsafe { + if self.xrm_ctx.raw().is_null() { + return; + } if let Some(xrm_reserve_id) = self.xrm_reserve_id { - let _ = xrmCuPoolRelinquishV2(self.xrm_ctx, xrm_reserve_id); + let _ = xrmCuPoolRelinquishV2(self.xrm_ctx.raw(), xrm_reserve_id); } if self.decode_res_in_use { - let _ = xrmCuListReleaseV2(self.xrm_ctx, self.cu_list_res.as_mut()); + let _ = xrmCuListReleaseV2(self.xrm_ctx.raw(), self.cu_list_res.as_mut()); } } } diff --git a/xilinx/src/xlnx_decoder.rs b/xilinx/src/xlnx_decoder.rs index ca5a10ec..18df737a 100644 --- a/xilinx/src/xlnx_decoder.rs +++ b/xilinx/src/xlnx_decoder.rs @@ -1,18 +1,21 @@ +use std::marker::PhantomData; + use crate::sys::*; use crate::xlnx_dec_utils::*; use crate::{XlnxError, XlnxErrorType}; use simple_error::{bail, SimpleError}; -pub struct XlnxDecoder { +pub struct XlnxDecoder<'a> { pub dec_session: *mut XmaDecoderSession, pub frame_props: XmaFrameProperties, in_buf: XmaDataBuffer, pub out_frame: *mut XmaFrame, pub flush_sent: bool, + decoder_ctx_lifetime: PhantomData>, } -impl XlnxDecoder { - pub fn new(xma_dec_props: &mut XmaDecoderProperties, xlnx_dec_ctx: &mut XlnxDecoderXrmCtx) -> Result { +impl<'a> XlnxDecoder<'a> { + pub fn new(xma_dec_props: &mut XmaDecoderProperties, xlnx_dec_ctx: &mut XlnxDecoderXrmCtx<'a>) -> Result { let dec_session = xlnx_create_dec_session(xma_dec_props, xlnx_dec_ctx)?; let mut frame_props: XmaFrameProperties = Default::default(); @@ -41,6 +44,7 @@ impl XlnxDecoder { in_buf, out_frame, flush_sent: false, + decoder_ctx_lifetime: PhantomData, }) } @@ -126,7 +130,7 @@ impl XlnxDecoder { } } -impl Drop for XlnxDecoder { +impl<'a> Drop for XlnxDecoder<'a> { fn drop(&mut self) { unsafe { if !self.dec_session.is_null() { diff --git a/xilinx/src/xlnx_enc_utils.rs b/xilinx/src/xlnx_enc_utils.rs index a12ca138..3b35fbea 100644 --- a/xilinx/src/xlnx_enc_utils.rs +++ b/xilinx/src/xlnx_enc_utils.rs @@ -1,21 +1,21 @@ -use crate::{strcpy_to_arr_i8, sys::*, xrm_precision_1000000_bitmask}; +use crate::{strcpy_to_arr_i8, sys::*, xrm_precision_1000000_bitmask, XrmContext}; use libloading::{Library, Symbol}; use simple_error::{bail, SimpleError}; use std::{ffi::CString, os::raw::c_char, str::from_utf8}; const ENC_PLUGIN_NAME: &[u8] = b"xrmU30EncPlugin\0"; -pub struct XlnxEncoderXrmCtx { +pub struct XlnxEncoderXrmCtx<'a> { pub xrm_reserve_id: Option, pub device_id: Option, pub enc_load: i32, pub(crate) encode_res_in_use: bool, - pub(crate) xrm_ctx: xrmContext, + pub(crate) xrm_ctx: &'a XrmContext, pub(crate) cu_list_res: Box, } -impl XlnxEncoderXrmCtx { - pub fn new(xrm_ctx: xrmContext, device_id: Option, reserve_id: Option, enc_load: i32) -> Self { +impl<'a> XlnxEncoderXrmCtx<'a> { + pub fn new(xrm_ctx: &'a XrmContext, device_id: Option, reserve_id: Option, enc_load: i32) -> Self { Self { xrm_reserve_id: reserve_id, device_id, @@ -29,7 +29,7 @@ impl XlnxEncoderXrmCtx { /// Calculates the encoder load uing the xrmU30Enc plugin. #[allow(clippy::not_unsafe_ptr_arg_deref)] -pub fn xlnx_calc_enc_load(xrm_ctx: xrmContext, xma_enc_props: *mut XmaEncoderProperties) -> Result { +pub fn xlnx_calc_enc_load(xrm_ctx: &XrmContext, xma_enc_props: *mut XmaEncoderProperties) -> Result { let func_id = 0; let mut plugin_param: xrmPluginFuncParam = Default::default(); unsafe { @@ -50,7 +50,7 @@ pub fn xlnx_calc_enc_load(xrm_ctx: xrmContext, xma_enc_props: *mut XmaEncoderPro } unsafe { - let ret = xrmExecPluginFunc(xrm_ctx, ENC_PLUGIN_NAME.as_ptr() as *mut i8, func_id, &mut plugin_param); + let ret = xrmExecPluginFunc(xrm_ctx.raw(), ENC_PLUGIN_NAME.as_ptr() as *mut i8, func_id, &mut plugin_param); if ret != XRM_SUCCESS as i32 { bail!("XRM encoder plugin failed to calculate encoder load. error: {}", ret); } @@ -110,12 +110,12 @@ pub fn xlnx_reserve_enc_resource(xlnx_enc_ctx: &mut XlnxEncoderXrmCtx) -> Result xlnx_fill_enc_pool_props(&mut cu_pool_prop, enc_count, xlnx_enc_ctx.enc_load, xlnx_enc_ctx.device_id)?; unsafe { - let num_cu_pool = xrmCheckCuPoolAvailableNumV2(xlnx_enc_ctx.xrm_ctx, cu_pool_prop.as_mut()); + let num_cu_pool = xrmCheckCuPoolAvailableNumV2(xlnx_enc_ctx.xrm_ctx.raw(), cu_pool_prop.as_mut()); if num_cu_pool <= 0 { bail!("no encoder resources avaliable for allocation") } - let xrm_reserve_id: u64 = xrmCuPoolReserveV2(xlnx_enc_ctx.xrm_ctx, cu_pool_prop.as_mut(), cu_pool_res_infor.as_mut()); + let xrm_reserve_id: u64 = xrmCuPoolReserveV2(xlnx_enc_ctx.xrm_ctx.raw(), cu_pool_prop.as_mut(), cu_pool_res_infor.as_mut()); if xrm_reserve_id == 0 { bail!("failed to reserve encode cu pool") } @@ -166,7 +166,7 @@ fn xlnx_enc_cu_alloc(xma_enc_props: &mut XmaEncoderProperties, xlnx_enc_ctx: &mu } } - if unsafe { xrmCuListAllocV2(xlnx_enc_ctx.xrm_ctx, encode_cu_list_prop.as_mut(), xlnx_enc_ctx.cu_list_res.as_mut()) } != XRM_SUCCESS as _ { + if unsafe { xrmCuListAllocV2(xlnx_enc_ctx.xrm_ctx.raw(), encode_cu_list_prop.as_mut(), xlnx_enc_ctx.cu_list_res.as_mut()) } != XRM_SUCCESS as _ { bail!( "failed to allocate encode cu list from reserve id {:?} and device id {:?}", xlnx_enc_ctx.xrm_reserve_id, @@ -202,17 +202,17 @@ pub(crate) fn xlnx_create_enc_session( Ok(enc_session) } -impl Drop for XlnxEncoderXrmCtx { +impl<'a> Drop for XlnxEncoderXrmCtx<'a> { fn drop(&mut self) { - if self.xrm_ctx.is_null() { - return; - } unsafe { + if self.xrm_ctx.raw().is_null() { + return; + } if let Some(xrm_reserve_id) = self.xrm_reserve_id { - let _ = xrmCuPoolRelinquishV2(self.xrm_ctx, xrm_reserve_id); + let _ = xrmCuPoolRelinquishV2(self.xrm_ctx.raw(), xrm_reserve_id); } if self.encode_res_in_use { - let _ = xrmCuListReleaseV2(self.xrm_ctx, self.cu_list_res.as_mut()); + let _ = xrmCuListReleaseV2(self.xrm_ctx.raw(), self.cu_list_res.as_mut()); } } } diff --git a/xilinx/src/xlnx_encoder.rs b/xilinx/src/xlnx_encoder.rs index 9c3064d9..7694e9bd 100644 --- a/xilinx/src/xlnx_encoder.rs +++ b/xilinx/src/xlnx_encoder.rs @@ -1,14 +1,17 @@ +use std::marker::PhantomData; + use crate::{sys::*, xlnx_enc_utils::*, xlnx_error::*}; use simple_error::SimpleError; -pub struct XlnxEncoder { +pub struct XlnxEncoder<'a> { enc_session: *mut XmaEncoderSession, pub out_buffer: *mut XmaDataBuffer, pub flush_frame_sent: bool, + encoder_ctx_lifetime: PhantomData>, } -impl XlnxEncoder { - pub fn new(xma_enc_props: &mut XmaEncoderProperties, xlnx_enc_ctx: &mut XlnxEncoderXrmCtx) -> Result { +impl<'a> XlnxEncoder<'a> { + pub fn new(xma_enc_props: &mut XmaEncoderProperties, xlnx_enc_ctx: &mut XlnxEncoderXrmCtx<'a>) -> Result { let enc_session = xlnx_create_enc_session(xma_enc_props, xlnx_enc_ctx)?; let buffer_size = xma_enc_props.height * xma_enc_props.width * xma_enc_props.bits_per_pixel; @@ -18,10 +21,11 @@ impl XlnxEncoder { enc_session, out_buffer, flush_frame_sent: false, + encoder_ctx_lifetime: PhantomData, }) } - /// Sends raw frames to Xilinx Encoder plugin and receives back decoded frames. + /// Sends raw frames to Xilinx Encoder plugin and receives back decoded frames. pub fn process_frame(&mut self, enc_in_frame: *mut XmaFrame, enc_null_frame: bool, enc_out_size: &mut i32) -> Result<(), XlnxError> { if !self.flush_frame_sent { match self.send_frame(enc_in_frame) { @@ -76,7 +80,7 @@ impl XlnxEncoder { } } -impl Drop for XlnxEncoder { +impl<'a> Drop for XlnxEncoder<'a> { fn drop(&mut self) { unsafe { if !self.enc_session.is_null() { diff --git a/xilinx/src/xlnx_scal_utils.rs b/xilinx/src/xlnx_scal_utils.rs index 14443df5..1e82a753 100644 --- a/xilinx/src/xlnx_scal_utils.rs +++ b/xilinx/src/xlnx_scal_utils.rs @@ -2,22 +2,22 @@ use libloading::{Library, Symbol}; use simple_error::{bail, SimpleError}; use std::{ffi::CString, os::raw::c_char, str::from_utf8}; -use crate::{strcpy_to_arr_i8, sys::*, xrm_precision_1000000_bitmask}; +use crate::{strcpy_to_arr_i8, sys::*, xrm_precision_1000000_bitmask, XrmContext}; const SCAL_PLUGIN_NAME: &[u8] = b"xrmU30ScalPlugin\0"; -pub struct XlnxScalerXrmCtx { +pub struct XlnxScalerXrmCtx<'a> { pub xrm_reserve_id: Option, pub device_id: Option, pub scal_load: i32, pub(crate) scal_res_in_use: bool, pub num_outputs: i32, - pub(crate) xrm_ctx: xrmContext, + pub(crate) xrm_ctx: &'a XrmContext, pub(crate) cu_res: Box, } -impl XlnxScalerXrmCtx { - pub fn new(xrm_ctx: xrmContext, device_id: Option, reserve_id: Option, scal_load: i32, num_outputs: i32) -> Self { +impl<'a> XlnxScalerXrmCtx<'a> { + pub fn new(xrm_ctx: &'a XrmContext, device_id: Option, reserve_id: Option, scal_load: i32, num_outputs: i32) -> Self { Self { xrm_reserve_id: reserve_id, device_id, @@ -31,7 +31,7 @@ impl XlnxScalerXrmCtx { } #[allow(clippy::not_unsafe_ptr_arg_deref)] -pub fn xlnx_calc_scal_load(xrm_ctx: xrmContext, xma_scal_props: *mut XmaScalerProperties) -> Result { +pub fn xlnx_calc_scal_load(xrm_ctx: &XrmContext, xma_scal_props: *mut XmaScalerProperties) -> Result { let func_id = 0; let mut plugin_param: xrmPluginFuncParam = Default::default(); unsafe { @@ -52,7 +52,7 @@ pub fn xlnx_calc_scal_load(xrm_ctx: xrmContext, xma_scal_props: *mut XmaScalerPr } unsafe { - let ret = xrmExecPluginFunc(xrm_ctx, SCAL_PLUGIN_NAME.as_ptr() as *mut i8, func_id, &mut plugin_param); + let ret = xrmExecPluginFunc(xrm_ctx.raw(), SCAL_PLUGIN_NAME.as_ptr() as *mut i8, func_id, &mut plugin_param); if ret != XRM_SUCCESS as i32 { bail!("XRM Scaler plugin failed to calculate scaler load. error: {}", ret); } @@ -99,12 +99,12 @@ pub fn xlnx_reserve_scal_resource(xlnx_scal_ctx: &mut XlnxScalerXrmCtx) -> Resul xlnx_fill_scal_pool_props(&mut cu_pool_prop, xlnx_scal_ctx.scal_load, xlnx_scal_ctx.device_id)?; unsafe { - let num_cu_pool = xrmCheckCuPoolAvailableNumV2(xlnx_scal_ctx.xrm_ctx, cu_pool_prop.as_mut()); + let num_cu_pool = xrmCheckCuPoolAvailableNumV2(xlnx_scal_ctx.xrm_ctx.raw(), cu_pool_prop.as_mut()); if num_cu_pool == 0 { bail!("no scaler resources available for allocation") } - let xrm_reserve_id = xrmCuPoolReserveV2(xlnx_scal_ctx.xrm_ctx, cu_pool_prop.as_mut(), cu_pool_res_infor.as_mut()); + let xrm_reserve_id = xrmCuPoolReserveV2(xlnx_scal_ctx.xrm_ctx.raw(), cu_pool_prop.as_mut(), cu_pool_res_infor.as_mut()); if xrm_reserve_id == 0 { bail!("failed to reserve scaler cu pool") } @@ -129,7 +129,7 @@ pub(crate) fn xlnx_create_scal_session( Ok(scal_session) } -fn xlnx_scal_cu_alloc(xma_scal_props: &mut XmaScalerProperties, xlnx_scal_ctx: &mut XlnxScalerXrmCtx) -> Result<(), SimpleError> { +fn xlnx_scal_cu_alloc(xma_scal_props: &mut XmaScalerProperties, xlnx_scal_ctx: &mut XlnxScalerXrmCtx<'_>) -> Result<(), SimpleError> { let mut scaler_cu_prop: Box = Box::new(Default::default()); strcpy_to_arr_i8(&mut scaler_cu_prop.kernelName, "scaler")?; @@ -157,7 +157,7 @@ fn xlnx_scal_cu_alloc(xma_scal_props: &mut XmaScalerProperties, xlnx_scal_ctx: & } } - if unsafe { xrmCuAllocV2(xlnx_scal_ctx.xrm_ctx, scaler_cu_prop.as_mut(), xlnx_scal_ctx.cu_res.as_mut()) } != XRM_SUCCESS as _ { + if unsafe { xrmCuAllocV2(xlnx_scal_ctx.xrm_ctx.raw(), scaler_cu_prop.as_mut(), xlnx_scal_ctx.cu_res.as_mut()) } != XRM_SUCCESS as _ { bail!( "failed to allocate scaler cu from reserve id {:?} and device id {:?}", xlnx_scal_ctx.xrm_reserve_id, @@ -177,17 +177,17 @@ fn xlnx_scal_cu_alloc(xma_scal_props: &mut XmaScalerProperties, xlnx_scal_ctx: & Ok(()) } -impl Drop for XlnxScalerXrmCtx { +impl<'a> Drop for XlnxScalerXrmCtx<'a> { fn drop(&mut self) { - if self.xrm_ctx.is_null() { - return; - } unsafe { + if self.xrm_ctx.raw().is_null() { + return; + } if let Some(xrm_reserve_id) = self.xrm_reserve_id { - let _ = xrmCuPoolRelinquishV2(self.xrm_ctx, xrm_reserve_id); + let _ = xrmCuPoolRelinquishV2(self.xrm_ctx.raw(), xrm_reserve_id); } if self.scal_res_in_use { - xrmCuReleaseV2(self.xrm_ctx, self.cu_res.as_mut()); + xrmCuReleaseV2(self.xrm_ctx.raw(), self.cu_res.as_mut()); } } } diff --git a/xilinx/src/xlnx_scaler.rs b/xilinx/src/xlnx_scaler.rs index b1e527b8..d0efa0f2 100644 --- a/xilinx/src/xlnx_scaler.rs +++ b/xilinx/src/xlnx_scaler.rs @@ -1,3 +1,5 @@ +use std::marker::PhantomData; + use crate::{sys::*, xlnx_error::*, xlnx_scal_utils::*}; use simple_error::SimpleError; @@ -5,15 +7,16 @@ pub const SCAL_MAX_ABR_CHANNELS: usize = 8; pub const SCAL_MAX_SESSIONS: usize = 2; pub const SCAL_RATE_STRING_LEN: usize = 8; -pub struct XlnxScaler { +pub struct XlnxScaler<'a> { scal_session: *mut XmaScalerSession, pub out_frame_list: Vec<*mut XmaFrame>, pub xrm_scalres_count: i32, pub flush_sent: bool, + scaler_ctx_lifetime: PhantomData>, } -impl XlnxScaler { - pub fn new(xma_scal_props: &mut XmaScalerProperties, xlnx_scal_ctx: &mut XlnxScalerXrmCtx) -> Result { +impl<'a> XlnxScaler<'a> { + pub fn new(xma_scal_props: &mut XmaScalerProperties, xlnx_scal_ctx: &mut XlnxScalerXrmCtx<'a>) -> Result { let scal_session = xlnx_create_scal_session(xma_scal_props, xlnx_scal_ctx)?; let mut out_frame_list = Vec::new(); @@ -46,6 +49,7 @@ impl XlnxScaler { out_frame_list, xrm_scalres_count: xma_scal_props.num_outputs, flush_sent: false, + scaler_ctx_lifetime: PhantomData, }) } @@ -94,7 +98,7 @@ impl XlnxScaler { } } -impl Drop for XlnxScaler { +impl<'a> Drop for XlnxScaler<'a> { fn drop(&mut self) { unsafe { if !self.scal_session.is_null() { diff --git a/xilinx/src/xlnx_transcoder_utils.rs b/xilinx/src/xlnx_transcoder_utils.rs index d8067830..b7054729 100644 --- a/xilinx/src/xlnx_transcoder_utils.rs +++ b/xilinx/src/xlnx_transcoder_utils.rs @@ -1,4 +1,4 @@ -use crate::{strcpy_to_arr_i8, sys::*, xlnx_dec_utils::*, xlnx_enc_utils::*, xlnx_scal_utils::*, xrm_precision_1000000_bitmask}; +use crate::{strcpy_to_arr_i8, sys::*, xlnx_dec_utils::*, xlnx_enc_utils::*, xlnx_scal_utils::*, xrm_precision_1000000_bitmask, XrmContext}; use simple_error::{bail, SimpleError}; /// This struct is used to hold the load information for the transcode @@ -13,17 +13,15 @@ pub struct XlnxTranscodeLoad { pub enc_loads: Vec, } -pub struct XlnxTranscodeXrmCtx { - pub xrm_ctx: xrmContext, +pub struct XlnxTranscodeXrmCtx<'a> { + pub xrm_ctx: &'a XrmContext, pub transcode_load: XlnxTranscodeLoad, pub xrm_reserve_id: Option, pub device_id: Option, } -impl XlnxTranscodeXrmCtx { - pub fn new() -> Self { - let xrm_ctx = unsafe { xrmCreateContext(XRM_API_VERSION_1) }; - +impl<'a> XlnxTranscodeXrmCtx<'a> { + pub fn new(xrm_ctx: &'a XrmContext) -> Self { Self { xrm_ctx, transcode_load: XlnxTranscodeLoad { @@ -132,11 +130,15 @@ pub fn xlnx_reserve_transcode_resource( &mut transcode_cu_pool_prop, )?; unsafe { - let num_cu_pool = xrmCheckCuPoolAvailableNumV2(xlnx_transcode_xrm_ctx.xrm_ctx, transcode_cu_pool_prop.as_mut()); + let num_cu_pool = xrmCheckCuPoolAvailableNumV2(xlnx_transcode_xrm_ctx.xrm_ctx.raw(), transcode_cu_pool_prop.as_mut()); if num_cu_pool <= 0 { bail!("no xilinx hardware resources avaliable for allocation") } - let xrm_reserve_id = xrmCuPoolReserveV2(xlnx_transcode_xrm_ctx.xrm_ctx, transcode_cu_pool_prop.as_mut(), cu_pool_res_infor.as_mut()); + let xrm_reserve_id = xrmCuPoolReserveV2( + xlnx_transcode_xrm_ctx.xrm_ctx.raw(), + transcode_cu_pool_prop.as_mut(), + cu_pool_res_infor.as_mut(), + ); if xrm_reserve_id == 0 { bail!("failed to reserve transcode cu pool") } @@ -146,23 +148,15 @@ pub fn xlnx_reserve_transcode_resource( Ok(cu_pool_res_infor) } -impl Default for XlnxTranscodeXrmCtx { - fn default() -> Self { - Self::new() - } -} - -impl Drop for XlnxTranscodeXrmCtx { +impl<'a> Drop for XlnxTranscodeXrmCtx<'a> { fn drop(&mut self) { - if self.xrm_ctx.is_null() { - return; - } unsafe { + if self.xrm_ctx.raw().is_null() { + return; + } if let Some(xrm_reserve_id) = self.xrm_reserve_id { - let _ = xrmCuPoolRelinquishV2(self.xrm_ctx, xrm_reserve_id); + let _ = xrmCuPoolRelinquishV2(self.xrm_ctx.raw(), xrm_reserve_id); } - - xrmDestroyContext(self.xrm_ctx); } } } diff --git a/xilinx/src/xrm_context.rs b/xilinx/src/xrm_context.rs new file mode 100644 index 00000000..ff5376a6 --- /dev/null +++ b/xilinx/src/xrm_context.rs @@ -0,0 +1,35 @@ +use crate::sys; + +/// A wrapper of the XrmContext which will correctly drop the context when dropped +pub struct XrmContext { + context: sys::xrmContext, +} + +impl XrmContext { + pub fn new() -> Self { + Self::default() + } + + /// SAFETY: If the `XrmContext` wrapping structure is dropped this raw value may + /// be freed. Do not use unless the source `XrmContext` still exists. + pub unsafe fn raw(&self) -> sys::xrmContext { + self.context + } +} + +impl Default for XrmContext { + fn default() -> Self { + let context = unsafe { sys::xrmCreateContext(sys::XRM_API_VERSION_1) }; + Self { context } + } +} + +impl Drop for XrmContext { + fn drop(&mut self) { + unsafe { + unsafe { + sys::xrmDestroyContext(self.context); + } + } + } +}