-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add retainCodecs and retainCandidates functions #18
Merged
Merged
Changes from 1 commit
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import * as fs from 'fs'; | ||
import { AvMediaDescription, CodecInfo, Sdp } from './model'; | ||
import { filterCandidates, filterCodecs, removeCodec } from './munge'; | ||
import { parse } from './parser'; | ||
|
||
/** | ||
* Validate that the sdp offer does not use any video codecs besides h264 or opus. | ||
* | ||
* @param offer - The sdp offer string to validate. | ||
* @returns True if the offer is valid. | ||
*/ | ||
const validateOfferCodecs = (offer: Sdp): boolean => { | ||
offer.avMedia | ||
.filter((av: AvMediaDescription) => av.type === 'video') | ||
.forEach((av: AvMediaDescription) => { | ||
[...av.codecs.values()].forEach((c: CodecInfo) => { | ||
if (c.name?.toLowerCase() !== 'h264') { | ||
throw new Error('SDP contains non-h264 codec in video media description'); | ||
} | ||
}); | ||
}); | ||
offer.avMedia | ||
.filter((av: AvMediaDescription) => av.type === 'audio') | ||
.forEach((av: AvMediaDescription) => { | ||
[...av.codecs.values()].forEach((c: CodecInfo) => { | ||
if (c.name?.toLowerCase() !== 'opus') { | ||
throw new Error('SDP contains non-opus codec in audio media description'); | ||
} | ||
}); | ||
}); | ||
return true; | ||
}; | ||
|
||
describe('munging', () => { | ||
describe('removeCodec', () => { | ||
it('should remove codecs correctly when passing in an SDP', () => { | ||
expect.hasAssertions(); | ||
const offer = fs.readFileSync('./src/sdp-corpus/offer_with_extra_codecs.sdp', 'utf-8'); | ||
const parsed = parse(offer); | ||
|
||
const unwantedVideoCodecs = ['VP8', 'VP9', 'AV1', 'rtx', 'red', 'ulpfec']; | ||
const unwantedAudioCodecs = ['red', 'ISAC', 'G722', 'PCMU', 'PCMA', 'CN', 'telephone-event']; | ||
|
||
unwantedVideoCodecs.forEach((codec) => removeCodec(parsed, codec)); | ||
unwantedAudioCodecs.forEach((codec) => removeCodec(parsed, codec)); | ||
expect(validateOfferCodecs(parsed)).toBe(true); | ||
}); | ||
it('should remove codecs correctly when passing in an AvMediaDescription', () => { | ||
expect.hasAssertions(); | ||
const offer = fs.readFileSync('./src/sdp-corpus/offer_with_extra_codecs.sdp', 'utf-8'); | ||
const parsed = parse(offer); | ||
|
||
const unwantedVideoCodecs = ['VP8', 'VP9', 'AV1', 'rtx', 'red', 'ulpfec']; | ||
const unwantedAudioCodecs = ['red', 'ISAC', 'G722', 'PCMU', 'PCMA', 'CN', 'telephone-event']; | ||
|
||
parsed.avMedia.forEach((av) => { | ||
unwantedVideoCodecs.forEach((codec) => removeCodec(av, codec)); | ||
unwantedAudioCodecs.forEach((codec) => removeCodec(av, codec)); | ||
}); | ||
expect(validateOfferCodecs(parsed)).toBe(true); | ||
}); | ||
}); | ||
describe('filterCodecs', () => { | ||
it('should filter codecs correctly when passing in an SDP', () => { | ||
expect.hasAssertions(); | ||
const offer = fs.readFileSync('./src/sdp-corpus/offer_with_extra_codecs.sdp', 'utf-8'); | ||
const parsed = parse(offer); | ||
|
||
filterCodecs(parsed, ['h264', 'opus']); | ||
expect(validateOfferCodecs(parsed)).toBe(true); | ||
}); | ||
it('should filter codecs correctly when passing in an AvMediaDescription', () => { | ||
expect.hasAssertions(); | ||
const offer = fs.readFileSync('./src/sdp-corpus/offer_with_extra_codecs.sdp', 'utf-8'); | ||
const parsed = parse(offer); | ||
|
||
parsed.avMedia.forEach((av) => { | ||
filterCodecs(av, ['h264', 'opus']); | ||
}); | ||
expect(validateOfferCodecs(parsed)).toBe(true); | ||
}); | ||
}); | ||
|
||
describe('filterCandidates', () => { | ||
it('should filter candidates correctly when passing in an SDP', () => { | ||
expect.hasAssertions(); | ||
const offer = fs.readFileSync('./src/sdp-corpus/answer_with_extra_candidates.sdp', 'utf-8'); | ||
const parsed = parse(offer); | ||
|
||
// should return true when some candidates have been filtered out | ||
expect(filterCandidates(parsed, ['udp', 'tcp'])).toBeTruthy(); | ||
parsed.media.forEach((mline) => { | ||
expect(mline.iceInfo.candidates).toHaveLength(4); | ||
expect( | ||
mline.iceInfo.candidates.every((candidate) => | ||
['udp', 'tcp'].includes(candidate.transport.toLowerCase()) | ||
) | ||
).toBeTruthy(); | ||
}); | ||
// should return false when no candidates have been filtered out | ||
expect(filterCandidates(parsed, ['udp', 'tcp'])).toBeFalsy(); | ||
}); | ||
it('should filter candidates correctly when passing in an AvMediaDescription', () => { | ||
expect.hasAssertions(); | ||
const offer = fs.readFileSync('./src/sdp-corpus/answer_with_extra_candidates.sdp', 'utf-8'); | ||
const parsed = parse(offer); | ||
|
||
parsed.media.forEach((media) => { | ||
// should return true when some candidates have been filtered out | ||
expect(filterCandidates(media, ['udp', 'tcp'])).toBeTruthy(); | ||
expect(media.iceInfo.candidates).toHaveLength(4); | ||
expect( | ||
media.iceInfo.candidates.every((candidate) => | ||
['udp', 'tcp'].includes(candidate.transport.toLowerCase()) | ||
) | ||
).toBeTruthy(); | ||
// should return false when no candidates have been filtered out | ||
expect(filterCandidates(media, ['udp', 'tcp'])).toBeFalsy(); | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
v=0 | ||
o=homer 0 0 IN IP4 10.224.203.38 | ||
s=- | ||
i=linus;homer:focal-3143;mf:3653 | ||
c=IN IP4 10.224.203.38 | ||
b=TIAS:1021256000 | ||
t=0 0 | ||
a=group:BUNDLE 0 1 | ||
a=ice-lite | ||
m=video 5004 RTP/AVP 102 103 | ||
c=IN IP4 10.224.203.38 | ||
b=TIAS:1000000000 | ||
a=content:main | ||
a=sendrecv | ||
a=rtpmap:102 H264/90000 | ||
a=fmtp:102 profile-level-id=420034;packetization-mode=1;max-mbps=2073600;max-fs=36864;max-fps=3000;max-br=1000000;max-dpb=69120;level-asymmetry-allowed=1 | ||
a=rtpmap:103 rtx/90000 | ||
a=fmtp:103 apt=102 | ||
a=rtcp-fb:* goog-remb | ||
a=rtcp-fb:* ccm fir | ||
a=rtcp-fb:* nack | ||
a=rtcp-fb:* nack pli | ||
a=extmap:2/sendrecv http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time | ||
a=rtcp-mux | ||
a=mid:0 | ||
a=jmp:v1 | ||
a=jmp-source:0 | ||
a=jmp-stream-id-mode:SSRC | ||
a=setup:passive | ||
a=fingerprint:sha-256 2B:C0:C2:C8:9D:B0:D3:B1:B6:FC:D2:98:23:40:A4:14:A3:79:99:E1:AA:AD:4C:75:F3:07:F8:13:AB:A5:3F:1F | ||
a=label:0 | ||
a=ice-ufrag:CQkMoaMl | ||
a=ice-pwd:XuRyavxtbUskqv61aunHNusXpaHjll88 | ||
a=candidate:0 1 UDP 2130706431 10.224.203.38 5004 typ host | ||
a=candidate:1 1 UDP 2130706175 10.224.203.38 33434 typ host | ||
a=candidate:2 1 TCP 1962934271 10.224.203.38 5004 typ host tcptype passive | ||
a=candidate:3 1 TCP 1962934015 10.224.203.38 33434 typ host tcptype passive | ||
a=candidate:4 1 xTLS 1795162111 10.224.203.38 443 typ host tcptype passive fingerprint sha-1;C3:C7:01:E9:C0:5D:74:BA:E8:3A:A4:D4:95:F2:75:3A:84:B0:F3:4B | ||
a=rtcp:5005 IN IP4 10.224.203.38 | ||
m=audio 5004 RTP/AVP 111 | ||
c=IN IP4 10.224.203.38 | ||
b=TIAS:1000000 | ||
a=content:main | ||
a=sendrecv | ||
a=rtpmap:111 opus/48000/2 | ||
a=fmtp:111 maxplaybackrate=48000;maxaveragebitrate=64000;stereo=1;sprop-stereo=1;useinbandfec=1 | ||
a=extmap:14/sendrecv urn:ietf:params:rtp-hdrext:ssrc-audio-level | ||
a=extmap:2/sendrecv http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time | ||
a=rtcp-mux | ||
a=mid:1 | ||
a=jmp:v1 | ||
a=jmp-source:0 | ||
a=jmp-stream-id-mode:SSRC | ||
a=setup:passive | ||
a=fingerprint:sha-256 2B:C0:C2:C8:9D:B0:D3:B1:B6:FC:D2:98:23:40:A4:14:A3:79:99:E1:AA:AD:4C:75:F3:07:F8:13:AB:A5:3F:1F | ||
a=label:1 | ||
a=ice-ufrag:TSd3jAfz | ||
a=ice-pwd:IgtEWo1oeuGbnYsnp85PeOETLfXZFrj8 | ||
a=candidate:0 1 UDP 2130706431 10.224.203.38 5004 typ host | ||
a=candidate:1 1 UDP 2130706175 10.224.203.38 33434 typ host | ||
a=candidate:2 1 TCP 1962934271 10.224.203.38 5004 typ host tcptype passive | ||
a=candidate:3 1 TCP 1962934015 10.224.203.38 33434 typ host tcptype passive | ||
a=candidate:4 1 xTLS 1795162111 10.224.203.38 443 typ host tcptype passive fingerprint sha-1;C3:C7:01:E9:C0:5D:74:BA:E8:3A:A4:D4:95:F2:75:3A:84:B0:F3:4B | ||
a=rtcp:5005 IN IP4 10.224.203.38 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering if we can name this something better...I feel like there's ambiguity around if the passed list are the ones being kept or the ones being removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
retainCodecs
maybeThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I can also rename
filterCandidates
toretainCandidates
.