Initialize gstreamer only once
This commit is contained in:
parent
1269cbf68e
commit
378584b626
6 changed files with 41 additions and 3 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
/target
|
/target
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
|
*.png
|
||||||
|
|
18
examples/simple.rs
Normal file
18
examples/simple.rs
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
resources/video.mp4
Normal file
BIN
resources/video.mp4
Normal file
Binary file not shown.
13
src/file.rs
13
src/file.rs
|
@ -1,6 +1,8 @@
|
||||||
use crate::StreamError;
|
use crate::StreamError;
|
||||||
use crate::{FrameData, VideoStream, VideoStreamIterator};
|
use crate::{FrameData, VideoStream, VideoStreamIterator};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::fs;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
pub struct FileSource {
|
pub struct FileSource {
|
||||||
source: PathBuf,
|
source: PathBuf,
|
||||||
|
@ -9,11 +11,12 @@ pub struct FileSource {
|
||||||
|
|
||||||
impl FileSource {
|
impl FileSource {
|
||||||
pub fn new(source: &Path, frame_size: (u32, u32)) -> Result<Self, CaptureError> {
|
pub fn new(source: &Path, frame_size: (u32, u32)) -> Result<Self, CaptureError> {
|
||||||
|
let source = fs::canonicalize(source)?;
|
||||||
if !source.exists() {
|
if !source.exists() {
|
||||||
return Err(CaptureError::FileNotFound);
|
return Err(CaptureError::FileNotFound);
|
||||||
}
|
}
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
source: source.to_path_buf(),
|
source,
|
||||||
frame_size,
|
frame_size,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -34,6 +37,14 @@ impl IntoIterator for FileSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum CaptureError {
|
pub enum CaptureError {
|
||||||
|
IoError(io::Error),
|
||||||
FileNotFound,
|
FileNotFound,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for CaptureError {
|
||||||
|
fn from(err: io::Error) -> Self {
|
||||||
|
CaptureError::IoError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,12 +14,11 @@
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use std::path::Path;
|
//! use std::path::Path;
|
||||||
//! use vid2img::FileSource;
|
|
||||||
//!
|
//!
|
||||||
//! fn main() {
|
//! fn main() {
|
||||||
//! let file_path = Path::new("video.mp4");
|
//! 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() {
|
//! for frame in frame_source.into_iter() {
|
||||||
//! if let Ok(Some(png_img_data)) = frame {
|
//! if let Ok(Some(png_img_data)) = frame {
|
||||||
//! // do something with the image data here ...
|
//! // do something with the image data here ...
|
||||||
|
|
|
@ -3,21 +3,29 @@ use gst::prelude::*;
|
||||||
use gstreamer as gst;
|
use gstreamer as gst;
|
||||||
use gstreamer_app as gst_app;
|
use gstreamer_app as gst_app;
|
||||||
use std::sync::mpsc::{sync_channel, Receiver, TryRecvError, TrySendError};
|
use std::sync::mpsc::{sync_channel, Receiver, TryRecvError, TrySendError};
|
||||||
|
use std::sync::Once;
|
||||||
|
|
||||||
pub type FrameData = Vec<u8>;
|
pub type FrameData = Vec<u8>;
|
||||||
|
|
||||||
|
static INIT_GST: Once = Once::new();
|
||||||
|
|
||||||
pub struct VideoStream {
|
pub struct VideoStream {
|
||||||
pipeline_description: String,
|
pipeline_description: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VideoStream {
|
impl VideoStream {
|
||||||
pub fn new<S: AsRef<str>>(pipeline_description: S) -> Self {
|
pub fn new<S: AsRef<str>>(pipeline_description: S) -> Self {
|
||||||
|
INIT_GST.call_once(|| {
|
||||||
|
log::trace!("Initializing GStreamer..");
|
||||||
|
gst::init().expect("Could not initialize GStreamer!");
|
||||||
|
});
|
||||||
Self {
|
Self {
|
||||||
pipeline_description: String::from(pipeline_description.as_ref()),
|
pipeline_description: String::from(pipeline_description.as_ref()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct GstErrorMessage {
|
pub struct GstErrorMessage {
|
||||||
pub src: String,
|
pub src: String,
|
||||||
pub error: String,
|
pub error: String,
|
||||||
|
@ -25,6 +33,7 @@ pub struct GstErrorMessage {
|
||||||
pub source: glib::Error,
|
pub source: glib::Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum StreamError {
|
pub enum StreamError {
|
||||||
GstError(GstErrorMessage),
|
GstError(GstErrorMessage),
|
||||||
FrameCaptureError,
|
FrameCaptureError,
|
||||||
|
|
Loading…
Reference in a new issue