diff --git a/examples/transcode-audio.rs b/examples/transcode-audio.rs index 71e3a3bf..9f9a7f3c 100644 --- a/examples/transcode-audio.rs +++ b/examples/transcode-audio.rs @@ -123,24 +123,25 @@ fn main() { let in_time_base = transcoder.decoder.time_base(); let out_time_base = octx.stream(0).unwrap().time_base(); - let mut decoded = frame::Audio::empty(); let mut encoded = ffmpeg::Packet::empty(); for (stream, mut packet) in ictx.packets() { if stream.index() == transcoder.stream { packet.rescale_ts(stream.time_base(), in_time_base); - if let Ok(true) = transcoder.decoder.decode(&packet, &mut decoded) { - let timestamp = decoded.timestamp(); - decoded.set_pts(timestamp); + for decoded in transcoder.decoder.decode_iter(&packet) { + if let Ok(Some(mut decoded)) = decoded { + let timestamp = decoded.timestamp(); + decoded.set_pts(timestamp); - transcoder.filter.get("in").unwrap().source().add(&decoded).unwrap(); + transcoder.filter.get("in").unwrap().source().add(&decoded).unwrap(); - while let Ok(..) = transcoder.filter.get("out").unwrap().sink().frame(&mut decoded) { - if let Ok(true) = transcoder.encoder.encode(&decoded, &mut encoded) { - encoded.set_stream(0); - encoded.rescale_ts(in_time_base, out_time_base); - encoded.write_interleaved(&mut octx).unwrap(); + while let Ok(..) = transcoder.filter.get("out").unwrap().sink().frame(&mut decoded) { + if let Ok(true) = transcoder.encoder.encode(&decoded, &mut encoded) { + encoded.set_stream(0); + encoded.rescale_ts(in_time_base, out_time_base); + encoded.write_interleaved(&mut octx).unwrap(); + } } } } @@ -149,6 +150,8 @@ fn main() { transcoder.filter.get("in").unwrap().source().flush().unwrap(); + let mut decoded = frame::Audio::empty(); + while let Ok(..) = transcoder.filter.get("out").unwrap().sink().frame(&mut decoded) { if let Ok(true) = transcoder.encoder.encode(&decoded, &mut encoded) { encoded.set_stream(0); diff --git a/src/codec/decoder/audio.rs b/src/codec/decoder/audio.rs index e040d1c6..ea1d87fb 100644 --- a/src/codec/decoder/audio.rs +++ b/src/codec/decoder/audio.rs @@ -4,7 +4,8 @@ use libc::c_int; use ffi::*; use super::Opened; -use ::{packet, Error, AudioService, ChannelLayout}; +use ::{Error, AudioService, ChannelLayout}; +use ::packet::{self, Mut, Packet}; use ::frame; use ::util::format; use ::codec::Context; @@ -23,6 +24,10 @@ impl Audio { } } + pub fn decode_iter<'a, 'b>(&'a mut self, packet: &'b Packet) -> AudioFrameIter<'a, 'b> { + AudioFrameIter::new(self, packet) + } + pub fn rate(&self) -> u32 { unsafe { (*self.as_ptr()).sample_rate as u32 @@ -130,3 +135,53 @@ impl AsMut for Audio { &mut self.0 } } + +pub struct AudioFrameIter<'a, 'b> { + audio: &'a mut Audio, + _packet: &'b Packet, + packet: Packet, +} + +impl<'a, 'b> AudioFrameIter<'a, 'b> { + fn new(audio: &'a mut Audio, packet: &'b Packet) -> AudioFrameIter<'a, 'b> { + let mut copied = Packet::empty(); + copied.clone_from(packet); + + AudioFrameIter { + audio: audio, + _packet: packet, + packet: copied, + } + } +} + +impl<'a, 'b> Iterator for AudioFrameIter<'a, 'b> { + type Item = Result, Error>; + + fn next(&mut self) -> Option { + if self.packet.size() != 0 { + let mut frame = frame::Audio::empty(); + let mut got: c_int = 0; + + unsafe { + let avpkt = self.packet.as_mut_ptr(); + + match avcodec_decode_audio4(self.audio.as_mut_ptr(), frame.as_mut_ptr(), &mut got, avpkt) { + e if e < 0 => Some(Err(Error::from(e))), + n => { + (*avpkt).data = (*avpkt).data.offset(n as isize); + (*avpkt).size -= n; + + if got != 0 { + Some(Ok(Some(frame))) + } else { + Some(Ok(None)) + } + } + } + } + } else { + None + } + } +} diff --git a/src/util/frame/mod.rs b/src/util/frame/mod.rs index 8b609090..38ec94b6 100644 --- a/src/util/frame/mod.rs +++ b/src/util/frame/mod.rs @@ -182,8 +182,10 @@ impl Frame { impl Drop for Frame { #[inline] fn drop(&mut self) { - unsafe { - av_frame_free(&mut self.as_mut_ptr()); + if self._own { + unsafe { + av_frame_free(&mut self.as_mut_ptr()); + } } } }