rtp

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Aug 27, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Index

Constants

View Source
const (
	RtcpPtSr         uint8 = 200
	RtcpPtSdes       uint8 = 202
	RtcpPtPsfb       uint8 = 206
	RtcpPtWaCompact  uint8 = 208
	RtcpPtWaCompact2 uint8 = 209
	RtcpHeaderLen    int   = 8
	SrtcpTrailerLen  int   = 14

	WhatsappRtcpCnameLen = 18
)
View Source
const (
	RtpPayloadTypeOpus uint8 = 120
	// RtpPayloadTypeAppData carries protobuf call reactions and other RTC app data.
	RtpPayloadTypeAppData uint8 = 119
	// RtpPayloadTypeH264 is the WhatsApp video (H.264) RTP payload type, used to demux
	// video off the relay. Source of truth: https://github.com/JotaDev66/WaCalls/blob/2d6a1f666426049a89ef9541414e771acdcf8a16/internal/voip/core/types.go#L44
	RtpPayloadTypeH264          uint8  = 97
	WhatsappRtpExtensionProfile uint16 = 0xdebe
	WhatsappRtpHeaderSize       int    = 16
	WhatsappRtpHeaderDtxSize    int    = 20
	WhatsappVideoRtpHeaderSize  int    = 28
	WhatsappRtpExtensionDtxWord uint32 = 0x30010000
	VideoMediaFrameInfoIDR      uint8  = 0x08
	VideoMediaFrameInfoDelta    uint8  = 0x20
)
View Source
const (
	HBHFECTXSlotWord uint32 = 7
	HBHFECRXSlotWord uint32 = 8
)

HBHFECTXSlotWord and HBHFECRXSlotWord are the deterministic local hop-by-hop FEC stream slots advertised when the relay switches to multi-party SFU mode.

View Source
const AppDataSlotWord uint32 = 6

AppDataSlotWord is the relay stream slot for RTC app-data such as call reactions.

View Source
const VideoSlotWord uint32 = 2

VideoSlotWord is the relay stream slot for a participant's video SSRC (audio is slot 0). Source of truth: https://github.com/JotaDev66/WaCalls/blob/2d6a1f666426049a89ef9541414e771acdcf8a16/internal/voip/call/callmanager_video.go#L13

Variables

View Source
var OpusPrimingFrame1 = [18]byte{
	0x12, 0x36, 0x26, 0x2b, 0x4a, 0xc8, 0x2b, 0x09, 0xc9, 0x1f, 0x34, 0xc2, 0xd6, 0x7a, 0x01, 0x73,
	0x1b, 0x2e,
}

OpusPrimingFrame1 is the Android first priming frame (18 bytes).

View Source
var OpusPrimingFrame1Wasm = [24]byte{
	0x32, 0x36, 0x26, 0x2b, 0x4a, 0xcb, 0x1b, 0x5f, 0xba, 0x91, 0x68, 0x7e, 0xb8, 0x50, 0x93, 0x58,
	0xe6, 0xd0, 0xa3, 0xa9, 0xd7, 0x1d, 0x81, 0x8c,
}

OpusPrimingFrame1Wasm is the WASM/Web caller priming frame (24 bytes).

View Source
var OpusPrimingFrame2 = [5]byte{0x90, 0xb8, 0x14, 0x14, 0xc4}

OpusPrimingFrame2 is the second priming frame (5 bytes).

View Source
var WasmRelayStreamSlotWords = [9]uint32{0, 1, 4, 2, 3, 5, 7, 8, 6}

WasmRelayStreamSlotWords are the slot words for the 9-stream relay allocate plan.

Functions

func AUHasIDR

func AUHasIDR(au []byte) bool

AUHasIDR reports whether an Annex-B access unit contains an IDR NAL unit.

func BuildCompactRtcp208

func BuildCompactRtcp208(localSsrc, remoteSsrc uint32, log ...zerolog.Logger) [12]byte

BuildCompactRtcp208 builds the 12-byte compact RTCP (PT 208, RC=1).

func BuildCompactRtcp209

func BuildCompactRtcp209(localSsrc uint32, log ...zerolog.Logger) [8]byte

BuildCompactRtcp209 builds the 8-byte compact RTCP (PT 209, RC=1).

func BuildGroupSenderReport

func BuildGroupSenderReport(localSSRC uint32, stats *RtcpSenderStats, nowMs uint64, report *RtcpReceptionReport, extension RTCPGroupReportExtension) []byte

BuildGroupSenderReport builds the capture-observed group audio SR with one reception block, its opaque extension, and no SDES packet.

func BuildPictureLossIndication

func BuildPictureLossIndication(senderSSRC, mediaSSRC uint32, profileExtension bool) [12]byte

