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
1 change: 0 additions & 1 deletion Cargo.lock

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

1 change: 1 addition & 0 deletions demo/pub/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ deploy:
# Use ffmpeg to fragment before uploading:
# ffmpeg -i input.mp4 -c copy -f mp4 \
# -movflags cmaf+separate_moof+delay_moov+skip_trailer+frag_every_frame \

# output.mp4
upload file:
bun install
Expand Down
3 changes: 3 additions & 0 deletions go/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,21 @@ default:

# Build moq-ffi for the host, run uniffi-bindgen-go, stage everything
# into a tmp dir, and run `go build`/`go vet`/`go test` from there.

# Skips cleanly if cargo, go, or uniffi-bindgen-go is missing.
check:
bash scripts/check.sh

# Stage the in-tree go/ source + per-target moq-ffi libs + generated

# bindings into a single Go module ready for publish.
package *args:
bash scripts/package.sh {{ args }}

# Full Go CI: `check` builds moq-ffi, regenerates bindings, runs go
# vet/build/test. Takes a newline-separated list of changed files;
# skips if FILES is non-empty and none match the Go scope. Run

# `just go ci` (no FILES) to force-run.
ci FILES="":
#!/usr/bin/env bash
Expand Down
1 change: 1 addition & 0 deletions infra/apt/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ deploy:
bun wrangler deploy

# Regenerate apt repo metadata and upload to the apt-moq-dev R2 bucket.

# Reads .deb files from $ARTIFACTS_DIR (defaults to ./artifacts).
publish artifacts="artifacts":
ARTIFACTS_DIR="{{ artifacts }}" ./publish.sh
Expand Down
1 change: 1 addition & 0 deletions infra/rpm/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ deploy:
bun wrangler deploy

# Regenerate rpm repo metadata and upload to the rpm-moq-dev R2 bucket.

# Reads .rpm files from $ARTIFACTS_DIR (defaults to ./artifacts).
publish artifacts="artifacts":
ARTIFACTS_DIR="{{ artifacts }}" ./publish.sh
Expand Down
1 change: 1 addition & 0 deletions js/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ build:

# Full JS CI: lint + tests + build. Takes a newline-separated list of
# changed files; skips if FILES is non-empty and none match the JS

# scope. Run `just js ci` (no FILES) to force-run everything.
ci FILES="":
#!/usr/bin/env bash
Expand Down
10 changes: 5 additions & 5 deletions justfile
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
#!/usr/bin/env just --justfile

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

# Per-language modules. Anything that's specific to one language lives in

# its own justfile; the recipes below orchestrate across them.
mod js
mod rs
mod py
mod kt
mod swift
mod go

# Demos and infra.
mod demo
mod infra

# GitHub Actions workflow linting.
mod gh '.github'

# Shortcuts to avoid `demo::` prefix.
mod boy 'demo/boy'
mod pub 'demo/pub'
Expand All @@ -34,6 +30,7 @@ dev:
just demo

# Install repo-wide tooling. Per-language deps install on first invocation

# of `just <lang> check`.
install:
bun install
Expand All @@ -42,6 +39,7 @@ install:
# Fast inner-loop checks. Runs JS, Rust, and Markdown lints.
# Shell + workflow + TOML + Nix + justfile lints skip silently if their
# binaries aren't on $PATH; `nix develop` provides them, and `just ci`

# requires them.
check *args:
just js check
Expand All @@ -55,6 +53,7 @@ check *args:

# Run every per-language `ci` with the diff vs BASE; each greps for its
# own scope and skips when nothing relevant changed. Pass BASE="" to

# default to $GITHUB_BASE_REF (CI) or origin/main (local).
ci BASE="":
#!/usr/bin/env bash
Expand Down Expand Up @@ -101,6 +100,7 @@ ci BASE="":
just gh ci

# Auto-fix linting/formatting issues across all languages.

