Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use explicit lifetime instead of 'static for custom IO context #125

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions src/avformat/avformat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<AVIOContextContainer> = None,
AVFormatContextInput<'a>: ffi::AVFormatContext,
io_context: Option<AVIOContextContainer<'a>> = None,
}

impl AVFormatContextInput {
impl<'a> AVFormatContextInput<'a> {
/// Create a [`AVFormatContextInput`] instance of a file, and find info of
/// all streams.
///
Expand Down Expand Up @@ -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<Self> {
pub fn from_io_context(mut io_context: AVIOContextContainer<'a>) -> Result<Self> {
let input_format_context = {
// Only fails on no memory, so unwrap().
// `avformat_open_input`'s documentation:
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -209,22 +209,22 @@ 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) }
}
}

wrap! {
AVFormatContextOutput: ffi::AVFormatContext,
io_context: Option<AVIOContextContainer> = None,
AVFormatContextOutput<'a>: ffi::AVFormatContext,
io_context: Option<AVIOContextContainer<'a>> = 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<AVIOContextContainer>) -> Result<Self> {
pub fn create(filename: &CStr, io_context: Option<AVIOContextContainer<'a>>) -> Result<Self> {
let mut output_format_context = ptr::null_mut();

// Alloc the context
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down
37 changes: 18 additions & 19 deletions src/avformat/avio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
_opaque: Box<Opaque<'a>>,
}

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<dyn FnMut(&mut Vec<u8>, &mut [u8]) -> i32 + Send + 'static>;
pub type WritePacketCallback = Box<dyn FnMut(&mut Vec<u8>, &[u8]) -> i32 + Send + 'static>;
pub type SeekCallback = Box<dyn FnMut(&mut Vec<u8>, i64, i32) -> i64 + Send + 'static>;
pub type ReadPacketCallback<'a> = Box<dyn FnMut(&mut Vec<u8>, &mut [u8]) -> i32 + Send + 'a>;
pub type WritePacketCallback<'a> = Box<dyn FnMut(&mut Vec<u8>, &[u8]) -> i32 + Send + 'a>;
pub type SeekCallback<'a> = Box<dyn FnMut(&mut Vec<u8>, i64, i32) -> i64 + Send + 'a>;

pub struct Opaque {
pub struct Opaque<'a> {
data: Vec<u8>,
read_packet: Option<ReadPacketCallback>,
write_packet: Option<WritePacketCallback>,
seek: Option<SeekCallback>,
read_packet: Option<ReadPacketCallback<'a>>,
write_packet: Option<WritePacketCallback<'a>>,
seek: Option<SeekCallback<'a>>,
}

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<u8>,
read_packet: Option<ReadPacketCallback>,
write_packet: Option<WritePacketCallback>,
seek: Option<SeekCallback>,
read_packet: Option<ReadPacketCallback<'a>>,
write_packet: Option<WritePacketCallback<'a>>,
seek: Option<SeekCallback<'a>>,
) -> Self {
// According to the documentation of `avio_alloc_context`:
//
Expand Down Expand Up @@ -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 _,
Expand All @@ -140,8 +140,7 @@ impl AVIOContextCustom {
write_packet_c,
seek_c,
)
}
.upgrade()
})
.unwrap();

// If `AVIOContext` allocation successes, buffer is transferred to
Expand All @@ -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
Expand Down
16 changes: 8 additions & 8 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 _
}
Expand Down Expand Up @@ -50,21 +50,21 @@ 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 {
unsafe { self.something_should_not_be_touched_directly.as_ref() }
}
}

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>)? {}
};
}

Expand Down Expand Up @@ -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)*);
}
};
}
Expand Down
4 changes: 2 additions & 2 deletions tests/avio_writing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
4 changes: 2 additions & 2 deletions tests/transcode_aac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.")?;
Expand Down
4 changes: 2 additions & 2 deletions tests/transcoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ fn open_input_file(filename: &CStr) -> Result<(Vec<Option<AVCodecContext>>, 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<Option<AVCodecContext>>,
dict: &mut Option<AVDictionary>,
) -> Result<(Vec<Option<StreamContext>>, AVFormatContextOutput)> {
) -> Result<(Vec<Option<StreamContext>>, AVFormatContextOutput<'a>)> {
let mut output_format_context = AVFormatContextOutput::create(filename, None)?;
let mut stream_contexts = vec![];

Expand Down
Loading