BuildPictureLossIndication builds an RFC 4585 PLI asking the sender of mediaSSRC for a fresh intra frame.

func BuildSenderReport

func BuildSenderReport(localSsrc uint32, stats *RtcpSenderStats, nowMs uint64, log ...zerolog.Logger) [28]byte

BuildSenderReport builds the 28-byte Sender Report (PT 200, RC=0); nowMs is wall-clock ms.

func BuildSenderReportWithSdes

func BuildSenderReportWithSdes(localSsrc uint32, stats *RtcpSenderStats, nowMs uint64, cname *[WhatsappRtcpCnameLen]byte, profileExtension bool) []byte

BuildSenderReportWithSdes builds WhatsApp's periodic compound SR+SDES packet.

func BuildSenderReportWithSdesAndReception

func BuildSenderReportWithSdesAndReception(localSsrc uint32, stats *RtcpSenderStats, nowMs uint64, cname *[WhatsappRtcpCnameLen]byte, report *RtcpReceptionReport, profileExtension bool) []byte

BuildSenderReportWithSdesAndReception builds WhatsApp's native 1:1 compound report. Its receive block is the RFC 3550 layout followed by 24 zero-valued transport/BWE fields, matching the native unavailable-value representation. Source of truth: https://github.com/oxidezap/whatsapp-rust/blob/d37b1756d05fb34c9b6c2410c48dd20d27394929/wacore/src/voip/rtcp.rs#L461-L583

func BuildSourceDescription

func BuildSourceDescription(localSsrc uint32, cname *[WhatsappRtcpCnameLen]byte, profileExtension bool) [32]byte

BuildSourceDescription builds WhatsApp's one-chunk SDES packet.

func BuildWhatsappRtcpCname

func BuildWhatsappRtcpCname(entropy [12]byte) [WhatsappRtcpCnameLen]byte

BuildWhatsappRtcpCname builds the native 18-byte randomized CNAME shape.

func DeriveWasmParticipantSsrc

func DeriveWasmParticipantSsrc(callID, lid string, slotWord uint32, log ...zerolog.Logger) (uint32, error)

DeriveWasmParticipantSsrc derives a participant/stream SSRC: HKDF-SHA256(salt=slotWord LE32, ikm=callID, info=lid, 4), read back as LE u32.

func DeriveWasmRelayStreamSsrcs

func DeriveWasmRelayStreamSsrcs(callID, lid string, log ...zerolog.Logger) ([9]uint32, error)

DeriveWasmRelayStreamSsrcs derives all 9 relay-stream SSRCs in slot order.

func E2EParticipantIDVariants

func E2EParticipantIDVariants(jid string, log ...zerolog.Logger) []string

E2EParticipantIDVariants lists the device-qualified LID variants the recv path tries as HKDF info (peer sender LIDs), deduplicated in insertion order.

func EncodeRtpHeader

func EncodeRtpHeader(header *RtpHeader, log ...zerolog.Logger) []byte

EncodeRtpHeader encodes the RTP header and its WhatsApp extension.

func EstimateSrtpRtpWireBytes

func EstimateSrtpRtpWireBytes(opusPayload []byte) int

EstimateSrtpRtpWireBytes estimates the on-wire SRTP size (header + opus + tag).

func FormatE2ESrtpParticipantID

func FormatE2ESrtpParticipantID(jid string) string

FormatE2ESrtpParticipantID formats the device-qualified LID for E2E-SRTP HKDF info.

func IsOpusDtxPayload

func IsOpusDtxPayload(payload []byte) bool

IsOpusDtxPayload reports DTX / comfort-noise frames (RFC 0x10, mlow 0x90, warmup).

func IsOpusMlowSpeechPayload

func IsOpusMlowSpeechPayload(payload []byte) bool

IsOpusMlowSpeechPayload reports mlow speech frames (20ms 0x48..0x4f or 60ms 0x50..0x57).

func IsOpusPrimingPayload

func IsOpusPrimingPayload(payload []byte) bool

IsOpusPrimingPayload reports whether the payload equals a priming frame.

func IsRtcpPacket

func IsRtcpPacket(data []byte) bool

IsRtcpPacket reports whether data is an RTCP packet (vs a WhatsApp RTP packet).

func IsRtpVersion2

func IsRtpVersion2(data []byte) bool

IsRtpVersion2 reports a version-2 RTP packet.

func IsWhatsappOpusRtpPayload

func IsWhatsappOpusRtpPayload(payloadType uint8) bool

IsWhatsappOpusRtpPayload reports whether the payload type is WhatsApp Opus.

func PackageH264NALU

func PackageH264NALU(nalu []byte) [][]byte

