Documentation
¶
Index ¶
- Constants
- Variables
- func AUHasIDR(au []byte) bool
- func BuildCompactRtcp208(localSsrc, remoteSsrc uint32, log ...zerolog.Logger) [12]byte
- func BuildCompactRtcp209(localSsrc uint32, log ...zerolog.Logger) [8]byte
- func BuildGroupSenderReport(localSSRC uint32, stats *RtcpSenderStats, nowMs uint64, ...) []byte
- func BuildPictureLossIndication(senderSSRC, mediaSSRC uint32, profileExtension bool) [12]byte
- func BuildSenderReport(localSsrc uint32, stats *RtcpSenderStats, nowMs uint64, log ...zerolog.Logger) [28]byte
- func BuildSenderReportWithSdes(localSsrc uint32, stats *RtcpSenderStats, nowMs uint64, ...) []byte
- func BuildSenderReportWithSdesAndReception(localSsrc uint32, stats *RtcpSenderStats, nowMs uint64, ...) []byte
- func BuildSourceDescription(localSsrc uint32, cname *[WhatsappRtcpCnameLen]byte, profileExtension bool) [32]byte
- func BuildWhatsappRtcpCname(entropy [12]byte) [WhatsappRtcpCnameLen]byte
- func DeriveWasmParticipantSsrc(callID, lid string, slotWord uint32, log ...zerolog.Logger) (uint32, error)
- func DeriveWasmRelayStreamSsrcs(callID, lid string, log ...zerolog.Logger) ([9]uint32, error)
- func E2EParticipantIDVariants(jid string, log ...zerolog.Logger) []string
- func EncodeRtpHeader(header *RtpHeader, log ...zerolog.Logger) []byte
- func EstimateSrtpRtpWireBytes(opusPayload []byte) int
- func FormatE2ESrtpParticipantID(jid string) string
- func IsOpusDtxPayload(payload []byte) bool
- func IsOpusMlowSpeechPayload(payload []byte) bool
- func IsOpusPrimingPayload(payload []byte) bool
- func IsRtcpPacket(data []byte) bool
- func IsRtpVersion2(data []byte) bool
- func IsWhatsappOpusRtpPayload(payloadType uint8) bool
- func PackageH264NALU(nalu []byte) [][]byte
- func PackageH264STAPA(nalus [][]byte) []byte
- func ParseRtcpSenderSsrc(data []byte, log ...zerolog.Logger) (uint32, bool)
- func ParseSenderReportTiming(data []byte) (senderSsrc, ntpSeconds, ntpFraction uint32, ok bool)
- func RtcpPayloadType(data []byte) (uint8, bool)
- func RtcpRequestsKeyframe(data []byte, localVideoSsrc uint32) bool
- func RtpExtensionProfileAndData(data []byte) (uint16, []byte, bool)
- func RtpHeaderByteLength(data []byte, log ...zerolog.Logger) (int, bool)
- func SplitAnnexB(data []byte) [][]byte
- type H264AccessUnitAssembler
- type H264Depacketizer
- type Option
- type RTCPGroupReportExtension
- type RtcpReceptionReport
- type RtcpReceptionStats
- type RtcpReceptionStatsSet
- func (s *RtcpReceptionStatsSet) Observe(ssrc uint32, sequence uint16, rtpTimestamp uint32, arrivalMs uint64, ...)
- func (s *RtcpReceptionStatsSet) ObserveSenderReport(senderSSRC uint32, ntpSeconds uint32, ntpFraction uint32, arrivalMs uint64)
- func (s *RtcpReceptionStatsSet) Reports(nowMs uint64) []*RtcpReceptionReport
- func (s *RtcpReceptionStatsSet) Retain(ssrcs []uint32)
- type RtcpSenderStats
- type RtpHeader
- type RtpStream
- type VideoRtpExtension
- type VideoRtpStream
Constants ¶
const ( RtcpPtSr uint8 = 200 RtcpPtSdes uint8 = 202 RtcpPtPsfb uint8 = 206 RtcpPtWaCompact uint8 = 208 RtcpPtWaCompact2 uint8 = 209 RtcpHeaderLen int = 8 SrtcpTrailerLen int = 14 WhatsappRtcpCnameLen = 18 )
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 )
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.
const AppDataSlotWord uint32 = 6
AppDataSlotWord is the relay stream slot for RTC app-data such as call reactions.
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 ¶
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).
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).
var OpusPrimingFrame2 = [5]byte{0x90, 0xb8, 0x14, 0x14, 0xc4}
OpusPrimingFrame2 is the second priming frame (5 bytes).
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 BuildCompactRtcp208 ¶
BuildCompactRtcp208 builds the 12-byte compact RTCP (PT 208, RC=1).
func BuildCompactRtcp209 ¶
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 ¶
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 ¶
DeriveWasmRelayStreamSsrcs derives all 9 relay-stream SSRCs in slot order.
func E2EParticipantIDVariants ¶
E2EParticipantIDVariants lists the device-qualified LID variants the recv path tries as HKDF info (peer sender LIDs), deduplicated in insertion order.
func EncodeRtpHeader ¶
EncodeRtpHeader encodes the RTP header and its WhatsApp extension.
func EstimateSrtpRtpWireBytes ¶
EstimateSrtpRtpWireBytes estimates the on-wire SRTP size (header + opus + tag).
func FormatE2ESrtpParticipantID ¶
FormatE2ESrtpParticipantID formats the device-qualified LID for E2E-SRTP HKDF info.
func IsOpusDtxPayload ¶
IsOpusDtxPayload reports DTX / comfort-noise frames (RFC 0x10, mlow 0x90, warmup).
func IsOpusMlowSpeechPayload ¶
IsOpusMlowSpeechPayload reports mlow speech frames (20ms 0x48..0x4f or 60ms 0x50..0x57).
func IsOpusPrimingPayload ¶
IsOpusPrimingPayload reports whether the payload equals a priming frame.
func IsRtcpPacket ¶
IsRtcpPacket reports whether data is an RTCP packet (vs a WhatsApp RTP packet).
func IsRtpVersion2 ¶
IsRtpVersion2 reports a version-2 RTP packet.
func IsWhatsappOpusRtpPayload ¶
IsWhatsappOpusRtpPayload reports whether the payload type is WhatsApp Opus.
func PackageH264NALU ¶
PackageH264NALU splits one NAL unit into RTP payloads: a single payload when it fits the MTU budget, else FU-A fragments.
func PackageH264STAPA ¶
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 ¶
ParseRtcpSenderSsrc returns the sender SSRC (bytes 4-7); ok=false if malformed.
func ParseSenderReportTiming ¶
ParseSenderReportTiming extracts the first SR sender SSRC and NTP timestamp from a compound RTCP packet.
func RtcpPayloadType ¶
RtcpPayloadType returns the RTCP payload type; ok=false if not an RTCP packet.
func RtcpRequestsKeyframe ¶
RtcpRequestsKeyframe reports whether a compound RTCP packet contains PLI/FIR feedback for localVideoSsrc.
func RtpExtensionProfileAndData ¶
RtpExtensionProfileAndData returns the extension profile and word-aligned payload.
func RtpHeaderByteLength ¶
RtpHeaderByteLength returns the full on-wire header size (12 + CSRC + ext); ok=false if malformed.
func SplitAnnexB ¶
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.
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 ¶
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 ¶
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 ¶
ParseRtpHeader parses the fixed RTP header fields (the extension word is not decoded).
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 ¶
NewRtpStream builds a sequencer for ssrc with samplesPerPacket per packet.
func (*RtpStream) NextPacket ¶
NextPacket builds the next RTP header for payload, latching the marker on the first speech frame.
func (*RtpStream) NextPreSpeechPacket ¶
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