diff --git a/src/decode.rs b/src/decode.rs index 3ad3733..e4a19f3 100644 --- a/src/decode.rs +++ b/src/decode.rs @@ -12,13 +12,70 @@ use crate::frame::FRAME_PIXEL_FORMAT; use crate::io::Reader; use crate::options::Options; use crate::packet::Packet; -use crate::{Error, Locator, RawFrame, Resize}; +use crate::{Error, Locator, RawFrame, Resize, StreamInfo}; #[cfg(feature = "ndarray")] use crate::{ffi::convert_frame_to_ndarray_rgb24, Frame, Time}; type Result = std::result::Result; +pub struct DecoderBuilder { + reader: Reader, + reader_stream_index: Option, + resize: Option, +} + +impl<'a> DecoderBuilder { + pub fn new(source: &Locator, reader_options: Option) -> Result { + let reader = match reader_options { + Some(options) => Reader::new_with_options(&source, &options)?, + None => Reader::new(&source)?, + }; + Ok(Self { + reader, + reader_stream_index: None, + resize: None, + }) + } + + pub fn build(self) -> Result { + let reader_stream_index = match self.reader_stream_index { + Some(index) => index, + None => self.reader.best_video_stream_index()?, + }; + + Ok(Decoder { + decoder: DecoderSplit::new(&self.reader, reader_stream_index, self.resize)?, + reader: self.reader, + reader_stream_index, + }) + } + + pub fn resize(mut self, resize: Resize) -> Self { + self.resize = Some(resize); + self + } + + pub fn reader_stream_index(mut self, selector: SelectorFn) -> Self + where + SelectorFn: FnOnce(Vec) -> usize, + { + let stream_infos = self + .reader + .input + .streams() + .enumerate() + .map(|(index, stream)| StreamInfo { + index, + codec_parameters: stream.parameters(), + time_base: stream.time_base(), + }) + .collect(); + self.reader_stream_index = Some(selector(stream_infos)); + self + } +} + /// Decode video files and streams. /// /// # Example @@ -38,70 +95,6 @@ pub struct Decoder { } impl Decoder { - /// Create a new decoder for the specified file. - /// - /// # Arguments - /// - /// * `source` - Locator to file to decode. - pub fn new(source: &Locator) -> Result { - let reader = Reader::new(source)?; - let reader_stream_index = reader.best_video_stream_index()?; - Ok(Self { - decoder: DecoderSplit::new(&reader, reader_stream_index, None)?, - reader, - reader_stream_index, - }) - } - - /// Create a new decoder for the specified file with input options. - /// - /// # Arguments - /// - /// * `source` - Locator to file to decode. - /// * `options` - The input options. - pub fn new_with_options(source: &Locator, options: &Options) -> Result { - let reader = Reader::new_with_options(source, options)?; - let reader_stream_index = reader.best_video_stream_index()?; - Ok(Self { - decoder: DecoderSplit::new(&reader, reader_stream_index, None)?, - reader, - reader_stream_index, - }) - } - - /// Create a new decoder for the specified file with input options and custom dimensions. Each - /// frame will be resized to the given dimensions. - /// - /// # Arguments - /// - /// * `source` - Locator to file to decode. - /// * `options` - The input options. - /// * `resize` - How to resize frames. - /// - /// # Example - /// - /// ```ignore - /// let decoder = Decoder::new_with_options_and_resize( - /// &PathBuf::from("video.mp4").into(), - /// Options::new_with_rtsp_transport_tcp(), - /// Resize::Exact(800, 600), - /// ) - /// .unwrap(); - /// ``` - pub fn new_with_options_and_resize( - source: &Locator, - options: &Options, - resize: Resize, - ) -> Result { - let reader = Reader::new_with_options(source, options)?; - let reader_stream_index = reader.best_video_stream_index()?; - Ok(Self { - decoder: DecoderSplit::new(&reader, reader_stream_index, Some(resize))?, - reader, - reader_stream_index, - }) - } - /// Get decoder time base. #[inline] pub fn time_base(&self) -> AvRational { diff --git a/src/lib.rs b/src/lib.rs index 46aed92..ac49766 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,7 @@ mod rtp; mod stream; mod time; -pub use decode::{Decoder, DecoderSplit}; +pub use decode::{Decoder, DecoderBuilder, DecoderSplit}; pub use encode::{Encoder, Settings as EncoderSettings}; pub use error::Error; pub use extradata::{Pps, Sps}; diff --git a/src/stream.rs b/src/stream.rs index bc7c576..3db02c3 100644 --- a/src/stream.rs +++ b/src/stream.rs @@ -12,8 +12,8 @@ type Result = std::result::Result; #[derive(Clone)] pub struct StreamInfo { pub index: usize, - codec_parameters: AvCodecParameters, - time_base: AvRational, + pub codec_parameters: AvCodecParameters, + pub time_base: AvRational, } impl StreamInfo {