PackageH264NALU splits one NAL unit into RTP payloads: a single payload when it fits the MTU budget, else FU-A fragments.

func PackageH264STAPA

func PackageH264STAPA(nalus [][]byte) []byte

PackageH264STAPA aggregates several small NAL units into one STAP-A payload, or nil when there are fewer than two or the aggregate would exceed the MTU budget.

func ParseRtcpSenderSsrc

func ParseRtcpSenderSsrc(data []byte, log ...zerolog.Logger) (uint32, bool)

ParseRtcpSenderSsrc returns the sender SSRC (bytes 4-7); ok=false if malformed.

func ParseSenderReportTiming

func ParseSenderReportTiming(data []byte) (senderSsrc, ntpSeconds, ntpFraction uint32, ok bool)

ParseSenderReportTiming extracts the first SR sender SSRC and NTP timestamp from a compound RTCP packet.

func RtcpPayloadType

func RtcpPayloadType(data []byte) (uint8, bool)

RtcpPayloadType returns the RTCP payload type; ok=false if not an RTCP packet.

func RtcpRequestsKeyframe

func RtcpRequestsKeyframe(data []byte, localVideoSsrc uint32) bool

RtcpRequestsKeyframe reports whether a compound RTCP packet contains PLI/FIR feedback for localVideoSsrc.

func RtpExtensionProfileAndData

func RtpExtensionProfileAndData(data []byte) (uint16, []byte, bool)

RtpExtensionProfileAndData returns the extension profile and word-aligned payload.

func RtpHeaderByteLength

func RtpHeaderByteLength(data []byte, log ...zerolog.Logger) (int, bool)

RtpHeaderByteLength returns the full on-wire header size (12 + CSRC + ext); ok=false if malformed.

func SplitAnnexB

func SplitAnnexB(data []byte) [][]byte

SplitAnnexB splits an Annex-B byte stream (00 00 01 / 00 00 00 01 start codes) into its constituent NAL units, trimming trailing zero bytes before each start code.

Types

type H264AccessUnitAssembler

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

H264AccessUnitAssembler reconstructs complete Annex-B access units while withholding damaged interframes until an IDR restores decoder state.

func (*H264AccessUnitAssembler) Push

func (a *H264AccessUnitAssembler) Push(sequence uint16, marker bool, payload []byte) ([]byte, bool, bool)

Push consumes one ordered RTP payload and returns a complete, decodable access unit when the marker closes the frame.

type H264Depacketizer

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

H264Depacketizer reassembles H.264 NAL units from RFC 6184 RTP payloads (single NAL, STAP-A, FU-A), carrying FU-A fragment state across packets.

func (*H264Depacketizer) Depacketize

func (d *H264Depacketizer) Depacketize(payload []byte) [][]byte

Depacketize consumes one RTP payload and returns the NAL units it produced (zero for a mid-fragment, one for single/FU-A completion, many for STAP-A).

type Option

type Option func(*config)

Option configures optional, non-behavioral aspects (currently the diagnostic logger).

func WithLogger

func WithLogger(l zerolog.Logger) Option

WithLogger sets the zerolog logger for debug/trace diagnostics; default is silent.

type RTCPGroupReportExtension

type RTCPGroupReportExtension [8]byte

RTCPGroupReportExtension is the opaque eight-byte suffix on one native group audio reception report.

type RtcpReceptionReport

type RtcpReceptionReport struct {
	Ssrc                       uint32
	FractionLost               uint8
	CumulativeLost             int32
	ExtendedHighestSequence    uint32
	Jitter                     uint32
	LastSenderReport           uint32
	DelaySinceLastSenderReport uint32
}

RtcpReceptionReport is the RFC 3550 receive-stream state carried in a Sender Report. WhatsApp appends 24 bytes of transport statistics after this block.

type RtcpReceptionStats

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

RtcpReceptionStats tracks one inbound RTP stream and produces interval loss, jitter, LSR, and DLSR fields for periodic reception reports. Its methods are safe to call from the media receive loop and the RTCP ticker concurrently. Source of truth: https://github.com/oxidezap/whatsapp-rust/blob/d37b1756d05fb34c9b6c2410c48dd20d27394929/wacore/src/voip/rtcp.rs#L255-L388

func (*RtcpReceptionStats) Observe

func (s *RtcpReceptionStats) Observe(ssrc uint32, sequence uint16, rtpTimestamp uint32, arrivalMs uint64, clockRate uint32)

Observe records one authenticated inbound RTP packet.

func (*RtcpReceptionStats) ObserveSenderReport

func (s *RtcpReceptionStats) ObserveSenderReport(senderSsrc, ntpSeconds, ntpFraction uint32, arrivalMs uint64)

ObserveSenderReport records the compact NTP timestamp needed for LSR/DLSR.

