Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
target/
*.mp4
*.fmp4
debug/
debug/
29 changes: 29 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ moq-karp = "0.14"

gst = { package = "gstreamer", version = "0.23" }
gst-base = { package = "gstreamer-base", version = "0.23" }
gst-app = { package = "gstreamer-app", version = "0.23", features = ["v1_20"] }

once_cell = "1"
tokio = { version = "1", features = ["full"] }
env_logger = "0.9"
Expand Down
36 changes: 29 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,39 @@
<p align="center">
<img height="128px" src="https://github.com/kixelated/moq-rs/blob/main/.github/logo.svg" alt="Media over QUIC">
</p>

A gstreamer plugin utilizing [moq-rs](https://github.com/kixelated/moq-rs).

# Usage
Check out the `dev/pub` script for an example pipeline.
## Requirements
- [Rustup](https://www.rust-lang.org/tools/install)
- [Just](https://github.com/casey/just?tab=readme-ov-file#installation)

## Setup
We use `just` to simplify the development process.
Check out the [Justfile](justfile) or run `just` to see the available commands.

```bash
./dev/pub
Install any other required tools:
```sh
just setup
```

By default this uses a localhost relay.
You can change the ENV args if you want to make it watchable on production instead:
## Development
First make sure you have a local moq-relay server running:
```sh
# In github.com/kixelated/moq-rs
just relay
```

Now you can publish and subscribe to a video:
```sh
# In github.com/kixelated/moq-gst

# Publish to a localhost moq-relay server
just pub

```bash
ADDR=relay.quic.video NAME=something ./dev/pub
# Subscribe from a localhost moq-relay server
just sub
```

# License
Expand Down
48 changes: 0 additions & 48 deletions dev/pub

This file was deleted.

90 changes: 90 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/env just --justfile

# Using Just: https://github.com/casey/just?tab=readme-ov-file#installation

export RUST_BACKTRACE := "1"
export RUST_LOG := "info"
export URL := "http://localhost:4443"
#export GST_DEBUG:="*:4"

# List all of the available commands.
default:
just --list

# Install any required dependencies.
setup:
# Upgrade Rust
rustup update

# Make sure the right components are installed.
rustup component add rustfmt clippy

# Install cargo binstall if needed.
cargo install cargo-binstall

# Install cargo shear if needed.
cargo binstall --no-confirm cargo-shear

# Download the video and convert it to a fragmented MP4 that we can stream
download name url:
if [ ! -f dev/{{name}}.mp4 ]; then \
wget {{url}} -O dev/{{name}}.mp4; \
fi

if [ ! -f dev/{{name}}.fmp4 ]; then \
ffmpeg -i dev/{{name}}.mp4 \
-c copy \
-f mp4 -movflags cmaf+separate_moof+delay_moov+skip_trailer+frag_every_frame \
dev/{{name}}.fmp4; \
fi

# Publish a video using ffmpeg to the localhost relay server
pub: (download "bbb" "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")
# Build the plugins
cargo build

# Run gstreamer and pipe the output to our plugin
GST_PLUGIN_PATH="${PWD}/target/debug${GST_PLUGIN_PATH:+:$GST_PLUGIN_PATH}" \
gst-launch-1.0 -v -e multifilesrc location="dev/bbb.fmp4" loop=true ! qtdemux name=demux \
demux.video_0 ! h264parse ! queue ! identity sync=true ! isofmp4mux name=mux chunk-duration=1 fragment-duration=1 ! moqsink url="$URL/demo/bbb" tls-disable-verify=true \
demux.audio_0 ! aacparse ! queue ! mux.

# Subscribe to a video using gstreamer
sub:
# Build the plugins
cargo build

# Run gstreamer and pipe the output to our plugin
# This will render the video to the screen
GST_PLUGIN_PATH="${PWD}/target/debug${GST_PLUGIN_PATH:+:$GST_PLUGIN_PATH}" \
gst-launch-1.0 -v -e moqsrc url="$URL/demo/bbb" tls-disable-verify=true ! decodebin ! videoconvert ! autovideosink

# Run the CI checks
check $RUSTFLAGS="-D warnings":
cargo check --all-targets
cargo clippy --all-targets -- -D warnings
cargo fmt -- --check
cargo shear # requires: cargo binstall cargo-shear

# Run any CI tests
test $RUSTFLAGS="-D warnings":
cargo test

# Automatically fix some issues.
fix:
cargo fix --allow-staged --all-targets --all-features
cargo clippy --fix --allow-staged --all-targets --all-features
cargo fmt --all
cargo shear --fix

# Upgrade any tooling
upgrade:
rustup upgrade

# Install cargo-upgrades if needed.
cargo install cargo-upgrades cargo-edit
cargo upgrade

# Build the plugins
build:
cargo build
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use gst::glib;

mod sink;
mod source;

pub fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
env_logger::init();
sink::register(plugin)?;
source::register(plugin)?;

Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion src/sink/imp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl ElementImpl for MoqSink {
static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| {
gst::subclass::ElementMetadata::new(
"MoQ Sink",
"Sink",
"Sink/Network/MoQ",
"Transmits media over the network via MoQ",
"Luke Curley <kixelated@gmail.com>",
)
Expand Down
1 change: 0 additions & 1 deletion src/sink/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,5 @@ glib::wrapper! {
}

pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
env_logger::init();
gst::Element::register(Some(plugin), "moqsink", gst::Rank::NONE, MoqSink::static_type())
}
Loading
Loading