mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2025-01-24 16:08:16 +00:00
180 lines
4.9 KiB
Rust
180 lines
4.9 KiB
Rust
use std::env;
|
|
|
|
use anyhow::Error;
|
|
use gst_pbutils::{
|
|
prelude::*, Discoverer, DiscovererContainerInfo, DiscovererInfo, DiscovererResult,
|
|
DiscovererStreamInfo,
|
|
};
|
|
|
|
#[path = "../tutorials-common.rs"]
|
|
mod tutorials_common;
|
|
|
|
fn send_value_as_str(v: &glib::SendValue) -> Option<String> {
|
|
if let Ok(s) = v.get::<&str>() {
|
|
Some(s.to_string())
|
|
} else if let Ok(serialized) = v.serialize() {
|
|
Some(serialized.into())
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
fn print_stream_info(info: &DiscovererStreamInfo, depth: usize) {
|
|
let caps_str = if let Some(caps) = info.caps() {
|
|
if caps.is_fixed() {
|
|
gst_pbutils::pb_utils_get_codec_description(&caps)
|
|
} else {
|
|
glib::GString::from(caps.to_string())
|
|
}
|
|
} else {
|
|
glib::GString::from("")
|
|
};
|
|
|
|
let stream_nick = info.stream_type_nick();
|
|
println!(
|
|
"{stream_nick:>indent$}: {caps_str}",
|
|
stream_nick = stream_nick,
|
|
indent = 2 * depth + stream_nick.len(),
|
|
caps_str = caps_str
|
|
);
|
|
|
|
if let Some(tags) = info.tags() {
|
|
println!("{:indent$}Tags:", " ", indent = 2 * depth);
|
|
for (tag, values) in tags.iter_generic() {
|
|
let mut tags_str = format!(
|
|
"{tag:>indent$}: ",
|
|
tag = tag,
|
|
indent = 2 * (2 + depth) + tag.len()
|
|
);
|
|
let mut tag_num = 0;
|
|
for value in values {
|
|
if let Some(s) = send_value_as_str(value) {
|
|
if tag_num > 0 {
|
|
tags_str.push_str(", ")
|
|
}
|
|
tags_str.push_str(&s[..]);
|
|
tag_num += 1;
|
|
}
|
|
}
|
|
|
|
println!("{tags_str}");
|
|
}
|
|
};
|
|
}
|
|
|
|
/* Print information regarding a stream and its substreams, if any */
|
|
fn print_topology(info: &DiscovererStreamInfo, depth: usize) {
|
|
print_stream_info(info, depth);
|
|
|
|
if let Some(next) = info.next() {
|
|
print_topology(&next, depth + 1);
|
|
} else if let Some(container_info) = info.downcast_ref::<DiscovererContainerInfo>() {
|
|
for stream in container_info.streams() {
|
|
print_topology(&stream, depth + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn on_discovered(
|
|
_discoverer: &Discoverer,
|
|
discoverer_info: &DiscovererInfo,
|
|
error: Option<&glib::Error>,
|
|
) {
|
|
let uri = discoverer_info.uri();
|
|
match discoverer_info.result() {
|
|
DiscovererResult::Ok => println!("Discovered {uri}"),
|
|
DiscovererResult::UriInvalid => println!("Invalid uri {uri}"),
|
|
DiscovererResult::Error => {
|
|
if let Some(msg) = error {
|
|
println!("{msg}");
|
|
} else {
|
|
println!("Unknown error")
|
|
}
|
|
}
|
|
DiscovererResult::Timeout => println!("Timeout"),
|
|
DiscovererResult::Busy => println!("Busy"),
|
|
DiscovererResult::MissingPlugins => {
|
|
if let Some(s) = discoverer_info.misc() {
|
|
println!("{s}");
|
|
}
|
|
}
|
|
_ => println!("Unknown result"),
|
|
}
|
|
|
|
if discoverer_info.result() != DiscovererResult::Ok {
|
|
return;
|
|
}
|
|
|
|
println!("Duration: {}", discoverer_info.duration().display());
|
|
|
|
if let Some(tags) = discoverer_info.tags() {
|
|
println!("Tags:");
|
|
for (tag, values) in tags.iter_generic() {
|
|
print!(" {tag}: ");
|
|
values.for_each(|v| {
|
|
if let Some(s) = send_value_as_str(v) {
|
|
println!("{s}")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
println!(
|
|
"Seekable: {}",
|
|
if discoverer_info.is_seekable() {
|
|
"yes"
|
|
} else {
|
|
"no"
|
|
}
|
|
);
|
|
|
|
println!("Stream information:");
|
|
|
|
if let Some(stream_info) = discoverer_info.stream_info() {
|
|
print_topology(&stream_info, 1);
|
|
}
|
|
}
|
|
|
|
fn run_discoverer() -> Result<(), Error> {
|
|
gst::init()?;
|
|
|
|
let args: Vec<_> = env::args().collect();
|
|
let uri: &str = if args.len() == 2 {
|
|
args[1].as_ref()
|
|
} else {
|
|
"https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm"
|
|
};
|
|
|
|
println!("Discovering {uri}");
|
|
|
|
let loop_ = glib::MainLoop::new(None, false);
|
|
let timeout = 5 * gst::ClockTime::SECOND;
|
|
let discoverer = gst_pbutils::Discoverer::new(timeout)?;
|
|
discoverer.connect_discovered(on_discovered);
|
|
let loop_clone = loop_.clone();
|
|
discoverer.connect_finished(move |_| {
|
|
println!("\nFinished discovering");
|
|
loop_clone.quit();
|
|
});
|
|
discoverer.start();
|
|
discoverer.discover_uri_async(uri)?;
|
|
|
|
loop_.run();
|
|
|
|
discoverer.stop();
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn tutorial_main() {
|
|
match run_discoverer() {
|
|
Ok(_) => {}
|
|
Err(err) => eprintln!("Failed to run discovery: {err}"),
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
// tutorials_common::run is only required to set up the application environment on macOS
|
|
// (but not necessary in normal Cocoa applications where this is set up automatically)
|
|
tutorials_common::run(tutorial_main);
|
|
}
|