locmaf

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: MIT Imports: 6 Imported by: 0

README

LOCMAF

Reference implementation of LOCMAF (Low Overhead CMAF for MOQ) — a compact CMAF packaging for MoQ Transport, including DRM-protected content. Sample-level objects with a delta moof as small as 2 bytes, reconstructed into functionally lossless CMAF chunks at the receiver.

This repository is both the reference codec and its conformance suite: a stdlib-only Go implementation, a byte-pinned corpus of golden conformance vectors, and worked examples covering the packaging's edge cases — negative CTOs, CENC/cbcs carriage, BMDT re-anchoring, event-only chunks, and more.

Layout

locmaf/              package locmaf — codec: EncodeCanonical, Decode, ReconstructCanonical
├── vi64/            MOQT vi64 varints + zigzag (stdlib-only)
├── conform/         shared verify/dump/align conformance core (I/O-free; used by the CLI and the wasm build)
├── cmd/locmaf/      CLI: align, pack, dump, verify, vectors
├── cmd/locmaf-wasm/ browser (js/wasm) build of the conformance checker
├── testdata/        golden canonical-encoding vectors (see testdata/vectors/README.md)
└── web/             locmaf.dev site + /tools/ checker (separate stub module, not part of the Go module)

The codec implements packaging version 0.3: the element sequence (genBox / full / delta headers), vi64 integers, full 32-bit sample_flags, derived-only delta BMDT, scheme-agnostic CENC carriage, and the canonical reconstruction (byte-exact moof rebuild including senc/saiz/saio).

Command-line tool

cmd/locmaf is a go install-able CLI. Exit codes: 0 success, 1 findings (misalignment, corpus drift, or a malformed object), 2 usage or I/O error.

align — CMAF/LOCMAF round-trip conformance
locmaf align [-init init.mp4] [-report text|json] [-canon-out path] [-bytes] input.cmaf

Per fragment, asserts that canonical reconstruction straight from the source moof equals the encode→decode→reconstruct round trip, byte-identically. For a normalized fragment it explains, box and field at a time, how the canonical form differs from the source — e.g. moof/mfhd: sequence_number 3 → 0 [SEQUENCE_ZEROED], moof/traf/tfdt: version 0 → 1 [TFDT_WIDENED], moof/traf/trun: per-sample sample_size list dropped [REDUNDANT_DROPPED] — each tagged with its reason. (A raw byte diff would mislead here: the smaller canonical moof shifts everything after it, so -bytes adds the first-differing-byte hex window only on request.) With -canon-out <path> ("-" for stdout) it also writes the canonical CMAF — the input's init region unchanged followed by each chunk's canonical form — so align can generate canonical reference files, not just report differences. Those bytes are written only when every chunk aligns; when they go to stdout the report is routed to stderr so the two streams do not interleave.

pack — CMAF → .locmaf
locmaf pack [-init init.mp4] [-no-init] [-o out.locmaf] input.cmaf

Encodes a fragmented CMAF file into the self-framed .locmaf file format: a leading in-band rawBoxes init Object followed by one length-prefixed LOCMAF Object per chunk. The file is a single group — one delta chain, with a full header at the start and only re-anchoring on a timeline (BMDT) discontinuity; CMAF segment structure rides in the styp genBoxes. -no-init omits the init Object for bare media output (decoding then needs a separate init); output defaults to stdout.

dump — inspect a .locmaf
locmaf dump [-init init.mp4] [-report text|json] input.locmaf

Walks a .locmaf file and reports each Object — rawBoxes, full, or delta header — with its genBoxes, sample count, BMDT, and payload size.

verify — conformance-check a .locmaf
locmaf verify [-init init.mp4] [-report text|json] [-decodable] input.locmaf

Checks that a .locmaf file is a conformant LOCMAF stream — the wire-format analog of align. Per Object it runs the conformance ladder: it decodes, reconstructs a canonical CMAF chunk, and (unless -decodable) re-encodes that chunk and requires the result to be byte-identical to the wire Object, i.e. the Object is itself canonically encoded. -decodable relaxes the check to "decodes and reconstructs" for streams you do not require to be canonical. Exit 1 on any non-conformant Object.

vectors gen / vectors check manage the conformance corpus; see below.

Conformance vectors and golden files

testdata/vectors/ holds a codec-derived conformance corpus — one directory per case, each a worked example with the source init, the bare LOCMAF Objects (*.locmafobj), the reconstructed canonical CMAF chunks (*.cmfc), and the decoded effective values. Selected cases also carry a self-framed, self-contained file.locmaf. The corpus (including its own README, which describes every case) is regenerated from the codec and byte-pinned in CI:

locmaf vectors gen     # rewrite the corpus from the codec
locmaf vectors check   # re-derive and byte-compare against disk

