mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2025-09-01 01:13:48 +00:00
Merge branch 'mse-example' into 'main'
Draft: Adding example for using the mse rust bindings See merge request gstreamer/gstreamer-rs!1750
This commit is contained in:
commit
1b4a0d4b74
6 changed files with 122 additions and 0 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -528,6 +528,7 @@ dependencies = [
|
|||
"gstreamer-gl",
|
||||
"gstreamer-gl-egl",
|
||||
"gstreamer-gl-x11",
|
||||
"gstreamer-mse",
|
||||
"gstreamer-pbutils",
|
||||
"gstreamer-play",
|
||||
"gstreamer-player",
|
||||
|
|
|
@ -15,6 +15,7 @@ gst-gl-x11 = { workspace = true, optional = true }
|
|||
gst-app.workspace = true
|
||||
gst-audio.workspace = true
|
||||
gst-base.workspace = true
|
||||
gst-mse.workspace = true
|
||||
gst-video.workspace = true
|
||||
gst-pbutils.workspace = true
|
||||
gst-play = { workspace = true, optional = true }
|
||||
|
@ -109,6 +110,10 @@ name = "events"
|
|||
[[bin]]
|
||||
name = "iterator"
|
||||
|
||||
[[bin]]
|
||||
name = "mse-player"
|
||||
required-features = ["gst-play"]
|
||||
|
||||
[[bin]]
|
||||
name = "launch_glib_main"
|
||||
|
||||
|
|
BIN
examples/resources/frag_bunny.mp4
Normal file
BIN
examples/resources/frag_bunny.mp4
Normal file
Binary file not shown.
BIN
examples/resources/mse.mp4
Normal file
BIN
examples/resources/mse.mp4
Normal file
Binary file not shown.
BIN
examples/resources/mse.webm
Normal file
BIN
examples/resources/mse.webm
Normal file
Binary file not shown.
116
examples/src/bin/mse-player.rs
Normal file
116
examples/src/bin/mse-player.rs
Normal file
|
@ -0,0 +1,116 @@
|
|||
// This example shows how to use the GstPlay API.
|
||||
// The GstPlay API is a convenience API to allow implement playback applications
|
||||
// without having to write too much code.
|
||||
// Most of the tasks a play needs to support (such as seeking and switching
|
||||
// audio / subtitle streams or changing the volume) are all supported by simple
|
||||
// one-line function calls on the GstPlay.
|
||||
|
||||
use std::env::{self};
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
|
||||
use anyhow::Error;
|
||||
|
||||
#[path = "../examples-common.rs"]
|
||||
mod examples_common;
|
||||
|
||||
use gst_mse::{MediaSource, MediaSourceEOSError};
|
||||
use gst_play::prelude::*;
|
||||
use gst_play::{Play, PlayMessage, PlayVideoRenderer};
|
||||
|
||||
fn main_loop(file_path: &str, video_type: &str) -> Result<(), Error> {
|
||||
gst::init()?;
|
||||
|
||||
let play = Play::new(None::<PlayVideoRenderer>);
|
||||
|
||||
let media_source = MediaSource::new();
|
||||
play.set_uri(Some("mse://"));
|
||||
play.pipeline().connect_closure(
|
||||
"source-setup",
|
||||
false,
|
||||
glib::closure!(
|
||||
#[strong]
|
||||
media_source,
|
||||
move |_pipeline: &gst::Element, src: &gst_mse::MseSrc| {
|
||||
media_source.attach(&src);
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
media_source.connect_on_source_open(glib::clone!(
|
||||
#[to_owned]
|
||||
file_path,
|
||||
#[to_owned]
|
||||
video_type,
|
||||
#[strong]
|
||||
media_source,
|
||||
move |source| {
|
||||
let full_source_buffer = source
|
||||
.add_source_buffer(&video_type)
|
||||
.expect("Failed to create source buffer");
|
||||
|
||||
full_source_buffer.connect_on_update_end(glib::clone!(
|
||||
#[strong]
|
||||
media_source,
|
||||
move |_| {
|
||||
let _ = media_source.end_of_stream(MediaSourceEOSError::None);
|
||||
}
|
||||
));
|
||||
|
||||
let mut file = File::open(&file_path).expect("File should exist");
|
||||
let mut file_data = Vec::new();
|
||||
file.read_to_end(&mut file_data)
|
||||
.expect("Couldn't read file to end");
|
||||
|
||||
full_source_buffer
|
||||
.append_buffer(gst::Buffer::from_slice(file_data))
|
||||
.expect("Failed to append file buffer to source buffer");
|
||||
}
|
||||
));
|
||||
|
||||
play.play();
|
||||
|
||||
let mut result = Ok(());
|
||||
for msg in play.message_bus().iter_timed(gst::ClockTime::NONE) {
|
||||
match PlayMessage::parse(&msg) {
|
||||
Ok(PlayMessage::EndOfStream(_)) => {
|
||||
play.stop();
|
||||
break;
|
||||
}
|
||||
Ok(PlayMessage::Error(msg)) => {
|
||||
result = Err(msg.error().clone());
|
||||
play.stop();
|
||||
break;
|
||||
}
|
||||
Ok(_) => (),
|
||||
Err(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
// Set the message bus to flushing to ensure that all pending messages are dropped and there
|
||||
// are no further references to the play instance.
|
||||
play.message_bus().set_flushing(true);
|
||||
|
||||
result.map_err(|e| e.into())
|
||||
}
|
||||
|
||||
fn example_main() {
|
||||
let args: Vec<_> = env::args().collect();
|
||||
let (file_path, video_type): (&str, &str) = if args.len() == 3 {
|
||||
(args[1].as_ref(), args[2].as_ref())
|
||||
} else {
|
||||
println!("Usage: play uri");
|
||||
std::process::exit(-1)
|
||||
};
|
||||
|
||||
match main_loop(file_path, video_type) {
|
||||
Ok(r) => r,
|
||||
Err(e) => eprintln!("Error! {e}"),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// examples_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)
|
||||
examples_common::run(example_main);
|
||||
}
|
Loading…
Reference in a new issue