Skip to content

Commit

Permalink
fix: make the fmtp params could be munged in firefox (#12)
Browse files Browse the repository at this point in the history
* fix: make the fmtp params could be munged in firefox

* fix: change the params type in FmtpLine and fmtParams type in CodecInfo as map

Co-authored-by: Brown Zhang <weizha2@example.com>
  • Loading branch information
x-epoch and Brown Zhang committed Dec 13, 2022
1 parent 7068d37 commit 6636f37
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 15 deletions.
7 changes: 4 additions & 3 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"ndarray",
"Onnx",
"onnxruntime",
"packetization",
"prettierignore",
"raddr",
"remb",
Expand All @@ -52,14 +53,14 @@
"rtcpfb",
"rtpmap",
"sandboxed",
"SAVPF",
"sdp",
"sdps",
"SSDK",
"ssrcs",
"TIAS",
"tfjs",
"TIAS",
"toffset",
"SAVPF",
"SSDK",
"trackingid",
"transcoding",
"transpiled",
Expand Down
70 changes: 70 additions & 0 deletions src/lines/fmtp-line.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { parseFmtpParams } from './fmtp-line';

describe('parseFmtpParams', () => {
it('normal case', async () => {
expect.hasAssertions();
const expectedValue = {
'level-asymmetry-allowed': '1',
'max-br': '1000000',
'max-dpb': '63600',
'packetization-mode': '1',
'profile-level-id': '420034',
};
let fmtpParams = parseFmtpParams(
'level-asymmetry-allowed=1;max-br=1000000;max-dpb=63600;packetization-mode=1;profile-level-id=420034'
);
expect(Object.fromEntries(fmtpParams)).toStrictEqual(expectedValue);
fmtpParams = parseFmtpParams(
'a=fmtp:97 level-asymmetry-allowed=1;max-br=1000000;max-dpb=63600;packetization-mode=1;profile-level-id=420034' // real Safari case.
);
expect(Object.fromEntries(fmtpParams)).toStrictEqual(expectedValue);
});
it('exceptional case', async () => {
expect.hasAssertions();
expect(() => {
parseFmtpParams(
'level-asymmetry-allowed=1;max-br=1000000max-dpb=63600;packetization-mode=1;profile-level-id=420034' // only lack semicolon
);
}).toThrow(Error);
expect(() => {
parseFmtpParams(
'level-asymmetry-allowed=1;max-br=max-dpb=63600;packetization-mode=1;profile-level-id=420034' // lack semicolon and value
);
}).toThrow(Error);
expect(() => {
parseFmtpParams(
'level-asymmetry-allowed=1;max-br;max-dpb=63600;packetization-mode=1;profile-level-id=420034' // lack semicolon, value and equals sign
);
}).toThrow(Error);
expect(() => {
parseFmtpParams(
'level-asymmetry-allowed=1;max-br=1000000;;max-dpb=63600;packetization-mode=1;profile-level-id=420034' // lack semicolon, value, equals sign and key
);
}).toThrow(Error);
expect(() => {
parseFmtpParams(
'level-asymmetry-allowed=1;max-br=;max-dpb=63600;packetization-mode=1;profile-level-id=420034' // only lack value
);
}).toThrow(Error);
expect(() => {
parseFmtpParams(
'level-asymmetry-allowed=1;max-br;max-dpb=63600;packetization-mode=1;profile-level-id=420034' // lack value and equals sign
);
}).toThrow(Error);
expect(() => {
parseFmtpParams(
'level-asymmetry-allowed=1;=1000000;max-dpb=63600;packetization-mode=1;profile-level-id=420034' // only lack key
);
}).toThrow(Error);
expect(() => {
parseFmtpParams(
'level-asymmetry-allowed=1;=;max-dpb=63600;packetization-mode=1;profile-level-id=420034' // lack key and value
);
}).toThrow(Error);
expect(() => {
parseFmtpParams(
'level-asymmetry-allowed=1;=max-dpb=63600;packetization-mode=1;profile-level-id=420034' // lack key, value and semicolon
);
}).toThrow(Error);
});
});
46 changes: 42 additions & 4 deletions src/lines/fmtp-line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,36 @@
import { NUM, REST } from '../regex-helpers';
import { Line } from './line';

/**
* Parse the fmtpParams because SDP has no such util function for that.
*
* @param fmtpParams - like `key1=val1;key2=val2;key3=val3".
* @returns A JS key-value object.
*/
export function parseFmtpParams(fmtpParams: string) {
// compatible with Safari, since its `fmtpParams` here contains a prefix as `a=fmtp:{payloadType} `, and separated by space.
// eslint-disable-next-line no-param-reassign
fmtpParams = fmtpParams.replace(/^a=fmtp:\d+\x20/, '');

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)) {
fmtpObj.set(fmtpParams, undefined);
return fmtpObj;
}

