-
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: update retain helpers #21
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ | |
* limitations under the License. | ||
*/ | ||
|
||
import { CandidateLine } from './lines'; | ||
import { AvMediaDescription, CodecInfo, MediaDescription, Sdp } from './model'; | ||
|
||
/** | ||
|
@@ -69,50 +70,75 @@ export function removeCodec(sdpOrAv: Sdp | AvMediaDescription, codecName: string | |
|
||
/** | ||
* Retain specific codecs, filtering out unwanted ones from the given SDP or audio/video media | ||
* description. | ||
* description. The provided predicate should take in a single {@link codecInfo}, and only codecs | ||
* for which the predicate returns true will be retained. | ||
* | ||
* Note: Done this way because of a feature not implemented in all browsers, currently missing in | ||
* Firefox. Once that is added we can use `RTPSender.getCapabilities` and filter those to call | ||
* with `RTCRtpTransceiver.setCodecPreferences` instead of doing this manually. | ||
* Note: Done this way because of a feature that was only recently implemented in all browsers, | ||
* previously missing in Firefox. You can also use `RTPSender.getCapabilities` and filter those to | ||
* call with `RTCRtpTransceiver.setCodecPreferences` instead of doing this manually. | ||
* | ||
* @param sdpOrAv - The {@link Sdp} or {@link AvMediaDescription} from which to filter codecs. | ||
* @param allowedCodecNames - The names of the codecs that should remain in the SDP. | ||
* @param predicate - A function used to determine which codecs should be retained. | ||
* @returns A boolean that indicates if some codecs have been filtered out. | ||
*/ | ||
export function retainCodecs( | ||
sdpOrAv: Sdp | AvMediaDescription, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder, do we ever use this with an entire SDP? Retaining codecs across media types doesn't make much sense, not sure why I supported that (or if it was even me, I guess) I guess the predicate version it makes a bit more sense since then it can detect audio vs video. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a good question. I took a look at the history for this file. It seems like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah ok, yeah I think There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bbaldino Will it be logical to keep the API consistent between these functions and more flexible? Or is your vision always to retain codecs only from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's true that the APIs would differ, but I think in this situation it's accurate: the transport information is consistent across all mlines, while codecs differ between audio and video. |
||
allowedCodecNames: Array<string> | ||
): void { | ||
predicate: (codecInfo: CodecInfo) => boolean | ||
): boolean { | ||
const avMediaDescriptions = sdpOrAv instanceof Sdp ? sdpOrAv.avMedia : [sdpOrAv]; | ||
let filtered = false; | ||
|
||
avMediaDescriptions.forEach((av) => { | ||
av.codecs.forEach((codecInfo) => { | ||
if (!predicate(codecInfo)) { | ||
av.removePt(codecInfo.pt); | ||
filtered = true; | ||
} | ||
}); | ||
}); | ||
|
||
return filtered; | ||
} | ||
|
||
/** | ||
* Retain specific codecs, filtering out unwanted ones from the given SDP or audio/video media | ||
* description by codec name. | ||
* | ||
* @param sdpOrAv - The {@link Sdp} or {@link AvMediaDescription} from which to filter codecs. | ||
* @param allowedCodecNames - The names of the codecs that should remain in the SDP. | ||
* @returns A boolean that indicates if some codecs have been filtered out. | ||
*/ | ||
export function retainCodecsByCodecName( | ||
sdpOrAv: Sdp | AvMediaDescription, | ||
allowedCodecNames: Array<string> | ||
): boolean { | ||
const allowedLowerCase = allowedCodecNames.map((s) => s.toLowerCase()); | ||
|
||
avMediaDescriptions | ||
.map((av) => { | ||
return [...av.codecs.values()].map((c) => c.name as string); | ||
}) | ||
.flat() | ||
.filter((codecName) => !allowedLowerCase.includes(codecName.toLowerCase())) | ||
.forEach((unwantedCodec) => removeCodec(sdpOrAv, unwantedCodec)); | ||
return retainCodecs(sdpOrAv, (codecInfo) => | ||
allowedLowerCase.includes(codecInfo.name?.toLowerCase() as string) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How can you ensure that this function will always have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah yeah, it was like this before but I probably should be checking to see if it exists first before checking if it's in the list of allowed codec names. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bbaldino, do you remember why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Discussed offline, but I think your memory is right: it's optional because we fill in that information later. Bryce and I discussed some investigation of using an intermediary type while parsing that could then be finalized into another type which probably models required fields vs optional ones, so we can look into that. |
||
); | ||
} | ||
|
||
/** | ||
* Retain specific candidates, filtering out unwanted ones from the given SDP or media description | ||
* by transport type. | ||
* Retain specific candidates, filtering out unwanted ones from the given SDP or media description. | ||
* The provided predicate should take in a single {@link CandidateLine}, and only candidates for | ||
* which the predicate returns true will be retained. | ||
* | ||
* @param sdpOrMedia - The {@link Sdp} or {@link MediaDescription} from which to filter candidates. | ||
* @param allowedTransportTypes - The names of the transport types of the candidates that should remain in the SDP. | ||
* @param predicate - A function used to determine which candidates should be retained. | ||
* @returns A boolean that indicates if some candidates have been filtered out. | ||
*/ | ||
export function retainCandidates( | ||
sdpOrMedia: Sdp | MediaDescription, | ||
allowedTransportTypes: Array<string> | ||
predicate: (candidate: CandidateLine) => boolean | ||
) { | ||
const mediaDescriptions = sdpOrMedia instanceof Sdp ? sdpOrMedia.media : [sdpOrMedia]; | ||
let filtered = false; | ||
|
||
mediaDescriptions.forEach((media) => { | ||
// eslint-disable-next-line no-param-reassign | ||
media.iceInfo.candidates = media.iceInfo.candidates.filter((candidate) => { | ||
if (allowedTransportTypes.includes(candidate.transport.toLowerCase())) { | ||
if (predicate(candidate)) { | ||
return true; | ||
} | ||
filtered = true; | ||
|
@@ -122,3 +148,22 @@ export function retainCandidates( | |
|
||
return filtered; | ||
} | ||
|
||
/** | ||
* Retain specific candidates, filtering out unwanted ones from the given SDP or media description | ||
* by transport type. | ||
* | ||
* @param sdpOrMedia - The {@link Sdp} or {@link MediaDescription} from which to filter candidates. | ||
* @param allowedTransportTypes - The names of the transport types of the candidates that should remain in the SDP. | ||
* @returns A boolean that indicates if some candidates have been filtered out. | ||
*/ | ||
export function retainCandidatesByTransportType( | ||
sdpOrMedia: Sdp | MediaDescription, | ||
allowedTransportTypes: Array<string> | ||
) { | ||
const allowedLowerCase = allowedTransportTypes.map((s) => s.toLowerCase()); | ||
|
||
return retainCandidates(sdpOrMedia, (candidate) => | ||
allowedLowerCase.includes(candidate.transport.toLowerCase()) | ||
); | ||
} |
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.
If this predicate is the same for multiple tests, consider putting it in a describe to avoid duplicating code.
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.
It's only being used for half of the tests though. To me, it would make sense to do so if most or all of the tests use it (and in the future, if we add more cases to this describe block, that means most of the test cases will not use it).