2017-07-05 07:40:02 +00:00
|
|
|
extern crate gstreamer as gst;
|
2017-08-17 14:58:15 +00:00
|
|
|
use gst::prelude::*;
|
2017-07-05 07:40:02 +00:00
|
|
|
|
|
|
|
extern crate glib;
|
|
|
|
|
|
|
|
use std::env;
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
gst::init().unwrap();
|
|
|
|
|
|
|
|
let args: Vec<_> = env::args().collect();
|
|
|
|
let uri: &str = if args.len() == 2 {
|
|
|
|
args[1].as_ref()
|
|
|
|
} else {
|
2017-09-10 12:10:04 +00:00
|
|
|
panic!("Usage: decodebin file_path")
|
2017-07-05 07:40:02 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let pipeline = gst::Pipeline::new(None);
|
|
|
|
let src = gst::ElementFactory::make("filesrc", None).unwrap();
|
|
|
|
let decodebin = gst::ElementFactory::make("decodebin", None).unwrap();
|
|
|
|
|
2017-08-17 14:58:15 +00:00
|
|
|
src.set_property("location", &glib::Value::from(uri))
|
|
|
|
.unwrap();
|
2017-07-05 07:40:02 +00:00
|
|
|
|
2017-07-05 08:09:49 +00:00
|
|
|
pipeline.add_many(&[&src, &decodebin]).unwrap();
|
|
|
|
gst::Element::link_many(&[&src, &decodebin]).unwrap();
|
2017-07-05 07:40:02 +00:00
|
|
|
|
|
|
|
// Need to move a new reference into the closure
|
|
|
|
let pipeline_clone = pipeline.clone();
|
|
|
|
decodebin.connect_pad_added(move |_, src_pad| {
|
2017-08-02 17:15:16 +00:00
|
|
|
let pipeline = &pipeline_clone;
|
2017-07-05 07:40:02 +00:00
|
|
|
|
2017-07-10 21:02:08 +00:00
|
|
|
let (is_audio, is_video) = {
|
|
|
|
let caps = src_pad.get_current_caps().unwrap();
|
|
|
|
let structure = caps.get_structure(0).unwrap();
|
|
|
|
let name = structure.get_name();
|
2017-07-05 07:40:02 +00:00
|
|
|
|
|
|
|
(name.starts_with("audio/"), name.starts_with("video/"))
|
|
|
|
};
|
|
|
|
|
|
|
|
if is_audio {
|
|
|
|
let queue = gst::ElementFactory::make("queue", None).unwrap();
|
|
|
|
let convert = gst::ElementFactory::make("audioconvert", None).unwrap();
|
|
|
|
let resample = gst::ElementFactory::make("audioresample", None).unwrap();
|
|
|
|
let sink = gst::ElementFactory::make("autoaudiosink", None).unwrap();
|
|
|
|
|
2017-07-05 08:09:49 +00:00
|
|
|
let elements = &[&queue, &convert, &resample, &sink];
|
|
|
|
pipeline.add_many(elements).unwrap();
|
|
|
|
gst::Element::link_many(elements).unwrap();
|
2017-07-05 07:40:02 +00:00
|
|
|
|
2017-07-05 08:09:49 +00:00
|
|
|
for e in elements {
|
|
|
|
e.sync_state_with_parent().unwrap();
|
|
|
|
}
|
2017-07-05 07:40:02 +00:00
|
|
|
|
|
|
|
let sink_pad = queue.get_static_pad("sink").unwrap();
|
|
|
|
assert_eq!(src_pad.link(&sink_pad), gst::PadLinkReturn::Ok);
|
|
|
|
} else if is_video {
|
|
|
|
let queue = gst::ElementFactory::make("queue", None).unwrap();
|
|
|
|
let convert = gst::ElementFactory::make("videoconvert", None).unwrap();
|
|
|
|
let scale = gst::ElementFactory::make("videoscale", None).unwrap();
|
|
|
|
let sink = gst::ElementFactory::make("autovideosink", None).unwrap();
|
2017-07-05 08:09:49 +00:00
|
|
|
|
|
|
|
let elements = &[&queue, &convert, &scale, &sink];
|
|
|
|
pipeline.add_many(elements).unwrap();
|
|
|
|
gst::Element::link_many(elements).unwrap();
|
|
|
|
|
|
|
|
for e in elements {
|
|
|
|
e.sync_state_with_parent().unwrap();
|
|
|
|
}
|
2017-07-05 07:40:02 +00:00
|
|
|
|
|
|
|
let sink_pad = queue.get_static_pad("sink").unwrap();
|
|
|
|
assert_eq!(src_pad.link(&sink_pad), gst::PadLinkReturn::Ok);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-07-10 21:33:24 +00:00
|
|
|
assert_ne!(
|
|
|
|
pipeline.set_state(gst::State::Playing),
|
|
|
|
gst::StateChangeReturn::Failure
|
|
|
|
);
|
2017-07-05 07:40:02 +00:00
|
|
|
|
|
|
|
let bus = pipeline.get_bus().unwrap();
|
|
|
|
|
2017-09-13 16:35:35 +00:00
|
|
|
while let Some(msg) = bus.timed_pop(gst::CLOCK_TIME_NONE) {
|
2017-08-17 14:58:15 +00:00
|
|
|
use gst::MessageView;
|
|
|
|
|
2017-07-05 07:40:02 +00:00
|
|
|
match msg.view() {
|
2017-07-30 14:06:44 +00:00
|
|
|
MessageView::Eos(..) => break,
|
2017-07-05 07:40:02 +00:00
|
|
|
MessageView::Error(err) => {
|
2017-07-10 21:33:24 +00:00
|
|
|
println!(
|
|
|
|
"Error from {}: {} ({:?})",
|
|
|
|
msg.get_src().get_path_string(),
|
|
|
|
err.get_error(),
|
|
|
|
err.get_debug()
|
|
|
|
);
|
2017-07-05 07:40:02 +00:00
|
|
|
break;
|
2017-07-10 21:33:24 +00:00
|
|
|
}
|
2017-07-05 07:40:02 +00:00
|
|
|
MessageView::StateChanged(s) => {
|
2017-07-10 21:33:24 +00:00
|
|
|
println!(
|
|
|
|
"State changed from {}: {:?} -> {:?} ({:?})",
|
|
|
|
msg.get_src().get_path_string(),
|
|
|
|
s.get_old(),
|
|
|
|
s.get_current(),
|
|
|
|
s.get_pending()
|
|
|
|
);
|
|
|
|
}
|
2017-07-05 07:40:02 +00:00
|
|
|
_ => (),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-10 21:33:24 +00:00
|
|
|
assert_ne!(
|
|
|
|
pipeline.set_state(gst::State::Null),
|
|
|
|
gst::StateChangeReturn::Failure
|
|
|
|
);
|
2017-07-05 07:40:02 +00:00
|
|
|
}
|