Browser conformance checker

https://locmaf.dev/tools/ runs the same conformance core in the browser via WebAssembly (cmd/locmaf-wasm, a shim over the conform package): drop a .locmaf file to verify it, or a fragmented CMAF file to align it. Everything runs client-side — the file never leaves your machine. The page is built by web/'s npm run build (which compiles the wasm first) and served as static files; see web/.

License

MIT — see LICENSE.

Documentation

Overview

Package locmaf implements LOCMAF (Low Overhead CMAF for MOQ), a compact CMAF packaging for MoQ Transport defined by the Internet-Draft draft-einarsson-moq-locmaf.

A LOCMAF Object payload is a self-delimiting element sequence: zero or more genBox elements (pre-moof boxes such as styp, prft, and emsg, carried verbatim), exactly one full or delta moof header, and the raw mdat payload — or, alternatively, a single rawBoxes element carrying complete ISO BMFF boxes verbatim. The receiver reconstructs a functionally lossless CMAF chunk; a normative canonical reconstruction makes conformant receivers byte-identical, enabling golden-vector conformance testing.

This module is the reference implementation. EncodeCanonical produces canonical LOCMAF Objects from CMAF moof boxes (choosing full or delta headers per the canonical rules), EncodeRaw wraps complete boxes as a rawBoxes Object, Decode applies deltas and deletions against the in-group State and yields the chunk's EffectiveValues (or the raw boxes verbatim), and ReconstructCanonical builds the byte-exact canonical CMAF chunk from the effective values. AppendFramed and NextFramed implement the length-prefixed self-framed carriage used outside MOQT (the .locmaf file format). The vi64 subpackage implements the MOQT variable-length integer encoding and the zigzag signed variant that LOCMAF uses.

Specification: https://datatracker.ietf.org/doc/draft-einarsson-moq-locmaf/

Index

Constants

View Source
const (
	ElementTypeGenBox      uint64 = 1
	ElementTypeFullHeader  uint64 = 2
	ElementTypeDeltaHeader uint64 = 3
	ElementTypeRawBoxes    uint64 = 4
)

Element types. Each element of a LOCMAF Object payload begins with an element_type vi64; the mdat payload that follows the header element is untagged. A rawBoxes element is the sole element of its Object. An unknown element type is not self-delimiting and rejects the whole Object.

View Source
const Version = "0.3"

Version is the LOCMAF packaging version implemented by this package, announced in the CMSF catalog Track entry as locmafVersion.

Variables

View Source
var (
	ErrMalformed = errors.New("locmaf: malformed object")
	ErrBadSource = errors.New("locmaf: source not expressible in LOCMAF")
)

Sentinel errors. Wire-level violations that a receiver MUST reject wrap ErrMalformed; source content that cannot be expressed in LOCMAF wraps ErrBadSource.

Functions

func AppendFramed

func AppendFramed(dst, obj []byte) []byte

AppendFramed appends one LOCMAF Object to dst, prefixed by its vi64 length, and returns the extended slice.

func EncodeCanonical

func EncodeCanonical(genBoxes []GenBox, moof *mp4.MoofBox, mdatPayload []byte,
	prev *State, moov *mp4.MoovBox) ([]byte, error)

EncodeCanonical encodes one CMAF chunk as a canonical LOCMAF Object: the genBox elements, one full or delta header, and the mdat payload.

The header type follows the canonical rule: a full header when prev holds no in-group reference (the first chunk of a group) or when the source BMDT diverges from the delta derivation (a timeline discontinuity re-anchors with a full header); a delta header otherwise. prev is mutated to reflect the just-emitted chunk; it must not be nil.

func EncodeRaw

func EncodeRaw(boxes []byte, prev *State) ([]byte, error)

EncodeRaw encodes complete ISO BMFF boxes, carried verbatim, as a rawBoxes LOCMAF Object — the escape from the moof-header model for content LOCMAF does not otherwise carry: an in-band CMAF Header (ftyp + moov) in self-framed carriage, or a chunk whose moof falls outside the LOCMAF field model. boxes must be one or more complete boxes, each carrying its actual size in the 32-bit size field (the ISO size escapes 0 and 1 are not allowed). The element carries no length of its own — the Object length delimits it. A rawBoxes Object resets the in-group delta chain, so prev is Reset and the next EncodeCanonical chunk in the group emits a full header; prev must not be nil.

func NextFramed

func NextFramed(data []byte) (obj, rest []byte, err error)

NextFramed splits data into its first length-prefixed LOCMAF Object and the remaining bytes. Callers loop until rest is empty; obj is a subslice of data.

func ReconstructCanonical

func ReconstructCanonical(moov *mp4.MoovBox, eff *EffectiveValues) ([]byte, error)

