diff --git a/examples/transcode-audio.rs b/examples/transcode-audio.rs index 2513e97..ce8f339 100644 --- a/examples/transcode-audio.rs +++ b/examples/transcode-audio.rs @@ -47,10 +47,12 @@ struct Transcoder { fn transcoder>(ictx: &mut format::context::Input, octx: &mut format::context::Output, path: &P, filter_spec: &str) -> Result { let input = ictx.streams().best(media::Type::Audio).expect("could not find best audio stream"); - let decoder = try!(input.codec().decoder().audio()); + let mut decoder = try!(input.codec().decoder().audio()); let codec = try!(ffmpeg::encoder::find(octx.format().codec(path, media::Type::Audio)).expect("failed to find encoder").audio()); let global = octx.format().flags().contains(ffmpeg::format::flag::GLOBAL_HEADER); + try!(decoder.set_parameters(input.codec_parameters())); + let mut output = try!(octx.add_stream(codec)); let mut encoder = try!(output.codec().encoder().audio()); @@ -73,6 +75,8 @@ fn transcoder>(ictx: &mut format::context::Input, octx: &mut form output.set_time_base((1, decoder.rate() as i32)); let encoder = try!(encoder.open_as(codec)); + try!(output.set_codec_parameters_from(&encoder)); + let filter = try!(filter(filter_spec, &decoder, &encoder)); Ok(Transcoder { diff --git a/src/codec/context.rs b/src/codec/context.rs index 549e264..cee7911 100644 --- a/src/codec/context.rs +++ b/src/codec/context.rs @@ -4,8 +4,8 @@ use std::rc::Rc; use libc::c_int; use ffi::*; use ::media; -use ::Codec; -use super::{Flags, Id, Debug, Compliance, threading}; +use ::{Codec, Error}; +use super::{Flags, Id, Debug, Compliance, threading, Parameters}; use super::decoder::Decoder; use super::encoder::Encoder; @@ -103,6 +103,15 @@ impl Context { } } } + + pub fn set_parameters(&mut self, params: &Parameters) -> Result<(), Error> { + unsafe { + match avcodec_parameters_to_context(self.as_mut_ptr(), params.as_ptr()) { + e if e < 0 => Err(Error::from(e)), + _ => Ok(()), + } + } + } } impl Drop for Context { diff --git a/src/codec/mod.rs b/src/codec/mod.rs index 65821f0..b17dc36 100644 --- a/src/codec/mod.rs +++ b/src/codec/mod.rs @@ -20,6 +20,9 @@ pub use self::capabilities::Capabilities; pub mod codec; +pub mod parameters; +pub use self::parameters::Parameters; + pub mod video; pub use self::video::Video; diff --git a/src/codec/parameters.rs b/src/codec/parameters.rs new file mode 100644 index 0000000..28fb60b --- /dev/null +++ b/src/codec/parameters.rs @@ -0,0 +1,57 @@ +use std::rc::Rc; + +use ffi::*; + +pub struct Parameters { + ptr: *mut AVCodecParameters, + owner: Option>, +} + +unsafe impl Send for Parameters { } + +impl Parameters { + pub unsafe fn wrap(ptr: *mut AVCodecParameters, owner: Option>) -> Self { + Parameters { ptr: ptr, owner: owner } + } + + pub unsafe fn as_ptr(&self) -> *const AVCodecParameters { + self.ptr as *const _ + } + + pub unsafe fn as_mut_ptr(&mut self) -> *mut AVCodecParameters { + self.ptr + } +} + +impl Parameters { + pub fn new() -> Self { + unsafe { + Parameters { ptr: avcodec_parameters_alloc(), owner: None } + } + } +} + +impl Drop for Parameters { + fn drop(&mut self) { + unsafe { + if self.owner.is_none() { + avcodec_parameters_free(&mut self.as_mut_ptr()); + } + } + } +} + +impl Clone for Parameters { + fn clone(&self) -> Self { + let mut ctx = Parameters::new(); + ctx.clone_from(self); + + ctx + } + + fn clone_from(&mut self, source: &Self) { + unsafe { + avcodec_parameters_copy(self.as_mut_ptr(), source.as_ptr()); + } + } +} diff --git a/src/format/stream/stream.rs b/src/format/stream/stream.rs index eb236de..5d1753a 100644 --- a/src/format/stream/stream.rs +++ b/src/format/stream/stream.rs @@ -27,6 +27,12 @@ impl<'a> Stream<'a> { } } + pub fn codec_parameters(&self) -> codec::Parameters { + unsafe { + codec::Parameters::wrap((*self.as_ptr()).codecpar, Some(self.context.destructor())) + } + } + pub fn index(&self) -> usize { unsafe { (*self.as_ptr()).index as usize diff --git a/src/format/stream/stream_mut.rs b/src/format/stream/stream_mut.rs index bbce344..c044995 100644 --- a/src/format/stream/stream_mut.rs +++ b/src/format/stream/stream_mut.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use std::mem; use ffi::*; -use ::Rational; +use ::{Rational, Error}; use super::Stream; use format::context::common::Context; @@ -40,6 +40,15 @@ impl<'a> StreamMut<'a> { av_stream_set_r_frame_rate(self.as_mut_ptr(), value.into().into()); } } + + pub fn set_codec_parameters_from(&mut self, context: &::codec::Context) -> Result<(), Error> { + unsafe { + match avcodec_parameters_from_context((*self.as_mut_ptr()).codecpar, context.as_ptr()) { + e if e < 0 => Err(Error::from(e)), + _ => Ok(()), + } + } + } } impl<'a> Deref for StreamMut<'a> {