mrtp

package module
v0.0.0-...-2db96b1 Latest Latest
Warning

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

Go to latest
Published: Sep 24, 2026 License: MIT Imports: 8 Imported by: 0

README

MRTP

Overview

MRTP consists of several subcommands that support different transport protocols.

RTP over QUIC (RoQ)

The send and receive subcommands can send and receive video streams and data. They support RoQ and plain RTP over UDP.

If RoQ is activated, the video stream is sent using RTP over QUIC, according to the RoQ Internet-Draft and data is sent over a reliable data channel based on the QUIC Data Channels Internet-Draft.

Without RoQ, it sends the RTP packets over UDP without any signaling.

GStreamer is used for handling the video stream.

graph LR
  S["send<br/>cmd"] -->|roq| R["receive<br/>cmd"]
Experimental: RoQ without GStreamer

-media-pipeline go runs a custom video pipeline instead of GStreamer. It reads and writes Y4M, so it needs -source-location on the sender and -sink-location on the receiver: it has neither a test source nor a display.

graph LR
  S["send<br/>-media-pipeline go"] -->|roq| R["receive<br/>-media-pipeline go"]
WebRTC

Uses Pion WebRTC to send a video stream using RTP and data using WebRTC data channels. One of the peers must act as the offerer.

graph LR
  S["webrtc<br/>cmd"] -->|rtp| R["webrtc<br/>cmd"]
Chrome

The browser command can send a video stream and data using Chrome’s WebRTC library. As the congestion controller, Chrome uses its own GCC implementation.

graph LR
  S["browser<br/>cmd"] -->|rtp| R["webrtc<br/>cmd"]

Setup

Setup SCReAM Gstreamer plugin
  • Clone with submodules
  • In root directory, set GST_PLUGIN_PATH=./scream/gstscream/target/debug/ and LD_LIBRARY_PATH=./scream/code/wrapper_lib/
Setup gopipe

Only required for the experimental -media-pipeline go.

h264

Installation encoder:

  • Mac: brew install x264
  • Ubuntu: apt install libx264-dev

Installation decoder:

  • install libav
vpx

Installation:

  • Mac: brew install libvpx
  • Ubuntu: apt install libvpx-dev

Usage

RTP over QUIC (RoQ)

Start the receiver:

go run cmd/main.go receive -roq-server -roq-mapping 1

Start the sender:

go run cmd/main.go send -roq-client -roq-mapping 1 -bwe gcc

Add -source-location <path/to/video> to send a custom video instead of videotestsrc.

WebRTC

Start the receiver:

go run cmd/main.go webrtc -local-port 8081 -remote-port 8080 -pion-ccfb

Start the sender:

go run cmd/main.go webrtc -local-port 8080 -remote-port 8081 -pacing -bwe gcc -send-track - offer -pion-read-ccfb

Add -source-location <path/to/video> to send a custom video instead of videotestsrc.

Chrome

Start the webrtc command as receiver:

go run cmd/main.go webrtc -local-port 8081 -remote-port 8080 -sink-codec VP8 -pion-twcc

Start Chrome:

go run cmd/main.go browser -source-location <path/to/video> -local-port 8080 -remote-port 8081

Congestion Control Combinations

commands NADA GCC SCReAMv1 SCReAMv2
WebRTC webrtc ✅ ✅ ❌[^1] ❌[^1]
QUIC (RoQ) send, receive ✅ ✅ ❌[^2] ❌[^2]
UDP (Gst) send, receive without roq enabled ✅ ?[^3]

[^1]: There are two ways to implement this: Using the SCReAM Gstreamer plugin or using SCReAM directly from Pion interceptors. SCReAMs RFC8888 feedback is currently not compatible with Pion. One issue is https://github.com/EricssonResearch/scream/pull/66. Another one is some SSRC rewriting going on in SCReAM or Pion, which makes it impossible to pass feedback correctly. Should be possible to fix, but no idea when. [^2]: SCReAM will not work over RTP over QUIC because it is implemented with RTP in mind and requires access to packet queues from which it might try to drop packets. QUIC does not like dropping queued stuff (and does not even queue data in packets, packets are only created from queued stuff when it is send). [^3]: Should work, but behaves weird, possibly misconfigured parameters.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RTCPBytes

func RTCPBytes(p *RTCPPacket) *[]byte

RTCPBytes says where an RTCP packet keeps its buffer, for the io adapters.

func RTPBytes

func RTPBytes(p *RTPPacket) *[]byte

RTPBytes says where an RTP packet keeps its buffer, for the io adapters.

Types

type BWE

type BWE interface {
	OnAck(sequenceNumber uint64, size int, departure, arrival time.Time, ecn ECN)
	OnLoss(sequenceNumber uint64, size int, departure time.Time)
	UpdateRTT(rtt time.Duration)
	UpdateECNCounts(ect0, ect1, ce uint64)
	UpdateTargetRate(time.Time) int
}

