diff --git a/examples/transcode-audio.rs b/examples/transcode-audio.rs index eff780c4..d3190ca6 100644 --- a/examples/transcode-audio.rs +++ b/examples/transcode-audio.rs @@ -62,7 +62,7 @@ struct Transcoder { out_time_base: ffmpeg::Rational, } -fn transcoder>( +fn transcoder + ?Sized>( ictx: &mut format::context::Input, octx: &mut format::context::Output, path: &P, diff --git a/src/codec/codec.rs b/src/codec/codec.rs index 2e6c8cd0..0a1e1f45 100644 --- a/src/codec/codec.rs +++ b/src/codec/codec.rs @@ -7,24 +7,20 @@ use {media, Error}; #[derive(PartialEq, Eq, Copy, Clone)] pub struct Codec { - ptr: *mut AVCodec, + ptr: *const AVCodec, } unsafe impl Send for Codec {} unsafe impl Sync for Codec {} impl Codec { - pub unsafe fn wrap(ptr: *mut AVCodec) -> Self { + pub unsafe fn wrap(ptr: *const AVCodec) -> Self { Codec { ptr } } pub unsafe fn as_ptr(&self) -> *const AVCodec { self.ptr as *const _ } - - pub unsafe fn as_mut_ptr(&mut self) -> *mut AVCodec { - self.ptr - } } impl Codec { diff --git a/src/codec/context.rs b/src/codec/context.rs index 07b17c34..50d2e2e3 100644 --- a/src/codec/context.rs +++ b/src/codec/context.rs @@ -8,7 +8,7 @@ use super::{threading, Compliance, Debug, Flags, Id, Parameters}; use ffi::*; use libc::c_int; use media; -use {Codec, Error}; +use {Codec, Error, Rational}; pub struct Context { ptr: *mut AVCodecContext, @@ -41,6 +41,15 @@ impl Context { } } + pub fn new_with_codec(codec: Codec) -> Self { + unsafe { + Context { + ptr: avcodec_alloc_context3(codec.as_ptr()), + owner: None, + } + } + } + pub fn from_parameters>(parameters: P) -> Result { let parameters = parameters.into(); let mut context = Self::new(); @@ -129,6 +138,31 @@ impl Context { } } } + + pub fn time_base(&self) -> Rational { + unsafe { Rational::from((*self.as_ptr()).time_base) } + } + + pub fn set_time_base>(&mut self, value: R) { + unsafe { + (*self.as_mut_ptr()).time_base = value.into().into(); + } + } + + pub fn frame_rate(&self) -> Rational { + unsafe { Rational::from((*self.as_ptr()).framerate) } + } + + pub fn set_frame_rate>(&mut self, value: Option) { + unsafe { + if let Some(value) = value { + (*self.as_mut_ptr()).framerate = value.into().into(); + } else { + (*self.as_mut_ptr()).framerate.num = 0; + (*self.as_mut_ptr()).framerate.den = 1; + } + } + } } impl Default for Context { diff --git a/src/codec/decoder/decoder.rs b/src/codec/decoder/decoder.rs index 6990ab71..c7f69239 100644 --- a/src/codec/decoder/decoder.rs +++ b/src/codec/decoder/decoder.rs @@ -107,8 +107,14 @@ impl Decoder { } } - pub fn time_base(&self) -> Rational { - unsafe { Rational::from((*self.as_ptr()).time_base) } + pub fn packet_time_base(&self) -> Rational { + unsafe { Rational::from((*self.as_ptr()).pkt_timebase) } + } + + pub fn set_packet_time_base>(&mut self, value: R) { + unsafe { + (*self.as_mut_ptr()).pkt_timebase = value.into().into(); + } } } diff --git a/src/codec/encoder/encoder.rs b/src/codec/encoder/encoder.rs index 3dd507b4..2cd3723b 100644 --- a/src/codec/encoder/encoder.rs +++ b/src/codec/encoder/encoder.rs @@ -6,7 +6,7 @@ use libc::c_int; use super::{audio, subtitle, video}; use codec::Context; -use {media, packet, Error, Frame, Rational}; +use {media, packet, Error, Frame}; pub struct Encoder(pub Context); @@ -116,23 +116,6 @@ impl Encoder { } } } - - pub fn set_time_base>(&mut self, value: R) { - unsafe { - (*self.as_mut_ptr()).time_base = value.into().into(); - } - } - - pub fn set_frame_rate>(&mut self, value: Option) { - unsafe { - if let Some(value) = value { - (*self.as_mut_ptr()).framerate = value.into().into(); - } else { - (*self.as_mut_ptr()).framerate.num = 0; - (*self.as_mut_ptr()).framerate.den = 1; - } - } - } } impl Deref for Encoder { diff --git a/src/codec/packet/packet.rs b/src/codec/packet/packet.rs index 72a38ea7..dc0039d5 100644 --- a/src/codec/packet/packet.rs +++ b/src/codec/packet/packet.rs @@ -143,6 +143,18 @@ impl Packet { self.0.dts = value.unwrap_or(AV_NOPTS_VALUE); } + #[inline] + #[cfg(feature = "ffmpeg_5_0")] + pub fn time_base(&self) -> Rational { + self.0.time_base.into() + } + + #[inline] + #[cfg(feature = "ffmpeg_5_0")] + pub fn set_time_base(&mut self, value: Rational) { + self.0.time_base = value.into(); + } + #[inline] pub fn size(&self) -> usize { self.0.size as usize diff --git a/src/filter/context/sink.rs b/src/filter/context/sink.rs index 0c744e46..71801339 100644 --- a/src/filter/context/sink.rs +++ b/src/filter/context/sink.rs @@ -1,7 +1,7 @@ use super::Context; use ffi::*; use libc::c_int; -use {Error, Frame}; +use {Error, Frame, Rational}; pub struct Sink<'a> { ctx: &'a mut Context<'a>, @@ -41,4 +41,8 @@ impl<'a> Sink<'a> { av_buffersink_set_frame_size(self.ctx.as_mut_ptr(), value); } } + + pub fn time_base(&self) -> Rational { + unsafe { av_buffersink_get_time_base(self.ctx.as_ptr()) }.into() + } } diff --git a/src/format/context/output.rs b/src/format/context/output.rs index 7df5b0eb..3ab52c9e 100644 --- a/src/format/context/output.rs +++ b/src/format/context/output.rs @@ -9,7 +9,7 @@ use super::common::Context; use super::destructor; use codec::traits; use ffi::*; -use {format, ChapterMut, Dictionary, Error, Rational, StreamMut}; +use {codec, format, ChapterMut, Dictionary, Error, Rational, StreamMut}; pub struct Output { ptr: *mut AVFormatContext, @@ -90,6 +90,25 @@ impl Output { } } + pub fn add_stream_with(&mut self, context: &codec::Context) -> Result { + unsafe { + let ptr = avformat_new_stream(self.as_mut_ptr(), ptr::null()); + + if ptr.is_null() { + return Err(Error::Unknown); + } + + match avcodec_parameters_from_context((*ptr).codecpar, context.as_ptr()) { + 0 => (), + e => return Err(Error::from(e)), + } + + let index = (*self.ctx.as_ptr()).nb_streams - 1; + + Ok(StreamMut::wrap(&mut self.ctx, index as usize)) + } + } + pub fn add_chapter, S: AsRef>( &mut self, id: i64, diff --git a/src/format/format/output.rs b/src/format/format/output.rs index fdad3502..4cfd2d53 100644 --- a/src/format/format/output.rs +++ b/src/format/format/output.rs @@ -63,7 +63,7 @@ impl Output { } } - pub fn codec>(&self, path: &P, kind: media::Type) -> codec::Id { + pub fn codec + ?Sized>(&self, path: &P, kind: media::Type) -> codec::Id { // XXX: use to_cstring when stable let path = CString::new(path.as_ref().as_os_str().to_str().unwrap()).unwrap(); diff --git a/src/format/mod.rs b/src/format/mod.rs index 30ded96c..df389827 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -58,12 +58,12 @@ pub fn license() -> &'static str { } // XXX: use to_cstring when stable -fn from_path>(path: &P) -> CString { +fn from_path + ?Sized>(path: &P) -> CString { CString::new(path.as_ref().as_os_str().to_str().unwrap()).unwrap() } // NOTE: this will be better with specialization or anonymous return types -pub fn open>(path: &P, format: &Format) -> Result { +pub fn open + ?Sized>(path: &P, format: &Format) -> Result { unsafe { let mut ps = ptr::null_mut(); let path = from_path(path); @@ -100,7 +100,7 @@ pub fn open>(path: &P, format: &Format) -> Result } } -pub fn open_with>( +pub fn open_with + ?Sized>( path: &P, format: &Format, options: Dictionary, @@ -148,7 +148,7 @@ pub fn open_with>( } } -pub fn input>(path: &P) -> Result { +pub fn input + ?Sized>(path: &P) -> Result { unsafe { let mut ps = ptr::null_mut(); let path = from_path(path); @@ -167,7 +167,7 @@ pub fn input>(path: &P) -> Result { } } -pub fn input_with_dictionary>( +pub fn input_with_dictionary + ?Sized>( path: &P, options: Dictionary, ) -> Result { @@ -193,7 +193,7 @@ pub fn input_with_dictionary>( } } -pub fn input_with_interrupt, F>( +pub fn input_with_interrupt + ?Sized, F>( path: &P, closure: F, ) -> Result @@ -219,7 +219,7 @@ where } } -pub fn output>(path: &P) -> Result { +pub fn output + ?Sized>(path: &P) -> Result { unsafe { let mut ps = ptr::null_mut(); let path = from_path(path); @@ -235,7 +235,7 @@ pub fn output>(path: &P) -> Result { } } -pub fn output_with>( +pub fn output_with + ?Sized>( path: &P, options: Dictionary, ) -> Result { @@ -267,7 +267,10 @@ pub fn output_with>( } } -pub fn output_as>(path: &P, format: &str) -> Result { +pub fn output_as + ?Sized>( + path: &P, + format: &str, +) -> Result { unsafe { let mut ps = ptr::null_mut(); let path = from_path(path); @@ -289,7 +292,7 @@ pub fn output_as>(path: &P, format: &str) -> Result>( +pub fn output_as_with + ?Sized>( path: &P, format: &str, options: Dictionary,