Skip to content

Commit 1d65181

Browse files
authored
Merge pull request #338 from RidgeRun/feature/add-rust-api
Add Rust client library for GstD with examples
2 parents e95cd75 + 206f7ef commit 1d65181

17 files changed

Lines changed: 1507 additions & 0 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ autoregen.sh
3838
# debian files
3939
*.deb
4040
*.build
41+
!**/meson.build
4142
*.buildinfo
4243
*.changes
4344
debian/.debhelper/

Cargo.lock

Lines changed: 105 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[workspace]
2+
members = [
3+
"libgstc/rust/gstc",
4+
]
5+
resolver = "2"

examples/libgstc/rust/README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Rust `libgstc` Examples
2+
3+
These examples show how to control GStreamer Daemon (`gstd`) using the Rust `gstc` client library.
4+
5+
## Prerequisites
6+
7+
- `gstd` must be running and listening on `127.0.0.1:5000`
8+
- Rust examples assume the daemon is reachable at that address and port
9+
- Some examples require GStreamer plugins such as `autovideosink`, `playbin`, `qtmux`, `avenc_mpeg4`, and `lamemp3enc`
10+
11+
## How to Build
12+
To build the examples, run the following command from the repository root:
13+
```bash
14+
cargo build --examples
15+
```
16+
The examples will be available at the following path:
17+
```bash
18+
target/debug/examples/
19+
```
20+
21+
## How To Run
22+
23+
You can run the examples directly as an executable or
24+
with Cargo from the Repository root:
25+
26+
```bash
27+
cargo run --example simple_pipeline
28+
```
29+
30+
Examples that take an argument can be run like this:
31+
32+
```bash
33+
cargo run --example gapless_playback -- /path/to/video.mp4
34+
```
35+
36+
## Examples
37+
38+
### `simple_pipeline`
39+
40+
Creates a `videotestsrc ! autovideosink` pipeline, starts playback, waits for Enter, then stops and deletes the pipeline.
41+
42+
### `pipeline_lifecycle`
43+
44+
Creates a `videotestsrc ! fakesink` pipeline, sets it to `PLAYING`, polls until the daemon reports the expected state, then stops and deletes the pipeline.
45+
46+
### `wait_on_bus`
47+
48+
Creates a finite pipeline with `videotestsrc num-buffers=300`, waits for an EOS message on the bus, prints the raw bus message, then cleans up the pipeline.
49+
50+
### `dynamic_property_change`
51+
52+
Creates a `videotestsrc` pipeline and changes the `pattern` property once per second while the pipeline is running. Press Enter to stop it.
53+
54+
### `gapless_playback`
55+
56+
Plays a media file with `playbin`, waits for EOS, then seeks back to the start to continue playback. Press Enter to stop it.
57+
58+
Run with:
59+
60+
```bash
61+
cargo run --example gapless_playback -- /path/to/video.mp4
62+
```
63+
64+
### `mp4_recording`
65+
66+
Creates a live audio/video recording pipeline that writes to `mp4_recording.mp4`. When you press Enter, it injects EOS, waits for the EOS bus message, then stops and deletes the pipeline.
67+
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* This file is part of GStreamer Daemon
3+
* Copyright 2015-2026 RidgeRun, LLC (http://www.ridgerun.com)
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Library General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 2 of the License, or (at your option) any later version.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Library General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Library General Public
16+
* License along with this library; if not, write to the
17+
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18+
* Boston, MA 02110-1301, USA.
19+
*/
20+
21+
use gstc::{Client, Status};
22+
use std::io;
23+
use std::sync::atomic::{AtomicBool, Ordering};
24+
use std::sync::Arc;
25+
use std::thread;
26+
use std::time::Duration;
27+
28+
fn main() -> Result<(), Status> {
29+
let client = Client::new("127.0.0.1", 5000, -1, true)?;
30+
31+
client.pipeline_create("pipe", "videotestsrc name=vts ! autovideosink")?;
32+
println!("Pipeline created successfully!");
33+
34+
client.pipeline_play("pipe")?;
35+
println!("Pipeline set to playing!");
36+
37+
println!("Press enter to stop the pipeline...");
38+
let stop_flag = Arc::new(AtomicBool::new(false));
39+
let thread_stop_flag = Arc::clone(&stop_flag);
40+
thread::spawn(move || {
41+
let mut line = String::new();
42+
let _ = io::stdin().read_line(&mut line);
43+
thread_stop_flag.store(true, Ordering::Relaxed);
44+
});
45+
46+
let mut format = 0;
47+
loop {
48+
client.element_set("pipe", "vts", "pattern", &format.to_string())?;
49+
format = (format + 1) % 10;
50+
51+
if stop_flag.load(Ordering::Relaxed) {
52+
break;
53+
}
54+
55+
thread::sleep(Duration::from_secs(1));
56+
}
57+
58+
client.pipeline_stop("pipe")?;
59+
println!("Pipeline set to null!");
60+
61+
client.pipeline_delete("pipe")?;
62+
println!("Pipeline deleted!");
63+
64+
Ok(())
65+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* This file is part of GStreamer Daemon
3+
* Copyright 2015-2026 RidgeRun, LLC (http://www.ridgerun.com)
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Library General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 2 of the License, or (at your option) any later version.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Library General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Library General Public
16+
* License along with this library; if not, write to the
17+
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18+
* Boston, MA 02110-1301, USA.
19+
*/
20+
21+
use gstc::{Client, Status};
22+
use std::env;
23+
use std::io;
24+
use std::path::PathBuf;
25+
use std::sync::atomic::{AtomicBool, Ordering};
26+
use std::sync::Arc;
27+
use std::thread;
28+
29+
const RATE: f64 = 1.0;
30+
const FORMAT: i32 = 3;
31+
const FLAGS: i32 = 1;
32+
const START_TYPE: i32 = 1;
33+
const START: i64 = 0;
34+
const STOP_TYPE: i32 = 1;
35+
const STOP: i64 = -1;
36+
37+
fn main() -> Result<(), Status> {
38+
let video = match env::args().nth(1) {
39+
Some(path) => path,
40+
None => {
41+
eprintln!("Please provide a video to play");
42+
return Err(Status::NullArgument);
43+
}
44+
};
45+
46+
let abs_path = PathBuf::from(&video)
47+
.canonicalize()
48+
.unwrap_or_else(|_| PathBuf::from(&video));
49+
let uri = format!("file://{}", abs_path.display());
50+
51+
let client = Client::new("127.0.0.1", 5000, -1, true)?;
52+
53+
client.pipeline_create("pipe", &format!("playbin uri={}", uri))?;
54+
println!("Pipeline created successfully!");
55+
56+
client.pipeline_play("pipe")?;
57+
println!("Pipeline set to playing!");
58+
59+
println!("Press enter to stop the pipeline...");
60+
let stop_flag = Arc::new(AtomicBool::new(false));
61+
let thread_stop_flag = Arc::clone(&stop_flag);
62+
thread::spawn(move || {
63+
let mut line = String::new();
64+
let _ = io::stdin().read_line(&mut line);
65+
thread_stop_flag.store(true, Ordering::Relaxed);
66+
});
67+
68+
while !stop_flag.load(Ordering::Relaxed) {
69+
let message = client.pipeline_bus_wait("pipe", "eos", -1)?;
70+
if message.status != Status::Ok {
71+
eprintln!("Unable to read from bus: {}", message.status.code());
72+
break;
73+
}
74+
75+
println!("EOS message received!");
76+
77+
client.pipeline_seek(
78+
"pipe", RATE, FORMAT, FLAGS, START_TYPE, START, STOP_TYPE, STOP,
79+
)?;
80+
println!("Pipeline reset!");
81+
}
82+
83+
client.pipeline_stop("pipe")?;
84+
println!("Pipeline set to null!");
85+
86+
client.pipeline_delete("pipe")?;
87+
println!("Pipeline deleted!");
88+
89+
Ok(())
90+
}

0 commit comments

Comments
 (0)