-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add support for a:ssrc and a:ssrc-group (#3)
* feat: add support for a:ssrc line * feat: add support for a:ssrc-group lines * chore: export new line types * chore: fixes from pr comments
- Loading branch information
Showing
7 changed files
with
232 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,6 +53,7 @@ | |
"sandboxed", | ||
"sdp", | ||
"sdps", | ||
"ssrcs", | ||
"TIAS", | ||
"tfjs", | ||
"toffset", | ||
|
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,40 @@ | ||
import { SsrcGroupLine } from './ssrc-group-line'; | ||
|
||
describe('ssrc group line', () => { | ||
it('should parse valid lines correctly', () => { | ||
expect.hasAssertions(); | ||
{ | ||
const line = 'ssrc-group:SIM 123 456 789'; | ||
const result = SsrcGroupLine.fromSdpLine(line); | ||
|
||
expect(result).toBeTruthy(); | ||
expect(result?.semantics).toBe('SIM'); | ||
expect(result?.ssrcs).toStrictEqual([123, 456, 789]); | ||
} | ||
{ | ||
const line = 'ssrc-group:FID 123 456'; | ||
const result = SsrcGroupLine.fromSdpLine(line); | ||
|
||
expect(result).toBeTruthy(); | ||
expect(result?.semantics).toBe('FID'); | ||
expect(result?.ssrcs).toStrictEqual([123, 456]); | ||
} | ||
}); | ||
|
||
it('should fail to parse invalid lines', () => { | ||
expect.hasAssertions(); | ||
|
||
expect(SsrcGroupLine.fromSdpLine('foo:FID 123 456')).toBeFalsy(); | ||
expect(SsrcGroupLine.fromSdpLine('ssrc-group:BAR 123 456')).toBeFalsy(); | ||
expect(SsrcGroupLine.fromSdpLine('ssrc-group:FID abc def')).toBeFalsy(); | ||
}); | ||
|
||
it('should serialize correctly', () => { | ||
expect.hasAssertions(); | ||
|
||
expect(new SsrcGroupLine('SIM', [123, 456, 789]).toSdpLine()).toBe( | ||
'a=ssrc-group:SIM 123 456 789' | ||
); | ||
expect(new SsrcGroupLine('FID', [123, 456]).toSdpLine()).toBe('a=ssrc-group:FID 123 456'); | ||
}); | ||
}); |
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,54 @@ | ||
import { NUM, SP } from '../regex-helpers'; | ||
import { Line } from './line'; | ||
|
||
type SsrcGroupSemantics = 'SIM' | 'FID' | 'FEC'; | ||
|
||
/** | ||
* Model an SSRC group line as define by https://datatracker.ietf.org/doc/html/rfc5576#section-4.2. | ||
* | ||
* @example | ||
* a=ssrc-group: FID 13579 24680 | ||
*/ | ||
export class SsrcGroupLine extends Line { | ||
semantics: SsrcGroupSemantics; | ||
|
||
ssrcs: number[]; | ||
|
||
private static regex = new RegExp(`^ssrc-group:(SIM|FID|FEC) ((?:${NUM}${SP}*)+)`); | ||
|
||
/** | ||
* Create an SsrcGroupLine from the given values. | ||
* | ||
* @param semantics - The semantics of this SSRC group. | ||
* @param ssrcs - The SSRCs in this SSRC group. | ||
*/ | ||
constructor(semantics: SsrcGroupSemantics, ssrcs: number[]) { | ||
super(); | ||
this.semantics = semantics; | ||
this.ssrcs = ssrcs; | ||
} | ||
|
||
/** | ||
* Create an SsrcGroupLine from the given string. | ||
* | ||
* @param line - The line to parse. | ||
* @returns An SsrcGroupLine instance or undefined if parsing failed. | ||
*/ | ||
static fromSdpLine(line: string): SsrcGroupLine | undefined { | ||
if (!SsrcGroupLine.regex.test(line)) { | ||
return undefined; | ||
} | ||
const tokens = line.match(SsrcGroupLine.regex) as RegExpMatchArray; | ||
const semantics = tokens[1]; | ||
const ssrcs = tokens[2].split(' ').map((ssrcStr) => parseInt(ssrcStr, 10)); | ||
|
||
return new SsrcGroupLine(semantics as SsrcGroupSemantics, ssrcs); | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
toSdpLine(): string { | ||
return `a=ssrc-group:${this.semantics} ${this.ssrcs.join(' ')}`; | ||
} | ||
} |
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,55 @@ | ||
import { SsrcLine } from './ssrc-line'; | ||
|
||
describe('ssrc line', () => { | ||
it('should parse a line with just an attribute correctly', () => { | ||
expect.hasAssertions(); | ||
const line = 'ssrc:1234567 foo'; | ||
const result = SsrcLine.fromSdpLine(line); | ||
|
||
expect(result).toBeTruthy(); | ||
expect(result?.ssrcId).toBe(1234567); | ||
expect(result?.attribute).toBe('foo'); | ||
expect(result?.attributeValue).toBeFalsy(); | ||
expect(result?.attributeData).toBeFalsy(); | ||
}); | ||
|
||
it('should parse a line with an attribute and attribute value correctly', () => { | ||
expect.hasAssertions(); | ||
const line = 'ssrc:1234567 foo:bar'; | ||
const result = SsrcLine.fromSdpLine(line); | ||
|
||
expect(result).toBeTruthy(); | ||
expect(result?.ssrcId).toBe(1234567); | ||
expect(result?.attribute).toBe('foo'); | ||
expect(result?.attributeValue).toBe('bar'); | ||
expect(result?.attributeData).toBeFalsy(); | ||
}); | ||
|
||
it('should parse a line with an attribute, attribute value, and attribute data correctly', () => { | ||
expect.hasAssertions(); | ||
const line = 'ssrc:1234567 foo:bar baz'; | ||
const result = SsrcLine.fromSdpLine(line); | ||
|
||
expect(result).toBeTruthy(); | ||
expect(result?.ssrcId).toBe(1234567); | ||
expect(result?.attribute).toBe('foo'); | ||
expect(result?.attributeValue).toBe('bar'); | ||
expect(result?.attributeData).toBe('baz'); | ||
}); | ||
|
||
it('should fail to parse invalid lines', () => { | ||
expect.hasAssertions(); | ||
|
||
expect(SsrcLine.fromSdpLine('foo:1234567 foo')).toBeFalsy(); | ||
expect(SsrcLine.fromSdpLine('ssrc:1234567 foo=bar')).toBeFalsy(); | ||
}); | ||
|
||
it('should serialize correctly', () => { | ||
expect.hasAssertions(); | ||
expect(new SsrcLine(1234567, 'foo').toSdpLine()).toBe('a=ssrc:1234567 foo'); | ||
expect(new SsrcLine(1234567, 'foo', 'bar').toSdpLine()).toBe('a=ssrc:1234567 foo:bar'); | ||
expect(new SsrcLine(1234567, 'foo', 'bar', 'baz').toSdpLine()).toBe( | ||
'a=ssrc:1234567 foo:bar baz' | ||
); | ||
}); | ||
}); |
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,77 @@ | ||
import { NUM, SDP_TOKEN, TOKEN } from '../regex-helpers'; | ||
import { Line } from './line'; | ||
|
||
/** | ||
* Model an SSRC line in SDP as defined by https://datatracker.ietf.org/doc/html/rfc5576#section-4.1. | ||
* | ||
* @example | ||
* a=ssrc:1234567 cname:foo | ||
*/ | ||
export class SsrcLine extends Line { | ||
ssrcId: number; | ||
|
||
attribute: string; | ||
|
||
attributeValue: string | undefined; | ||
|
||
attributeData: string | undefined; | ||
|
||
private static regex = new RegExp( | ||
`^ssrc:(${NUM}) (${SDP_TOKEN})(?::(${SDP_TOKEN})?(?: (${TOKEN}))?)?$` | ||
); | ||
|
||
/** | ||
* Create an SsrcLine from the given values. | ||
* | ||
* @param ssrcId - The SSRC ID. | ||
* @param attribute - The attribute specific to this SSRC. | ||
* @param attributeValue - An optional attribute value, if applicable. | ||
* @param attributeData - Optional attribute data, if applicable. | ||
*/ | ||
constructor( | ||
ssrcId: number, | ||
attribute: string, | ||
attributeValue: string | undefined = undefined, | ||
attributeData: string | undefined = undefined | ||
) { | ||
super(); | ||
this.ssrcId = ssrcId; | ||
this.attribute = attribute; | ||
this.attributeValue = attributeValue; | ||
this.attributeData = attributeData; | ||
} | ||
|
||
/** | ||
* Create an SsrcLine from the given string. | ||
* | ||
* @param line - The line to parse. | ||
* @returns An SsrcLine instance or undefined if parsing failed. | ||
*/ | ||
static fromSdpLine(line: string): SsrcLine | undefined { | ||
if (!SsrcLine.regex.test(line)) { | ||
return undefined; | ||
} | ||
const tokens = line.match(SsrcLine.regex) as RegExpMatchArray; | ||
const ssrcId = parseInt(tokens[1], 10); | ||
const attribute = tokens[2]; | ||
const attributeValue = tokens[3]; | ||
const attributeData = tokens[4]; | ||
|
||
return new SsrcLine(ssrcId, attribute, attributeValue, attributeData); | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
toSdpLine(): string { | ||
let str = `a=ssrc:${this.ssrcId} ${this.attribute}`; | ||
if (this.attributeValue) { | ||
str += `:${this.attributeValue}`; | ||
} | ||
if (this.attributeData) { | ||
str += ` ${this.attributeData}`; | ||
} | ||
|
||
return str; | ||
} | ||
} |
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