type Codec

type Codec int

Codec identifies a media codec. It is the single codec type shared by the media pipelines (gstreamer, gopipe) and the transports.

const (
	H264 Codec = iota
	VP8
	VP9

	// Fake is a synthetic codec for RTP-only experiments. Its frames carry no
	// real media, only a size and a timestamp. Not every pipeline supports it.
	Fake
)

func NewCodec

func NewCodec(s string) (Codec, error)

NewCodec parses a codec name. Parsing is case insensitive.

func NewCodecFromMimeType

func NewCodecFromMimeType(mimeType string) (Codec, error)

NewCodecFromMimeType parses a codec from a "<media>/<codec>" MIME type, as negotiated by WebRTC. The media type is ignored, because every codec here is a video codec.

func (Codec) ClockRate

func (c Codec) ClockRate() int

ClockRate returns the RTP clock rate in Hz.

func (Codec) MediaType

func (c Codec) MediaType() string

MediaType returns the top level media type.

func (Codec) MimeType

func (c Codec) MimeType() string

MimeType returns the media type in "<media>/<codec>" form, as used by WebRTC and SDP.

func (Codec) String

func (c Codec) String() string

String returns the canonical codec name, as used for RTP encoding names and as the subtype of the media MIME type.

type Consumer

type Consumer[T any] interface {
	Element

	// Attach names the upstream puller.
	Attach(p Puller[T]) error
}

Consumer is a pull input: it reads from the puller it is attached to.

type Data

type Data struct{}

Data is the format of an edge carrying DataChunk.

func (Data) String

func (Data) String() string

type DataChunk

type DataChunk struct {
	Data []byte
}

DataChunk is non-media payload, such as a data channel's.

type Driver

type Driver interface {
	Element

	// Run moves packets until the stream ends, ctx is cancelled, or an error
	// occurs. It blocks, and returns nil at the end of the stream.
	Run(ctx context.Context) error
}

Driver is an element that needs a goroutine of its own. Exactly one element per scheduling segment is a Driver.

type ECN

type ECN uint8
const (
	ECNNonECT ECN = iota
	ECNECT1
	ECNECT0
	ECNCE
)

type Element

type Element interface {
	// Close releases the element's resources. It is safe to call more than
	// once.
	Close() error
}

Element is what a pipeline graph can own.

type EncodedFrame

type EncodedFrame struct {
	Data []byte

	PTS      time.Duration
	Duration time.Duration

	Keyframe bool
}

EncodedFrame is one coded picture.

type EncodedVideo

type EncodedVideo struct {
	Codec         Codec
	Width, Height uint
}

EncodedVideo is the format of an edge carrying EncodedFrame. It carries no frame rate, because the wire does not: each EncodedFrame times itself.

func (EncodedVideo) String

func (f EncodedVideo) String() string

type Format

type Format interface {
	fmt.Stringer
}

A Format says what an edge carries, with the parameters an element needs in order to configure itself for it. Each format pairs with one payload type by convention, so an element asserts the format it expects in Sink.Negotiate.

Formats are compared with ==, by the elements that merge several inputs into one output, so a format is a comparable value: a struct of scalars, not a pointer and not a struct holding a slice or a map.

type FrameRate

type FrameRate struct {
	Num, Den int
}

FrameRate is a nominal frame rate, in frames per second. Containers and codec APIs that want a timebase instead take the inverse fraction.

func (FrameRate) Duration

func (r FrameRate) Duration() time.Duration

Duration is how long one frame lasts.

func (FrameRate) String

func (r FrameRate) String() string

type GCC

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

func NewGCC

func NewGCC(initialRate, minRate, maxRate uint) (*GCC, error)

func (*GCC) OnAck

func (g *GCC) OnAck(sequenceNumber uint64, size int, departure time.Time, arrival time.Time, _ ECN)

OnAck implements BWE.

func (*GCC) OnLoss

func (g *GCC) OnLoss(uint64, int, time.Time)

OnLoss implements BWE.

func (*GCC) UpdateECNCounts

func (g *GCC) UpdateECNCounts(uint64, uint64, uint64)

UpdateECNCounts implements BWE.

func (*GCC) UpdateRTT

func (g *GCC) UpdateRTT(rtt time.Duration)

UpdateRTT implements BWE.

func (*GCC) UpdateTargetRate

func (g *GCC) UpdateTargetRate(time time.Time) int

UpdateTargetRate implements BWE.

type Nada

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

func NewNada

func NewNada(initRate, minRate, maxRate uint, feedbackInterval time.Duration) *Nada

func NewNadaWithConfig

func NewNadaWithConfig(config nada.Config) *Nada

func (*Nada) OnAck

func (n *Nada) OnAck(sequenceNumber uint64, size int, departure time.Time, arrival time.Time, ecn ECN)

