fix(goLive): emit H264 packetization-mode=1 in answer SDP so video decodes (voice was fine)

Discord's media relay negotiates H264 forwarding from the SDP fmtp. The
hand-built answer in handleProtocolAck emitted a=rtpmap:101 H264/90000 +
RTX fmtp + rtcp-fb but NO a=fmtp:101 ...;packetization-mode=1;profile-level-id=42e01f.

Our encoder emits baseline slices up to 8KB (>RTP MTU), so the packetizer
fragments them into FU-A units (RFC 6184). Without packetization-mode=1 the
relay drops every FU-A slice while passing SPS/PPS (small single NALs) and
Opus audio (no fragmentation) — result: black/broken video, working voice.

Matches @dank074's original fmtp and the native offer (which already had it).
This commit is contained in:
asepharyana
2026-08-12 23:52:55 +07:00
parent d3cb5f6756
commit db01117afa
@@ -258,6 +258,19 @@ a=ice-lite
`a=rtpmap:${el.payload_type} ${el.name}/90000`,
`a=rtpmap:${el.rtx_payload_type} rtx/90000`,
`a=fmtp:${el.rtx_payload_type} apt=${el.payload_type}`,
// CRITICAL: H264 MUST advertise packetization-mode=1. The encoder
// emits baseline slices up to 8KB (>RTP MTU), so the packetizer
// fragments them into FU-A units (RFC 6184). Discord's receiver only
// reassembles FU-A when packetization-mode=1 is negotiated — without
// it the slices (type 28) are DROPPED while SPS/PPS (small single
// NALs) and Opus audio (no fragmentation) still arrive → black video
// with working audio. profile-level-id=42e01f (constrained baseline
// 3.1) matches the -profile:v baseline encoder + SPS VUI rewriter.
...(el.name === "H264"
? [
`a=fmtp:${el.payload_type} level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f`,
]
: []),
`a=rtcp-fb:${el.payload_type} ccm fir`,
`a=rtcp-fb:${el.payload_type} nack`,
`a=rtcp-fb:${el.payload_type} nack pli`,