ReconstructCanonical builds the canonical CMAF chunk bytes — each genBox wrapped as an ISO box, the moof, and the mdat — from the chunk's effective values and the CMAF Header's moov.

Types

type EffectiveValues

type EffectiveValues struct {
	SampleCount            int
	BMDT                   uint64
	SampleDescriptionIndex uint32

	// Per-sample vectors, each SampleCount long.
	Durations []uint32
	Sizes     []uint32
	Flags     []uint32
	CTOs      []int32

	// CENC per-sample auxiliary information. IVs is the concatenation
	// of per-sample initialization vectors, PerSampleIVSize bytes each.
	// HasSubsamples reports whether the effective subsample map is
	// present; when true, SubsampleCounts has SampleCount entries and
	// ClearBytes/ProtectedBytes are flattened in chunk order.
	PerSampleIVSize uint8
	IVs             []byte
	HasSubsamples   bool
	SubsampleCounts []uint16
	ClearBytes      []uint16
	ProtectedBytes  []uint32

	// GenBoxes render before the moof, in order. MdatPayload is the raw
	// sample data (a subslice of the decoded object payload).
	GenBoxes    []GenBox
	MdatPayload []byte
}

EffectiveValues is a decoded chunk's meaning: the per-sample vectors after applying deltas, deletions, and the sample-size and BMDT derivations. It is the only chunk-derived input to ReconstructCanonical; the remaining inputs come from the CMAF Header.

func Decode

func Decode(payload []byte, prev *State, moov *mp4.MoovBox) (*EffectiveValues, []byte, error)

Decode decodes one LOCMAF Object payload, using prev as the in-group reference for delta chunks. For a moof-carrying Object it returns the chunk's effective values and a nil raw slice; for a rawBoxes Object it returns nil effective values and the carried boxes verbatim (a subslice of payload), which are also their own canonical form. prev is mutated to reflect the decoded Object (a full header resets it first; a rawBoxes Object resets it, so the next moof-carrying Object must be full); it must not be nil. Callers use one State per MOQT group, in object order, and Reset it (or use a fresh one) at every group boundary.

On error, prev is Reset: a malformed Object is a loss of in-group sync, so subsequent delta chunks are rejected until the next full header or rawBoxes Object re-anchors, matching the receiver rule for gaps.

func ExtractEffective

func ExtractEffective(genBoxes []GenBox, moof *mp4.MoofBox, mdatPayload []byte,
	moov *mp4.MoovBox) (*EffectiveValues, error)

ExtractEffective derives a chunk's effective values directly from a source CMAF moof — resolving per-sample trun values against the tfhd and trex defaults exactly as EncodeCanonical does, with no wire round-trip. An interop harness uses it to reconstruct canonical bytes straight from source CMAF and compare them against the encode-then-decode path.

type GenBox

type GenBox struct {
	Name    string
	Payload []byte
}

GenBox is one generic pre-moof box carried verbatim: the ISO box type FourCC and the box contents without the 8-byte ISO box header. For a uuid box the 16-byte usertype is the first 16 bytes of Payload.

type State

type State struct {
	// contains filtered or unexported fields
}

State carries the per-group in-group reference that both encoder and decoder consult for delta chunks. Callers keep one State per MOQT group and Reset it (or use a fresh one) when a new group begins. A full header resets it implicitly on both sides.

func NewState

func NewState() *State

NewState returns an empty State.

func (*State) Reset

func (s *State) Reset()

Reset empties the State so the next chunk is encoded as (or must be) a full header, e.g. at the start of a new MOQT group.

Directories

Path Synopsis
cmd
locmaf command
Command locmaf is the LOCMAF reference tooling: a CMAF/LOCMAF round-trip aligner and the golden-vector corpus generator/checker.
Command locmaf is the LOCMAF reference tooling: a CMAF/LOCMAF round-trip aligner and the golden-vector corpus generator/checker.
locmaf-wasm command
Package conform is the shared conformance core behind the locmaf CLI and its browser (js/wasm) build.
Package conform is the shared conformance core behind the locmaf CLI and its browser (js/wasm) build.
vectorgen
Package vectorgen defines the golden-vector case matrix and the generation/verification machinery around it.
Package vectorgen defines the golden-vector case matrix and the generation/verification machinery around it.
Package vi64 implements the MOQT variable-length integer encoding (Section 1.4.1 of draft-ietf-moq-transport-18) and the zigzag signed variant that LOCMAF (draft-einarsson-moq-locmaf) layers on top of it.
Package vi64 implements the MOQT variable-length integer encoding (Section 1.4.1 of draft-ietf-moq-transport-18) and the zigzag signed variant that LOCMAF (draft-einarsson-moq-locmaf) layers on top of it.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL