From 8d7d2bd3aab5b810f1278f2ce2ed09d876f4e8cb Mon Sep 17 00:00:00 2001 From: Kevin Rauwolf Date: Mon, 25 Sep 2023 14:40:24 -0700 Subject: [PATCH] Use explicit lifetime instead of 'static for custom IO context --- src/avformat/avformat.rs | 28 ++++++++++++++-------------- src/avformat/avio.rs | 37 ++++++++++++++++++------------------- src/macros.rs | 16 ++++++++-------- tests/avio_writing.rs | 4 ++-- tests/transcode_aac.rs | 4 ++-- tests/transcoding.rs | 4 ++-- 6 files changed, 46 insertions(+), 47 deletions(-) diff --git a/src/avformat/avformat.rs b/src/avformat/avformat.rs index 3ac4b63..8e32709 100644 --- a/src/avformat/avformat.rs +++ b/src/avformat/avformat.rs @@ -17,17 +17,17 @@ use crate::{ }; /// Container of all kinds of AVIOContexts. -pub enum AVIOContextContainer { +pub enum AVIOContextContainer<'a> { Url(AVIOContextURL), - Custom(AVIOContextCustom), + Custom(AVIOContextCustom<'a>), } wrap! { - AVFormatContextInput: ffi::AVFormatContext, - io_context: Option = None, + AVFormatContextInput<'a>: ffi::AVFormatContext, + io_context: Option> = None, } -impl AVFormatContextInput { +impl<'a> AVFormatContextInput<'a> { /// Create a [`AVFormatContextInput`] instance of a file, and find info of /// all streams. /// @@ -80,7 +80,7 @@ impl AVFormatContextInput { /// Create a [`AVFormatContextInput`] instance from an [`AVIOContext`], and find info of /// all streams. - pub fn from_io_context(mut io_context: AVIOContextContainer) -> Result { + pub fn from_io_context(mut io_context: AVIOContextContainer<'a>) -> Result { let input_format_context = { // Only fails on no memory, so unwrap(). // `avformat_open_input`'s documentation: @@ -181,7 +181,7 @@ impl AVFormatContextInput { } } -impl<'stream> AVFormatContextInput { +impl<'stream, 'a> AVFormatContextInput<'a> { /// Get Iterator of all [`AVStream`]s in the [`ffi::AVFormatContext`]. pub fn streams(&'stream self) -> AVStreamRefs<'stream> { AVStreamRefs { @@ -209,7 +209,7 @@ impl<'stream> AVFormatContextInput { } } -impl Drop for AVFormatContextInput { +impl<'a> Drop for AVFormatContextInput<'a> { fn drop(&mut self) { let mut context = self.as_mut_ptr(); unsafe { ffi::avformat_close_input(&mut context) } @@ -217,14 +217,14 @@ impl Drop for AVFormatContextInput { } wrap! { - AVFormatContextOutput: ffi::AVFormatContext, - io_context: Option = None, + AVFormatContextOutput<'a>: ffi::AVFormatContext, + io_context: Option> = None, } -impl AVFormatContextOutput { +impl<'a> AVFormatContextOutput<'a> { /// Open a file and create a [`AVFormatContextOutput`] instance of that /// file. Give it an [`AVIOContext`] if you want custom IO. - pub fn create(filename: &CStr, io_context: Option) -> Result { + pub fn create(filename: &CStr, io_context: Option>) -> Result { let mut output_format_context = ptr::null_mut(); // Alloc the context @@ -343,7 +343,7 @@ impl AVFormatContextOutput { } } -impl<'stream> AVFormatContextOutput { +impl<'stream, 'a> AVFormatContextOutput<'a> { /// Return Iterator of [`AVStreamRef`]. pub fn streams(&'stream self) -> AVStreamRefs<'stream> { AVStreamRefs { @@ -381,7 +381,7 @@ impl<'stream> AVFormatContextOutput { } } -impl Drop for AVFormatContextOutput { +impl<'a> Drop for AVFormatContextOutput<'a> { fn drop(&mut self) { // Here we drop the io context, which won't be touched by // avformat_free_context, so let it dangling is safe. diff --git a/src/avformat/avio.rs b/src/avformat/avio.rs index 1e51d65..8d87619 100644 --- a/src/avformat/avio.rs +++ b/src/avformat/avio.rs @@ -49,44 +49,44 @@ impl Drop for AVIOContextURL { } /// Custom [`AVIOContext`], used for custom IO. -pub struct AVIOContextCustom { +pub struct AVIOContextCustom<'a> { inner: AVIOContext, - _opaque: Box, + _opaque: Box>, } -impl Deref for AVIOContextCustom { +impl<'a> Deref for AVIOContextCustom<'a> { type Target = AVIOContext; fn deref(&self) -> &Self::Target { &self.inner } } -impl std::ops::DerefMut for AVIOContextCustom { +impl<'a> std::ops::DerefMut for AVIOContextCustom<'a> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } } -pub type ReadPacketCallback = Box, &mut [u8]) -> i32 + Send + 'static>; -pub type WritePacketCallback = Box, &[u8]) -> i32 + Send + 'static>; -pub type SeekCallback = Box, i64, i32) -> i64 + Send + 'static>; +pub type ReadPacketCallback<'a> = Box, &mut [u8]) -> i32 + Send + 'a>; +pub type WritePacketCallback<'a> = Box, &[u8]) -> i32 + Send + 'a>; +pub type SeekCallback<'a> = Box, i64, i32) -> i64 + Send + 'a>; -pub struct Opaque { +pub struct Opaque<'a> { data: Vec, - read_packet: Option, - write_packet: Option, - seek: Option, + read_packet: Option>, + write_packet: Option>, + seek: Option>, } -impl AVIOContextCustom { +impl<'a> AVIOContextCustom<'a> { /// `write_flag` - set to `false` on read, set to `true` on write. pub fn alloc_context( mut buffer: AVMem, write_flag: bool, data: Vec, - read_packet: Option, - write_packet: Option, - seek: Option, + read_packet: Option>, + write_packet: Option>, + seek: Option>, ) -> Self { // According to the documentation of `avio_alloc_context`: // @@ -130,7 +130,7 @@ impl AVIOContextCustom { // After reading the implementation, avio_alloc_context only fails on no // memory. - let context = unsafe { + let context = NonNull::new(unsafe { ffi::avio_alloc_context( buffer.as_mut_ptr(), buffer.len as _, @@ -140,8 +140,7 @@ impl AVIOContextCustom { write_packet_c, seek_c, ) - } - .upgrade() + }) .unwrap(); // If `AVIOContext` allocation successes, buffer is transferred to @@ -156,7 +155,7 @@ impl AVIOContextCustom { } } -impl Drop for AVIOContextCustom { +impl<'a> Drop for AVIOContextCustom<'a> { fn drop(&mut self) { // Recover the `AVMem` fom the buffer and drop it. We don't attach the // AVMem to this type because according to the documentation, the buffer diff --git a/src/macros.rs b/src/macros.rs index c1ef316..c01371f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -4,16 +4,16 @@ /// Wrapping with XXX -> XXX mapping. macro_rules! wrap_pure { ( - ($wrapped_type: ident): $ffi_type: ty + ($wrapped_type: ident)$(<$lt:lifetime>)?: $ffi_type: ty $(,$attach: ident: $attach_type: ty = $attach_default: expr)* ) => { - pub struct $wrapped_type { + pub struct $wrapped_type$(<$lt>)? { something_should_not_be_touched_directly: std::ptr::NonNull<$ffi_type>, // Publicize the attachment, can be directly changed without deref_mut() $(pub $attach: $attach_type,)* } - impl $wrapped_type { + impl$(<$lt>)? $wrapped_type$(<$lt>)? { pub fn as_ptr(&self) -> *const $ffi_type { self.something_should_not_be_touched_directly.as_ptr() as *const _ } @@ -50,7 +50,7 @@ macro_rules! wrap_pure { } } - impl std::ops::Deref for $wrapped_type { + impl$(<$lt>)? std::ops::Deref for $wrapped_type$(<$lt>)? { type Target = $ffi_type; fn deref(&self) -> &Self::Target { @@ -58,13 +58,13 @@ macro_rules! wrap_pure { } } - impl crate::shared::UnsafeDerefMut for $wrapped_type { + impl$(<$lt>)? crate::shared::UnsafeDerefMut for $wrapped_type$(<$lt>)? { unsafe fn deref_mut(&mut self) -> &mut Self::Target { unsafe { self.something_should_not_be_touched_directly.as_mut() } } } - unsafe impl Send for $wrapped_type {} + unsafe impl$(<$lt>)? Send for $wrapped_type$(<$lt>)? {} }; } @@ -191,11 +191,11 @@ macro_rules! wrap_mut { /// Wrapping with XXX, XXX -> XXX. macro_rules! wrap { ( - $name: ident: $ffi_type: ty + $name: ident$(<$lt:lifetime>)?: $ffi_type: ty $(,$attach: ident: $attach_type: ty = $attach_default: expr)* $(,)? ) => { paste::paste! { - wrap_pure!(($name): $ffi_type $(,$attach: $attach_type = $attach_default)*); + wrap_pure!(($name)$(<$lt>)?: $ffi_type $(,$attach: $attach_type = $attach_default)*); } }; } diff --git a/tests/avio_writing.rs b/tests/avio_writing.rs index e26e76c..1502bf4 100644 --- a/tests/avio_writing.rs +++ b/tests/avio_writing.rs @@ -45,10 +45,10 @@ fn open_input_file(filename: &CStr) -> Result<(usize, AVFormatContextInput, AVCo } /// Return output_format_context and encode_context -fn open_output_file( +fn open_output_file<'a>( filename: &CStr, decode_context: &AVCodecContext, -) -> Result<(AVFormatContextOutput, AVCodecContext)> { +) -> Result<(AVFormatContextOutput<'a>, AVCodecContext)> { let buffer = Arc::new(Mutex::new(File::create(filename.to_str()?)?)); let buffer1 = buffer.clone(); diff --git a/tests/transcode_aac.rs b/tests/transcode_aac.rs index 0791d4b..ddd2e57 100644 --- a/tests/transcode_aac.rs +++ b/tests/transcode_aac.rs @@ -30,10 +30,10 @@ fn open_input_file(input_file: &CStr) -> Result<(AVFormatContextInput, AVCodecCo Ok((input_format_context, decode_context, audio_index)) } -fn open_output_file( +fn open_output_file<'a>( output_file: &CStr, decode_context: &AVCodecContext, -) -> Result<(AVFormatContextOutput, AVCodecContext)> { +) -> Result<(AVFormatContextOutput<'a>, AVCodecContext)> { // Create a new format context for the output container format. let mut output_format_context = AVFormatContextOutput::create(output_file, None).context("Failed to open output file.")?; diff --git a/tests/transcoding.rs b/tests/transcoding.rs index 79e385a..1bfc108 100644 --- a/tests/transcoding.rs +++ b/tests/transcoding.rs @@ -77,11 +77,11 @@ fn open_input_file(filename: &CStr) -> Result<(Vec>, AVFo /// Accepts a output filename, attach `encode_context` to the corresponding /// `decode_context` and wrap them into a `stream_context`. `stream_context` is /// None when the given `decode_context` in the same index is None. -fn open_output_file( +fn open_output_file<'a>( filename: &CStr, decode_contexts: Vec>, dict: &mut Option, -) -> Result<(Vec>, AVFormatContextOutput)> { +) -> Result<(Vec>, AVFormatContextOutput<'a>)> { let mut output_format_context = AVFormatContextOutput::create(filename, None)?; let mut stream_contexts = vec![];