# shfmt / taplo / nixfmt / just --fmt skipped silently if missing locally.
fix:
just js fix
Expand Down
3 changes: 3 additions & 0 deletions kt/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,22 @@ default:
just check

# Build moq-ffi for the host, regenerate uniffi bindings, run :moq:jvmTest.

# Skips cleanly if cargo, java, or gradle is missing.
check:
bash scripts/check.sh

# Assemble the KMP module from per-target moq-ffi binaries + bindings.
# Used by .github/workflows/release-kt.yml; see kt/README.md for the

# expected --lib-dir layout.
package *args:
bash scripts/package.sh {{ args }}

# Full Kotlin CI: `check` already builds moq-ffi and runs gradle tests.
# Takes a newline-separated list of changed files; skips if FILES is
# non-empty and none match the Kotlin scope. Run `just kt ci` (no

# FILES) to force-run.
ci FILES="":
#!/usr/bin/env bash
Expand Down
3 changes: 3 additions & 0 deletions py/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ default:
# Lint + format + maturin source build + pyright. `--no-install-workspace`
# installs the root dev group (ruff, maturin, pyright, pytest) without
# trying to pip-build moq-rs; `maturin develop` then installs moq-rs

# as an editable wheel with the rs/moq-ffi cdylib + uniffi bindings.
check:
uv sync --no-install-workspace
Expand All @@ -30,6 +31,7 @@ test:
uv run --no-sync pytest moq-rs/tests/

# Local dev build: produces an editable install of moq-rs (with the

# moq-ffi cdylib + uniffi bindings) into the workspace venv.
build:
uv sync --no-install-workspace
Expand All @@ -38,6 +40,7 @@ build:
# Full Python CI: lint + tests + build. Takes a newline-separated list
# of changed files; skips if FILES is non-empty and none match the
# Python scope (which includes rs/moq-ffi because py bundles it via

# maturin). Run `just py ci` (no FILES) to force-run everything.
ci FILES="":
#!/usr/bin/env bash
Expand Down
2 changes: 2 additions & 0 deletions rs/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ check *args:
# force-run everything. `cargo publish --dry-run` lives in release-rs.yml.
#
# `cargo deny` runs here (not in `check`) so the inner-loop stays fast

# and devs aren't blocked by a fresh upstream advisory mid-edit.
ci FILES="":
#!/usr/bin/env bash
Expand Down Expand Up @@ -80,6 +81,7 @@ update:
#
# Examples:
# just rs package moq-relay deb

