Skip to content
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

fix: make the fmtp params could be munged in firefox #12

Merged
merged 2 commits into from
Dec 13, 2022

Conversation

x-epoch
Copy link
Contributor

@x-epoch x-epoch commented Dec 7, 2022

As this code shows, we originally pushed max-mbps & max-fs into fmtParams to make homer support the 1080P video, and it finally generated the SDP by ts-sdp as below:

a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=fmtp:102 max-mbps=244800
a=fmtp:102 max-fs=8160

Chrome CAN accept this SDP line when we set them by calling setLocalDescription API, however, Firefox do not like it . In order to achieve the same purpose in Firefox, we need to enhance the toLines() method in codec-info.ts , make it serialize things out correctly, which the final serialize string could be :

a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f;max-mbps=244800;max-fs=8160

lines.push(new FmtpLine(this.pt, fmt));
});

if (this.fmtParams.length > 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should do this at the FmtpLine level, not the CodecInfo level: it should still be possible to serialize multiple fmtp lines.

What we want is for the caller (wcme) to be able to grab the existing fmtp lines in the CodecInfo, and 'expand' one of them by adding extra params.

Copy link
Contributor Author

@x-epoch x-epoch Dec 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should do this at the FmtpLine level, not the CodecInfo level: it should still be possible to serialize multiple fmtp lines.

Since the fmtParams in CodecInfo currently is defined as Array type, so we CAN NOT prevent upper layer adding new fmtp params through the push method, and that actually the way we used to add new fmtp params in WCME as this code shows.
So what's this PR want to solve is: when there are multiple fmtp lines with the same payload type in fmtParams, just merge it as one line.

What we want is for the caller (wcme) to be able to grab the existing fmtp lines in the CodecInfo, and 'expand' one of them by adding extra params.

Yes, of course we can do this, but if we keep the fmtParams still as Array type, we still need to consider the problem that the fmtParams may be contains multiple values(lines) with same payload type, which would result in Firefox failed.

Copy link
Contributor Author

@x-epoch x-epoch Dec 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before the push method being called, there may be only 1 item in fmtParams , which could be:

['fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f']

After the push method being called like this:

ci.fmtParams.push(max-mbps=${defaultMaxVideoEncodeMbps});
ci.fmtParams.push(max-fs=${defaultMaxVideoEncodeFrameSize});

Then the value of fmtParams would contains 3 items, which could be:

['fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f', max-mbps=244800, max-fs=8160]

What this PR want to solve is, merge all items with same payload type in the fmtParams , and make it as one line, which final be:

['fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f';max-mbps=244800;max-fs=8160]

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I re-read the spec and it does say only one fmtp line is allowed per payload type, so since CodecInfo is on the scope of a payload type, it does make sense to make sure we always serialize to a single fmtp line. But this just means that, when serializing CodecInfo, instead of writing a new fmtp line for each param, we just need to use a single line for all the params?

This doesn't protect against multiple, duplicate values, though. But if we want to protect against that, FmtpLine should parse the params into an object/map, instead of a single string. CodecInfo should then hold a map of these params, instead of a list. So then the codec can add a new param just as before, but can avoid duplicate param values.

Copy link
Contributor Author

@x-epoch x-epoch Dec 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code updated.

const fmtpObj = new Map<string, string | undefined>();

// compatible with RED,such as `a=fmtp:121 0/5` in chrome and `a=fmtp:121 0-5` in firefox, which can {@link https://www.rfc-editor.org/rfc/rfc2198}
if (/^\d+([/-]\d+)+$/.test(fmtpParams)) {
Copy link
Contributor Author

@x-epoch x-epoch Dec 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we further parse the fmtp params as Map here, so we have to consider the case of RED, which the sample line likes a=fmtp:121 0/5 (and it would be a=fmtp:121 0-5 in Firefox by testing).
In such case, since it is lack of equals sign(= ), we need to set its default value as undefined when put it into Map. When compose the fmtp line in toSdpLine method from Map, we should ignore the value and only need to output the Map key.

Copy link
Collaborator

@bbaldino bbaldino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool, looks good. one small comment.

* @param fmtpParams - like `key1=val1;key2=val2;key3=val3".
* @returns A JS key-value object.
*/
export function parseFmtpParams(fmtpParams: string) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be exported? At this point I think it's just an internal helper function, right?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you pass a map in down below, I think we still don't need to export this. This will be used for the 'internal' parsing (where it takes the sdp string and parses it). The map constructor will be used when someone wants to craft a line on their own, so they'll just add the params specifically to the map.

Copy link
Contributor Author

@x-epoch x-epoch Dec 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this function is also needed in WCME, so just make it be exported and could be shared with codec-utils.ts in WCME which the code can refer to here

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see, I didn't think there was a need for parsing those after this, but I didn't realize RTCRtpCodecParameters still holds them in that format.

@bbaldino bbaldino merged commit 6636f37 into webex:main Dec 13, 2022
arun3528 pushed a commit that referenced this pull request Dec 13, 2022
## [1.3.1](v1.3.0...v1.3.1) (2022-12-13)

### Bug Fixes

* make the fmtp params could be munged in firefox ([#12](#12)) ([6636f37](6636f37))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants