Skip to content

Commit e2454d1

Browse files
committedFeb 5, 2024
Refine rtx support
Always handle header extensions from packet read from interceptor, let interceptor has consistent chance to process headers Fix rtx is not negotiated when there is multiple codecs has same mime but different profile (H264) Fix rtx stream info missed when SSRC group attr shows after base track's ssrc attr.
1 parent 987fb7a commit e2454d1

File tree

4 files changed

+79
-11
lines changed

4 files changed

+79
-11
lines changed
 

‎mediaengine.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -415,9 +415,11 @@ func (m *MediaEngine) matchRemoteCodec(remoteCodec RTPCodecParameters, typ RTPCo
415415
}
416416

417417
aptMatch := codecMatchNone
418+
var aptCodec RTPCodecParameters
418419
for _, codec := range exactMatches {
419420
if codec.PayloadType == PayloadType(payloadType) {
420421
aptMatch = codecMatchExact
422+
aptCodec = codec
421423
break
422424
}
423425
}
@@ -426,6 +428,7 @@ func (m *MediaEngine) matchRemoteCodec(remoteCodec RTPCodecParameters, typ RTPCo
426428
for _, codec := range partialMatches {
427429
if codec.PayloadType == PayloadType(payloadType) {
428430
aptMatch = codecMatchPartial
431+
aptCodec = codec
429432
break
430433
}
431434
}
@@ -435,8 +438,14 @@ func (m *MediaEngine) matchRemoteCodec(remoteCodec RTPCodecParameters, typ RTPCo
435438
return codecMatchNone, nil // not an error, we just ignore this codec we don't support
436439
}
437440

441+
// replace the apt value with the original codec's payload type
442+
toMatchCodec := remoteCodec
443+
if aptMatched, mt := codecParametersFuzzySearch(aptCodec, codecs); mt == aptMatch {
444+
toMatchCodec.SDPFmtpLine = strings.Replace(toMatchCodec.SDPFmtpLine, fmt.Sprintf("apt=%d", payloadType), fmt.Sprintf("apt=%d", aptMatched.PayloadType), 1)
445+
}
446+
438447
// if apt's media codec is partial match, then apt codec must be partial match too
439-
_, matchType := codecParametersFuzzySearch(remoteCodec, codecs)
448+
_, matchType := codecParametersFuzzySearch(toMatchCodec, codecs)
440449
if matchType == codecMatchExact && aptMatch == codecMatchPartial {
441450
matchType = codecMatchPartial
442451
}

‎mediaengine_test.go

+58-6
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,18 @@ a=rtpmap:96 VP8/90000
308308
o=- 4596489990601351948 2 IN IP4 127.0.0.1
309309
s=-
310310
t=0 0
311-
m=video 60323 UDP/TLS/RTP/SAVPF 94 96 97
311+
m=video 60323 UDP/TLS/RTP/SAVPF 94 95 106 107 108 109 96 97
312312
a=rtpmap:94 VP8/90000
313+
a=rtpmap:95 rtx/90000
314+
a=fmtp:95 apt=94
315+
a=rtpmap:106 H264/90000
316+
a=fmtp:106 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
317+
a=rtpmap:107 rtx/90000
318+
a=fmtp:107 apt=106
319+
a=rtpmap:108 H264/90000
320+
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
321+
a=rtpmap:109 rtx/90000
322+
a=fmtp:109 apt=108
313323
a=rtpmap:96 VP9/90000
314324
a=fmtp:96 profile-id=2
315325
a=rtpmap:97 rtx/90000
@@ -318,22 +328,64 @@ a=fmtp:97 apt=96
318328
m := MediaEngine{}
319329
assert.NoError(t, m.RegisterCodec(RTPCodecParameters{
320330
RTPCodecCapability: RTPCodecCapability{MimeTypeVP8, 90000, 0, "", nil},
321-
PayloadType: 94,
322-
}, RTPCodecTypeVideo))
323-
assert.NoError(t, m.RegisterCodec(RTPCodecParameters{
324-
RTPCodecCapability: RTPCodecCapability{MimeTypeVP9, 90000, 0, "profile-id=2", nil},
325331
PayloadType: 96,
326332
}, RTPCodecTypeVideo))
327333
assert.NoError(t, m.RegisterCodec(RTPCodecParameters{
328334
RTPCodecCapability: RTPCodecCapability{"video/rtx", 90000, 0, "apt=96", nil},
329335
PayloadType: 97,
330336
}, RTPCodecTypeVideo))
337+
assert.NoError(t, m.RegisterCodec(RTPCodecParameters{
338+
RTPCodecCapability: RTPCodecCapability{MimeTypeH264, 90000, 0, "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f", nil},
339+
PayloadType: 102,
340+
}, RTPCodecTypeVideo))
341+
assert.NoError(t, m.RegisterCodec(RTPCodecParameters{
342+
RTPCodecCapability: RTPCodecCapability{"video/rtx", 90000, 0, "apt=102", nil},
343+
PayloadType: 103,
344+
}, RTPCodecTypeVideo))
345+
assert.NoError(t, m.RegisterCodec(RTPCodecParameters{
346+
RTPCodecCapability: RTPCodecCapability{MimeTypeH264, 90000, 0, "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f", nil},
347+
PayloadType: 104,
348+
}, RTPCodecTypeVideo))
349+
assert.NoError(t, m.RegisterCodec(RTPCodecParameters{
350+
RTPCodecCapability: RTPCodecCapability{"video/rtx", 90000, 0, "apt=104", nil},
351+
PayloadType: 105,
352+
}, RTPCodecTypeVideo))
353+
assert.NoError(t, m.RegisterCodec(RTPCodecParameters{
354+
RTPCodecCapability: RTPCodecCapability{MimeTypeVP9, 90000, 0, "profile-id=2", nil},
355+
PayloadType: 98,
356+
}, RTPCodecTypeVideo))
357+
assert.NoError(t, m.RegisterCodec(RTPCodecParameters{
358+
RTPCodecCapability: RTPCodecCapability{"video/rtx", 90000, 0, "apt=98", nil},
359+
PayloadType: 99,
360+
}, RTPCodecTypeVideo))
331361
assert.NoError(t, m.updateFromRemoteDescription(mustParse(profileLevels)))
332362

333363
assert.True(t, m.negotiatedVideo)
334364

335-
_, _, err := m.getCodecByPayload(97)
365+
vp9Codec, _, err := m.getCodecByPayload(96)
366+
assert.NoError(t, err)
367+
assert.Equal(t, vp9Codec.MimeType, MimeTypeVP9)
368+
vp9RTX, _, err := m.getCodecByPayload(97)
369+
assert.NoError(t, err)
370+
assert.Equal(t, vp9RTX.MimeType, "video/rtx")
371+
372+
h264P1Codec, _, err := m.getCodecByPayload(106)
373+
assert.NoError(t, err)
374+
assert.Equal(t, h264P1Codec.MimeType, MimeTypeH264)
375+
assert.Equal(t, h264P1Codec.SDPFmtpLine, "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f")
376+
h264P1RTX, _, err := m.getCodecByPayload(107)
377+
assert.NoError(t, err)
378+
assert.Equal(t, h264P1RTX.MimeType, "video/rtx")
379+
assert.Equal(t, h264P1RTX.SDPFmtpLine, "apt=106")
380+
381+
h264P0Codec, _, err := m.getCodecByPayload(108)
382+
assert.NoError(t, err)
383+
assert.Equal(t, h264P0Codec.MimeType, MimeTypeH264)
384+
assert.Equal(t, h264P0Codec.SDPFmtpLine, "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f")
385+
h264P0RTX, _, err := m.getCodecByPayload(109)
336386
assert.NoError(t, err)
387+
assert.Equal(t, h264P0RTX.MimeType, "video/rtx")
388+
assert.Equal(t, h264P0RTX.SDPFmtpLine, "apt=108")
337389
})
338390

339391
t.Run("Matches when rtx apt for partial match codec", func(t *testing.T) {

‎peerconnection.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -1576,12 +1576,11 @@ func (pc *PeerConnection) handleIncomingSSRC(rtpStream io.Reader, ssrc SSRC) err
15761576
return err
15771577
}
15781578

1579-
var mid, rid, rsid string
1580-
payloadType, paddingOnly, err := handleUnknownRTPPacket(b[:i], uint8(midExtensionID), uint8(streamIDExtensionID), uint8(repairStreamIDExtensionID), &mid, &rid, &rsid)
1581-
if err != nil {
1582-
return err
1579+
if i < 4 {
1580+
return errRTPTooShort
15831581
}
15841582

1583+
payloadType := PayloadType(b[1] & 0x7f)
15851584
params, err := pc.api.mediaEngine.getRTPParametersByPayloadType(payloadType)
15861585
if err != nil {
15871586
return err
@@ -1593,6 +1592,8 @@ func (pc *PeerConnection) handleIncomingSSRC(rtpStream io.Reader, ssrc SSRC) err
15931592
return err
15941593
}
15951594

1595+
var mid, rid, rsid string
1596+
var paddingOnly bool
15961597
for readCount := 0; readCount <= simulcastProbeCount; readCount++ {
15971598
if mid == "" || (rid == "" && rsid == "") {
15981599
// skip padding only packets for probing

‎sdp.go

+6
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,12 @@ func trackDetailsFromSDP(log logging.LeveledLogger, s *sdp.SessionDescription) (
128128
}
129129
rtxRepairFlows[rtxRepairFlow] = baseSsrc
130130
tracksInMediaSection = filterTrackWithSSRC(tracksInMediaSection, SSRC(rtxRepairFlow)) // Remove if rtx was added as track before
131+
for i := range tracksInMediaSection {
132+
if tracksInMediaSection[i].ssrcs[0] == SSRC(baseSsrc) {
133+
repairSsrc := SSRC(rtxRepairFlow)
134+
tracksInMediaSection[i].repairSsrc = &repairSsrc
135+
}
136+
}
131137
}
132138
}
133139

0 commit comments

Comments
 (0)
Please sign in to comment.