fmtpParams.split(';').forEach((param) => {
const paramArr = param && param.split('=');
if (paramArr.length !== 2 || !paramArr[0] || !paramArr[1]) {
throw new Error(`Fmtp params is invalid with ${fmtpParams}`);
}
// eslint-disable-next-line prefer-destructuring
fmtpObj.set(paramArr[0], paramArr[1]);
});
return fmtpObj;
}

/**
* Definition of a fmtp attribute line as defined in https://datatracker.ietf.org/doc/html/rfc4566#section-6.
*
Expand All @@ -26,7 +56,7 @@ import { Line } from './line';
export class FmtpLine extends Line {
payloadType: number;

params: string;
params: Map<string, string | undefined>;

private static regex = new RegExp(`^fmtp:(${NUM}) (${REST})`);

Expand All @@ -36,7 +66,7 @@ export class FmtpLine extends Line {
* @param payloadType - The payload type.
* @param params - The fmtp parameters.
*/
constructor(payloadType: number, params: string) {
constructor(payloadType: number, params: Map<string, string | undefined>) {
super();
this.payloadType = payloadType;
this.params = params;
Expand All @@ -56,13 +86,21 @@ export class FmtpLine extends Line {
const payloadType = parseInt(tokens[1], 10);
const params = tokens[2];

return new FmtpLine(payloadType, params);
return new FmtpLine(payloadType, parseFmtpParams(params));
}

/**
* @inheritdoc
*/
toSdpLine(): string {
return `a=fmtp:${this.payloadType} ${this.params}`;
const fmtParams = Array.from(this.params.keys())
.map((key) => {
if (this.params.get(key) !== undefined) {
return `${key}=${this.params.get(key)}`;
}
return `${key}`;
})
.join(';');
return `a=fmtp:${this.payloadType} ${fmtParams}`;
}
}
18 changes: 10 additions & 8 deletions src/model/codec-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class CodecInfo implements SdpBlock {

encodingParams?: string;

fmtParams: Array<string> = [];
fmtParams: Map<string, string | undefined> = new Map();

feedback: Array<string> = [];

Expand Down Expand Up @@ -57,9 +57,12 @@ export class CodecInfo implements SdpBlock {
return true;
}
if (line instanceof FmtpLine) {
this.fmtParams.push(line.params);
if (line.params.indexOf('apt') !== -1) {
const apt = line.params.split('=')[1];
this.fmtParams = new Map([
...Array.from(this.fmtParams.entries()),
...Array.from(line.params.entries()),
]);
if (line.params.has('apt')) {
const apt = line.params.get('apt') as string;
this.primaryCodecPt = parseInt(apt, 10);
}
return true;
Expand All @@ -85,10 +88,9 @@ export class CodecInfo implements SdpBlock {
lines.push(new RtcpFbLine(this.pt, fb));
});
// Now all Fmtp
this.fmtParams.forEach((fmt) => {
lines.push(new FmtpLine(this.pt, fmt));
});

if (this.fmtParams.size > 0) {
lines.push(new FmtpLine(this.pt, this.fmtParams));
}
return lines;
}
}

0 comments on commit 6636f37

Please sign in to comment.