diff --git a/.gitignore b/.gitignore index 96ef6c0..95dfa36 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target Cargo.lock +*.png diff --git a/examples/simple.rs b/examples/simple.rs new file mode 100644 index 0000000..d58c899 --- /dev/null +++ b/examples/simple.rs @@ -0,0 +1,18 @@ +use std::path::Path; +use std::fs::File; +use std::io::Write; + +// Capture fist frame of the video file +fn main() { + let file_path = Path::new("resources/video.mp4"); + let mut first_frame = File::create("first_frame.png").unwrap(); + + let frame_source = vid2img::FileSource::new(file_path, (1280, 534)).unwrap(); + for frame in frame_source.into_iter() { + if let Ok(Some(png_img_data)) = frame { + println!("{}", png_img_data.len()); + first_frame.write_all(&png_img_data).unwrap(); + break; + } + } +} diff --git a/resources/video.mp4 b/resources/video.mp4 new file mode 100644 index 0000000..12c29e3 Binary files /dev/null and b/resources/video.mp4 differ diff --git a/src/file.rs b/src/file.rs index 1ce770b..b28b088 100644 --- a/src/file.rs +++ b/src/file.rs @@ -1,6 +1,8 @@ use crate::StreamError; use crate::{FrameData, VideoStream, VideoStreamIterator}; use std::path::{Path, PathBuf}; +use std::fs; +use std::io; pub struct FileSource { source: PathBuf, @@ -9,11 +11,12 @@ pub struct FileSource { impl FileSource { pub fn new(source: &Path, frame_size: (u32, u32)) -> Result { + let source = fs::canonicalize(source)?; if !source.exists() { return Err(CaptureError::FileNotFound); } Ok(Self { - source: source.to_path_buf(), + source, frame_size, }) } @@ -34,6 +37,14 @@ impl IntoIterator for FileSource { } } +#[derive(Debug)] pub enum CaptureError { + IoError(io::Error), FileNotFound, } + +impl From for CaptureError { + fn from(err: io::Error) -> Self { + CaptureError::IoError(err) + } +} diff --git a/src/lib.rs b/src/lib.rs index b9e25c2..f86b7e1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,12 +14,11 @@ //! //! ```no_run //! use std::path::Path; -//! use vid2img::FileSource; //! //! fn main() { //! let file_path = Path::new("video.mp4"); //! -//! let frame_source = FileSource::new(file_path, (200, 200)).unwrap(); +//! let frame_source = vid2img::FileSource::new(file_path, (200, 200)).unwrap(); //! for frame in frame_source.into_iter() { //! if let Ok(Some(png_img_data)) = frame { //! // do something with the image data here ... diff --git a/src/video_stream.rs b/src/video_stream.rs index 0a4d5e5..9016448 100644 --- a/src/video_stream.rs +++ b/src/video_stream.rs @@ -3,21 +3,29 @@ use gst::prelude::*; use gstreamer as gst; use gstreamer_app as gst_app; use std::sync::mpsc::{sync_channel, Receiver, TryRecvError, TrySendError}; +use std::sync::Once; pub type FrameData = Vec; +static INIT_GST: Once = Once::new(); + pub struct VideoStream { pipeline_description: String, } impl VideoStream { pub fn new>(pipeline_description: S) -> Self { + INIT_GST.call_once(|| { + log::trace!("Initializing GStreamer.."); + gst::init().expect("Could not initialize GStreamer!"); + }); Self { pipeline_description: String::from(pipeline_description.as_ref()), } } } +#[derive(Debug)] pub struct GstErrorMessage { pub src: String, pub error: String, @@ -25,6 +33,7 @@ pub struct GstErrorMessage { pub source: glib::Error, } +#[derive(Debug)] pub enum StreamError { GstError(GstErrorMessage), FrameCaptureError,