OnAck implements BWE.

func (*Nada) OnLoss

func (n *Nada) OnLoss(sequenceNumber uint64, size int, departure time.Time)

OnLoss implements BWE.

func (*Nada) UpdateECNCounts

func (n *Nada) UpdateECNCounts(ect0 uint64, ect1 uint64, ce uint64)

UpdateECNCounts implements BWE.

func (*Nada) UpdateRTT

func (n *Nada) UpdateRTT(rtt time.Duration)

UpdateRTT implements BWE.

func (*Nada) UpdateTargetRate

func (n *Nada) UpdateTargetRate(time.Time) int

UpdateTargetRate implements BWE.

type Packet

type Packet[T any] interface {
	// Value is valid until Release.
	Value() *T

	// Clone returns an independent reference, which the caller must Release.
	Clone() Packet[T]

	// Release gives the reference up.
	Release()
}

A Packet is one owned reference to a value of type T. Sink.Write and Puller.Pull transfer ownership, so the receiver must either Release the packet or pass it downstream. Clone first to keep or fan out a packet.

type Puller

type Puller[T any] interface {
	Element

	// Format is what this puller produces.
	Format() Format

	// Pull hands the next packet to the caller, io.EOF at the end of the
	// stream.
	Pull(ctx context.Context) (Packet[T], error)
}

Puller is a pull output: its downstream calls Pull.

type RTCP

type RTCP struct{}

RTCP is the format of an edge carrying RTCPPacket. It has no parameters, because pipelines generate and parse RTCP internally.

func (RTCP) String

func (RTCP) String() string

type RTCPPacket

type RTCPPacket struct {
	Data []byte
}

RTCPPacket is one marshalled RTCP packet.

type RTP

type RTP struct {
	Codec       Codec
	PayloadType uint8
	SSRC        uint32
	ClockRate   uint32
}

RTP is the format of an edge carrying RTPPacket.

func (RTP) String

func (f RTP) String() string

type RTPPacket

type RTPPacket struct {
	Data []byte
}

RTPPacket is one marshalled RTP packet.

func (*RTPPacket) Marker

func (p *RTPPacket) Marker() bool

Marker reports the RTP marker bit, which ends an access unit.

type RTTSource

type RTTSource interface {
	// RTT returns the current round trip time of the connection.
	RTT() time.Duration
}

RTTSource is implemented by a transport endpoint that knows the round trip time of the connection.

It is optional: a media pipeline that adapts to the RTT, such as one deciding how long to wait for a missing packet, type-asserts its endpoint to it and falls back to a fixed value for a transport that does not know its RTT.

type RawFrame

type RawFrame struct {
	Y, Cb, Cr []byte

	PTS      time.Duration
	Duration time.Duration
}

RawFrame is one decoded picture, its planes pointing into pooled buffers.

type RawVideo

type RawVideo struct {
	Width, Height uint
	Subsampling   image.YCbCrSubsampleRatio
	FrameRate     FrameRate
}

RawVideo is the format of an edge carrying RawFrame.

func (RawVideo) String

func (f RawVideo) String() string

type Sink

type Sink[T any] interface {
	Element

	// Negotiate configures the sink for format f, or rejects it. It is called
	// once every edge is wired, before the first Write, and again before the
	// first packet of a new format.
	Negotiate(f Format) error

	// Write consumes one packet and takes ownership of it. It must not block
	// indefinitely: an element that cannot keep up drops instead.
	Write(p Packet[T]) error

	// EndOfStream reports that no more packets will arrive.
	EndOfStream() error
}

Sink is a push input: its upstream calls Write.

type Source

type Source[T any] interface {
	Element

	// Format is what this source produces.
	Format() Format

	// Connect names the downstream sink.
	Connect(s Sink[T]) error
}

Source is a push output: it writes into the sink it is connected to.

Directories

Path Synopsis
Package cmdmain implements commands and subcommands.
Package cmdmain implements commands and subcommands.
Package data carries non media payload as a pipeline: a source that produces chunks and a sink that consumes them, both over mrtp.DataChunk.
Package data carries non media payload as a pipeline: a source that produces chunks and a sink that consumes them, both over mrtp.DataChunk.
internal
testvideo
Package testvideo generates synthetic I420 video for tests, so they need no video file.
Package testvideo generates synthetic I420 video for tests, so they need no video file.
web
Package media defines the boundary between media pipelines and transports.
Package media defines the boundary between media pipelines and transports.
Package pipeline is the machinery behind the mrtp element model: pooled packets, the graph that wires elements together and drives them, and the generic elements that every pipeline needs.
Package pipeline is the machinery behind the mrtp element model: pooled packets, the graph that wires elements together and drives them, and the generic elements that every pipeline needs.
Package udp implements plain RTP over UDP as a transport.
Package udp implements plain RTP over UDP as a transport.

Jump to

Keyboard shortcuts

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