# just rs package moq-cli rpm
package crate packager:
#!/usr/bin/env bash
Expand Down
25 changes: 5 additions & 20 deletions rs/libmoq/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,9 @@ pub enum Error {
#[error("unknown format: {0}")]
UnknownFormat(String),

/// Media decoder initialization failed.
#[error("init failed: {0}")]
InitFailed(Arc<anyhow::Error>),

/// Media frame decode failed.
#[error("decode failed: {0}")]
DecodeFailed(Arc<anyhow::Error>),
/// Buffer was not fully consumed.
#[error("buffer was not fully consumed")]
BufferNotConsumed,

/// Timestamp value overflow.
#[error("timestamp overflow")]
Expand Down Expand Up @@ -117,7 +113,7 @@ pub enum Error {

/// Error from the moq-mux consumer layer.
#[error("mux error: {0}")]
Mux(Arc<moq_mux::Error>),
Mux(#[from] moq_mux::Error),

/// Index out of bounds.
#[error("no index")]
Expand All @@ -144,16 +140,6 @@ impl From<tracing::metadata::ParseLevelError> for Error {
}
}

impl From<moq_mux::Error> for Error {
fn from(err: moq_mux::Error) -> Self {
match err {
moq_mux::Error::Moq(e) => Error::Moq(e),
moq_mux::Error::Hang(e) => Error::Hang(e),
e => Error::Mux(Arc::new(e)),
}
}
}

impl ffi::ReturnCode for Error {
fn code(&self) -> i32 {
tracing::error!("{}", self);
Expand All @@ -167,8 +153,6 @@ impl ffi::ReturnCode for Error {
Error::InvalidId => -7,
Error::NotFound => -8,
Error::UnknownFormat(_) => -9,
Error::InitFailed(_) => -10,
Error::DecodeFailed(_) => -11,
Error::TimestampOverflow(_) => -13,
Error::Level(_) => -14,
Error::InvalidCode => -15,
Expand All @@ -187,6 +171,7 @@ impl ffi::ReturnCode for Error {
Error::FrameNotFound => -28,
Error::Mux(_) => -29,
Error::Audio(_) => -30,
Error::BufferNotConsumed => -31,
}
}
}
15 changes: 5 additions & 10 deletions rs/libmoq/src/publish.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{str::FromStr, sync::Arc};
use std::str::FromStr;

use bytes::Buf;
use moq_mux::import;
Expand Down Expand Up @@ -50,8 +50,7 @@ impl Publish {
let (broadcast, catalog) = self.broadcasts.get(broadcast).ok_or(Error::BroadcastNotFound)?;

let format = import::FramedFormat::from_str(format).map_err(|_| Error::UnknownFormat(format.to_string()))?;
let decoder = import::Framed::new(broadcast.clone(), catalog.clone(), format, &mut init)
.map_err(|err| Error::InitFailed(Arc::new(err)))?;
let decoder = import::Framed::new(broadcast.clone(), catalog.clone(), format, &mut init)?;

let id = self.media.insert(decoder)?;
Ok(id)
Expand All @@ -65,22 +64,18 @@ impl Publish {
) -> Result<(), Error> {
let media = self.media.get_mut(media).ok_or(Error::MediaNotFound)?;

media
.decode_frame(&mut data, Some(timestamp))
.map_err(|err| Error::DecodeFailed(Arc::new(err)))?;
media.decode_frame(&mut data, Some(timestamp))?;

if data.has_remaining() {
return Err(Error::DecodeFailed(Arc::new(anyhow::anyhow!(
"buffer was not fully consumed"
))));
return Err(Error::BufferNotConsumed);
}

Ok(())
}

pub fn media_close(&mut self, media: Id) -> Result<(), Error> {
let mut decoder = self.media.remove(media).ok_or(Error::MediaNotFound)?;
decoder.finish().map_err(|err| Error::DecodeFailed(Arc::new(err)))?;
decoder.finish()?;
Ok(())
}
}
6 changes: 3 additions & 3 deletions rs/moq-cli/src/publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ impl PublishDecoder {
/// Decode a chunk of bytes from stdin (Avc3 or Fmp4 only).
fn decode_buf(&mut self, buffer: &mut bytes::BytesMut) -> anyhow::Result<()> {
match self {
Self::Avc3(d) => d.decode_stream(buffer, None),
Self::Fmp4(d) => d.decode(buffer),
Self::Avc3(d) => Ok(d.decode_stream(buffer, None)?),
Self::Fmp4(d) => Ok(d.decode(buffer)?),
Self::Hls(_) => unreachable!(),
}
}
Expand Down Expand Up @@ -67,7 +67,7 @@ impl Publish {
pub async fn run(mut self) -> anyhow::Result<()> {
if let PublishDecoder::Hls(decoder) = &mut self.decoder {
decoder.init().await?;
decoder.run().await
Ok(decoder.run().await?)
} else {
let mut stdin = tokio::io::stdin();
let mut buffer = bytes::BytesMut::new();
Expand Down
2 changes: 1 addition & 1 deletion rs/moq-loc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub struct Frame {
}

/// Errors from LOC frame encode/decode.
#[derive(Debug, thiserror::Error)]
#[derive(Debug, Clone, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
/// The frame's property block did not contain a 0x06 (Timestamp) entry.
Expand Down
1 change: 0 additions & 1 deletion rs/moq-mux/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ doctest = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow = "1"
base64 = "0.22"
bytes = "1"
conducer = { workspace = true }
Expand Down
Loading
Loading