Skip to content

Commit 6a541ca

Browse files
authored
Refactor codec::Parameters (shssoichiro#88)
* Split codec::Parameters into owned, ref, mut variants * Implement common functions via macro * Immutable AVCodecParameters API * Add `AsPtr` and `AsMutPtr` traits * Add missing API to StreamMut fn copy_parameters_from_context is more verbose but avoids an allocation. fn parameters_mut is necessary to ensure UB (before the refactor, fn parameters(&self) allowed mutation via unsafe code). * Add docs
1 parent 0fdfa9a commit 6a541ca

File tree

16 files changed

+415
-103
lines changed

16 files changed

+415
-103
lines changed

examples/remux.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fn main() {
3535
// issues when muxing into a different container format. Unfortunately
3636
// there's no high level API to do this (yet).
3737
unsafe {
38-
(*ost.parameters().as_mut_ptr()).codec_tag = 0;
38+
(*ost.parameters_mut().as_mut_ptr()).codec_tag = 0;
3939
}
4040
}
4141

examples/transcode-audio.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ fn transcoder<P: AsRef<Path>>(
135135
output.set_time_base((1, decoder.rate() as i32));
136136

137137
let encoder = encoder.open_as(codec)?;
138-
output.set_parameters(&encoder);
138+
output.copy_parameters_from_context(&encoder);
139139

140140
let filter = filter(filter_spec, &decoder, &encoder)?;
141141

examples/transcode-x264.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ impl Transcoder {
7070
encoder = codec::context::Context::from_parameters(ost.parameters())?
7171
.encoder()
7272
.video()?;
73-
ost.set_parameters(&encoder);
73+
ost.copy_parameters_from_context(&encoder);
7474
Ok(Self {
7575
ost_index,
7676
decoder,
@@ -224,7 +224,7 @@ fn main() {
224224
// issues when muxing into a different container format. Unfortunately
225225
// there's no high level API to do this (yet).
226226
unsafe {
227-
(*ost.parameters().as_mut_ptr()).codec_tag = 0;
227+
(*ost.parameters_mut().as_mut_ptr()).codec_tag = 0;
228228
}
229229
}
230230
ost_index += 1;

src/as_ptr.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
pub trait AsPtr<T> {
2+
/// Returns a *const raw pointer to the underlying FFmpeg type.
3+
fn as_ptr(&self) -> *const T;
4+
}
5+
6+
pub trait AsMutPtr<T> {
7+
/// Returns a *mut raw pointer to the underlying FFmpeg type.
8+
fn as_mut_ptr(&mut self) -> *mut T;
9+
}

src/codec/context.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ use std::rc::Rc;
44

55
use super::decoder::Decoder;
66
use super::encoder::Encoder;
7-
use super::{threading, Compliance, Debug, Flags, Id, Parameters};
7+
use super::{threading, Compliance, Debug, Flags, Id};
88
use crate::ffi::*;
99
use crate::media;
10+
use crate::AsPtr;
1011
use crate::{Codec, Error};
1112
use libc::c_int;
1213

@@ -41,8 +42,7 @@ impl Context {
4142
}
4243
}
4344

44-
pub fn from_parameters<P: Into<Parameters>>(parameters: P) -> Result<Self, Error> {
45-
let parameters = parameters.into();
45+
pub fn from_parameters<P: AsPtr<AVCodecParameters>>(parameters: P) -> Result<Self, Error> {
4646
let mut context = Self::new();
4747

4848
unsafe {
@@ -113,9 +113,10 @@ impl Context {
113113
}
114114
}
115115

116-
pub fn set_parameters<P: Into<Parameters>>(&mut self, parameters: P) -> Result<(), Error> {
117-
let parameters = parameters.into();
118-
116+
pub fn set_parameters<P: AsPtr<AVCodecParameters>>(
117+
&mut self,
118+
parameters: P,
119+
) -> Result<(), Error> {
119120
unsafe {
120121
match avcodec_parameters_to_context(self.as_mut_ptr(), parameters.as_ptr()) {
121122
e if e < 0 => Err(Error::from(e)),

src/codec/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub mod codec;
2828
pub use self::codec::{Audio, Codec, Video};
2929

3030
pub mod parameters;
31-
pub use self::parameters::Parameters;
31+
pub use self::parameters::{Parameters, ParametersMut, ParametersRef};
3232

3333
pub mod audio_service;
3434
pub mod field_order;

src/codec/parameters.rs

Lines changed: 0 additions & 88 deletions
This file was deleted.

src/codec/parameters/borrowed.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
use std::marker::PhantomData;
2+
use std::ptr::NonNull;
3+
4+
use crate::ffi::*;
5+
use crate::AsPtr;
6+
7+
pub struct ParametersRef<'p> {
8+
ptr: NonNull<AVCodecParameters>,
9+
_marker: PhantomData<&'p AVCodecParameters>,
10+
}
11+
12+
impl<'p> ParametersRef<'p> {
13+
/// # Safety
14+
///
15+
/// Ensure that
16+
/// - `ptr` is either null or valid,
17+
/// - the shared borrow represented by `ptr` follows Rust borrow rules and
18+
/// - the lifetime of the returned struct is correctly bounded.
19+
pub unsafe fn from_raw(ptr: *const AVCodecParameters) -> Option<Self> {
20+
NonNull::new(ptr as *mut _).map(|ptr| Self {
21+
ptr,
22+
_marker: PhantomData,
23+
})
24+
}
25+
26+
/// Exposes a pointer to the contained [`AVCodecParameters`] for FFI purposes.
27+
///
28+
/// This is guaranteed to be a non-null pointer.
29+
pub fn as_ptr(&self) -> *const AVCodecParameters {
30+
self.ptr.as_ptr()
31+
}
32+
}
33+
34+
impl<'p> AsPtr<AVCodecParameters> for ParametersRef<'p> {
35+
fn as_ptr(&self) -> *const AVCodecParameters {
36+
self.ptr.as_ptr()
37+
}
38+
}

src/codec/parameters/borrowed_mut.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use std::marker::PhantomData;
2+
use std::ptr::NonNull;
3+
4+
use crate::ffi::*;
5+
use crate::{AsMutPtr, AsPtr};
6+
7+
pub struct ParametersMut<'p> {
8+
ptr: NonNull<AVCodecParameters>,
9+
_marker: PhantomData<&'p mut AVCodecParameters>,
10+
}
11+
12+
impl<'p> ParametersMut<'p> {
13+
/// # Safety
14+
///
15+
/// Ensure that
16+
/// - `ptr` is either null or valid,
17+
/// - the mutable borrow represented by `ptr` follows Rust borrow rules and
18+
/// - the lifetime of the returned struct is correctly bounded.
19+
pub unsafe fn from_raw(ptr: *mut AVCodecParameters) -> Option<Self> {
20+
NonNull::new(ptr as *mut _).map(|ptr| Self {
21+
ptr,
22+
_marker: PhantomData,
23+
})
24+
}
25+
26+
/// Exposes a pointer to the contained [`AVCodecParameters`] for FFI purposes.
27+
///
28+
/// This is guaranteed to be a non-null pointer.
29+
pub fn as_ptr(&self) -> *const AVCodecParameters {
30+
self.ptr.as_ptr()
31+
}
32+
33+
/// Exposes a mutable pointer to the contained [`AVCodecParameters`] for FFI purposes.
34+
///
35+
/// This is guaranteed to be a non-null pointer.
36+
pub fn as_mut_ptr(&mut self) -> *mut AVCodecParameters {
37+
self.ptr.as_ptr()
38+
}
39+
}
40+
41+
impl<'p> AsPtr<AVCodecParameters> for ParametersMut<'p> {
42+
fn as_ptr(&self) -> *const AVCodecParameters {
43+
self.as_ptr()
44+
}
45+
}
46+
47+
impl<'p> AsMutPtr<AVCodecParameters> for ParametersMut<'p> {
48+
fn as_mut_ptr(&mut self) -> *mut AVCodecParameters {
49+
self.as_mut_ptr()
50+
}
51+
}

0 commit comments

Comments
 (0)