func (*RtcpReceptionStats) Report

func (s *RtcpReceptionStats) Report(nowMs uint64) *RtcpReceptionReport

Report snapshots interval and cumulative reception state.

type RtcpReceptionStatsSet

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

RtcpReceptionStatsSet retains independent RTCP reception state per inbound media SSRC.

func (*RtcpReceptionStatsSet) Observe

func (s *RtcpReceptionStatsSet) Observe(
	ssrc uint32,
	sequence uint16,
	rtpTimestamp uint32,
	arrivalMs uint64,
	clockRate uint32,
)

Observe records one authenticated RTP packet in its SSRC-specific state.

func (*RtcpReceptionStatsSet) ObserveSenderReport

func (s *RtcpReceptionStatsSet) ObserveSenderReport(
	senderSSRC uint32,
	ntpSeconds uint32,
	ntpFraction uint32,
	arrivalMs uint64,
)

ObserveSenderReport records sender timing in the matching SSRC-specific state.

func (*RtcpReceptionStatsSet) Reports

func (s *RtcpReceptionStatsSet) Reports(nowMs uint64) []*RtcpReceptionReport

Reports snapshots every tracked stream in ascending SSRC order.

func (*RtcpReceptionStatsSet) Retain

func (s *RtcpReceptionStatsSet) Retain(ssrcs []uint32)

Retain removes reception state for SSRCs absent from the authoritative active roster.

type RtcpSenderStats

type RtcpSenderStats struct {
	PacketsSent  uint32
	OctetsSent   uint32
	RtpTimestamp uint32
}

RtcpSenderStats are the Sender Report counters.

type RtpHeader

type RtpHeader struct {
	Marker         bool
	PayloadType    uint8
	SequenceNumber uint16
	Timestamp      uint32
	Ssrc           uint32
	ExtensionWord  *uint32            // nil = no audio extension word
	VideoExtension *VideoRtpExtension // nil = no video extension block
}

RtpHeader is the fixed RTP header plus an optional 0xdebe extension.

func ParseRtpHeader

func ParseRtpHeader(data []byte, log ...zerolog.Logger) (RtpHeader, bool)

ParseRtpHeader parses the fixed RTP header fields (the extension word is not decoded).

func (*RtpHeader) ByteSize

func (h *RtpHeader) ByteSize() int

ByteSize is the on-wire header size.

type RtpStream

type RtpStream struct {
	Ssrc uint32
	// contains filtered or unexported fields
}

RtpStream is the send-side RTP sequencer: seq starts at 1, timestamp advances per packet.

func NewRtpStream

func NewRtpStream(ssrc, samplesPerPacket uint32, warpPiggyback bool, opts ...Option) *RtpStream

NewRtpStream builds a sequencer for ssrc with samplesPerPacket per packet.

func (*RtpStream) NextPacket

func (s *RtpStream) NextPacket(payload []byte, marker bool) RtpHeader

NextPacket builds the next RTP header for payload, latching the marker on the first speech frame.

func (*RtpStream) NextPreSpeechPacket

func (s *RtpStream) NextPreSpeechPacket() RtpHeader

NextPreSpeechPacket builds a pre-speech ladder packet (advances seq/timestamp, no marker/latch).

type VideoRtpExtension

type VideoRtpExtension struct {
	MediaFrameInfo    uint8
	FrameNumber       *uint16
	InitialBandwidth  uint16
	ShortOffset       int16
	TransportSequence uint16
}

VideoRtpExtension is WhatsApp's video RTP metadata extension set.

func ParseWhatsappVideoExtension

func ParseWhatsappVideoExtension(data []byte) (*VideoRtpExtension, bool)

ParseWhatsappVideoExtension decodes WhatsApp's one-byte-header video extensions.

func (*VideoRtpExtension) DisplayOrientation

func (e *VideoRtpExtension) DisplayOrientation() int

DisplayOrientation returns the CVO receiver rotation as clockwise quarter turns.

type VideoRtpStream

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

VideoRtpStream sequences WhatsApp video packets. All packets in one access unit share a timestamp; the marker packet advances the 90 kHz clock.

func NewVideoRtpStream

func NewVideoRtpStream(ssrc, tsStride uint32) *VideoRtpStream

func (*VideoRtpStream) NextPacket

func (s *VideoRtpStream) NextPacket(lastInAccessUnit bool, mediaFrameInfo uint8) RtpHeader

func (*VideoRtpStream) RtpTimestamp

func (s *VideoRtpStream) RtpTimestamp() uint32

func (*VideoRtpStream) SetTimestampStride

func (s *VideoRtpStream) SetTimestampStride(tsStride uint32) bool

Jump to

Keyboard shortcuts

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