rtp.js
Version:
RTP stack for Node.js and browser written in TypeScript
242 lines (241 loc) • 9.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const XrPacket_1 = require("../../../packets/RTCP/XrPacket");
const RtcpPacket_1 = require("../../../packets/RTCP/RtcpPacket");
const ExtendedReport_1 = require("../../../packets/RTCP/extendedReports/ExtendedReport");
const LrleExtendedReport_1 = require("../../../packets/RTCP/extendedReports/LrleExtendedReport");
const DlrrExtendedReport_1 = require("../../../packets/RTCP/extendedReports/DlrrExtendedReport");
const chunks_1 = require("../../../packets/RTCP/extendedReports/chunks");
const helpers_1 = require("../../../utils/helpers");
const runLengthZerosChunk = 0b0010101010101010;
const runLengthOnesChunk = 0b0110101010101010;
const bitVectorChunk = 0b1110101010101010;
const terminatingNullChunk = 0b0000000000000000;
const report1Dump = {
byteLength: 20,
reportType: ExtendedReport_1.ExtendedReportType.LRLE,
thinning: 9,
ssrc: 0x03932db4,
beginSeq: 0x11,
endSeq: 0x22,
chunks: [runLengthZerosChunk, runLengthOnesChunk, bitVectorChunk],
};
const report2Dump = {
byteLength: 28,
reportType: ExtendedReport_1.ExtendedReportType.DLRR,
subReports: [
{ ssrc: 0x11121314, lrr: 0x00110011, dlrr: 0x11001100 },
{ ssrc: 0x21222324, lrr: 0x00220022, dlrr: 0x22002200 },
],
};
const packetDump = {
byteLength: 60,
padding: 4,
packetType: RtcpPacket_1.RtcpPacketType.XR,
count: 0, // No count field in XR packets.
ssrc: 0x5d931534,
reports: [report1Dump, report2Dump],
};
describe('parse RTCP XR packet', () => {
const array = new Uint8Array([
0xa0,
0xcf,
0x00,
0x0e, // Padding, Type: 207 (XR), Length: 14
0x5d,
0x93,
0x15,
0x34, // Sender SSRC: 0x5d931534
// Extended Report LRLE
0x01,
0x09,
0x00,
0x04, // BT: 1 (LRLE), T: 9, Block Length: 4
0x03,
0x93,
0x2d,
0xb4, // SSRC of source: 0x03932db4
0x00,
0x11,
0x00,
0x22, // Begin Seq: 0x11, End Seq: 0x22
0b00101010,
0b10101010, // Run Lengh Chunk (zeros)
0b01101010,
0b10101010, // Run Lengh Chunk (ones)
0b11101010,
0b10101010, // Bit Vector Chunk
0b00000000,
0b00000000, // Terminating Null Chunk
// Extended Report DLRR
0x05,
0x00,
0x00,
0x06, // BT: 5 (DLRR), Block Length: 6
0x11,
0x12,
0x13,
0x14, // SSRC 1
0x00,
0x11,
0x00,
0x11, // LRR 1
0x11,
0x00,
0x11,
0x00, // DLRR 1
0x21,
0x22,
0x23,
0x24, // SSRC 2
0x00,
0x22,
0x00,
0x22, // LRR 2
0x22,
0x00,
0x22,
0x00, // DLRR 2
0x00,
0x00,
0x00,
0x04, // Padding (4 bytes)
]);
const view = new DataView(array.buffer, array.byteOffset, array.byteLength);
test('buffer view is RTCP', () => {
expect((0, RtcpPacket_1.isRtcp)(view)).toBe(true);
});
test('packet processing succeeds', () => {
const packet = new XrPacket_1.XrPacket(view);
expect(packet.needsSerialization()).toBe(false);
expect(packet.getByteLength()).toBe(60);
expect(packet.getPacketType()).toBe(RtcpPacket_1.RtcpPacketType.XR);
// No count field in XR packetd, so this must be 0.
expect(packet.getCount()).toBe(0);
expect(packet.getPadding()).toBe(4);
expect(packet.getSsrc()).toBe(0x5d931534);
expect(packet.getReports().length).toBe(2);
expect(packet.dump()).toEqual(packetDump);
expect((0, helpers_1.areDataViewsEqual)(packet.getView(), view)).toBe(true);
const report1 = packet.getReports()[0];
expect(report1.needsSerialization()).toBe(false);
expect(report1.getByteLength()).toBe(20);
expect(report1.getReportType()).toBe(ExtendedReport_1.ExtendedReportType.LRLE);
expect(report1.getThinning()).toBe(9);
expect(report1.getSsrc()).toBe(0x03932db4);
expect(report1.getBeginSeq()).toBe(0x11);
expect(report1.getEndSeq()).toBe(0x22);
expect(report1.getChunks()).toEqual([
runLengthZerosChunk,
runLengthOnesChunk,
bitVectorChunk,
]);
expect(report1.dump()).toEqual(report1Dump);
const report2 = packet.getReports()[1];
expect(report2.needsSerialization()).toBe(false);
expect(report2.getByteLength()).toBe(28);
expect(report2.getReportType()).toBe(ExtendedReport_1.ExtendedReportType.DLRR);
expect(report2.getSubReports()).toEqual([
{ ssrc: 0x11121314, lrr: 0x00110011, dlrr: 0x11001100 },
{ ssrc: 0x21222324, lrr: 0x00220022, dlrr: 0x22002200 },
]);
expect(report2.dump()).toEqual(report2Dump);
});
});
describe('create RTCP XR packet', () => {
test('creating a XR packet succeeds', () => {
const packet = new XrPacket_1.XrPacket();
expect((0, RtcpPacket_1.isRtcp)(packet.getView())).toBe(true);
expect(packet.needsSerialization()).toBe(false);
// Byte length must be 8 (fixed header).
expect(packet.getByteLength()).toBe(8);
expect(packet.getPacketType()).toBe(RtcpPacket_1.RtcpPacketType.XR);
// No count in RTCP XR packet.
expect(packet.getCount()).toBe(0);
expect(packet.getPadding()).toBe(0);
expect(packet.getSsrc()).toBe(0);
expect(packet.getReports()).toEqual([]);
expect(packet.needsSerialization()).toBe(false);
packet.setSsrc(0x5d931534);
expect(packet.needsSerialization()).toBe(false);
const report1 = new LrleExtendedReport_1.LrleExtendedReport();
expect(report1.needsSerialization()).toBe(false);
expect(report1.getByteLength()).toBe(12);
expect(report1.getReportType()).toBe(ExtendedReport_1.ExtendedReportType.LRLE);
expect(report1.getThinning()).toBe(0);
expect(report1.getSsrc()).toBe(0);
expect(report1.getBeginSeq()).toBe(0);
expect(report1.getEndSeq()).toBe(0);
expect(report1.getChunks()).toEqual([]);
report1.setThinning(9);
report1.setSsrc(0x03932db4);
report1.setBeginSeq(0x11);
report1.setEndSeq(0x22);
report1.addChunk(runLengthZerosChunk);
report1.addChunk(runLengthOnesChunk);
report1.addChunk(bitVectorChunk);
expect(report1.dump()).toEqual(report1Dump);
expect(report1.needsSerialization()).toBe(true);
packet.addReport(report1);
const report2 = new DlrrExtendedReport_1.DlrrExtendedReport();
expect(report2.needsSerialization()).toBe(false);
expect(report2.getByteLength()).toBe(4);
expect(report2.getReportType()).toBe(ExtendedReport_1.ExtendedReportType.DLRR);
expect(report2.getSubReports()).toEqual([]);
report2.setSubReports(report2Dump.subReports);
expect(report2.dump()).toEqual(report2Dump);
expect(report2.needsSerialization()).toBe(true);
packet.addReport(report2);
// We cannot add padding to RTCP packets so fix the dump.
expect(packet.dump()).toEqual({
...packetDump,
byteLength: 56,
padding: 0,
});
packet.serialize();
expect(packet.needsSerialization()).toBe(false);
expect(report1.needsSerialization()).toBe(false);
expect(report2.needsSerialization()).toBe(false);
// We cannot add padding to RTCP packets so fix the dump.
expect(packet.dump()).toEqual({
...packetDump,
byteLength: 56,
padding: 0,
});
const clonedPacket = packet.clone();
expect(clonedPacket.dump()).toEqual({
...packetDump,
byteLength: 56,
padding: 0,
});
expect((0, helpers_1.areDataViewsEqual)(clonedPacket.getView(), packet.getView())).toBe(true);
});
});
describe('chunks parsing and creation', () => {
test('parseExtendedReportChunk()', () => {
expect((0, chunks_1.parseExtendedReportChunk)(runLengthZerosChunk)).toEqual({
chunkType: 'run-length',
runType: 'zeros',
runLength: 0b10101010101010,
});
expect((0, chunks_1.parseExtendedReportChunk)(runLengthOnesChunk)).toEqual({
chunkType: 'run-length',
runType: 'ones',
runLength: 0b10101010101010,
});
expect((0, chunks_1.parseExtendedReportChunk)(bitVectorChunk)).toEqual({
chunkType: 'bit-vector',
bitVector: 0b110101010101010,
});
expect((0, chunks_1.parseExtendedReportChunk)(terminatingNullChunk)).toEqual({
chunkType: 'terminating-null',
});
});
test('createExtendedReportRunLengthChunk()', () => {
expect((0, chunks_1.createExtendedReportRunLengthChunk)('zeros', 0b10101010101010)).toBe(runLengthZerosChunk);
expect((0, chunks_1.createExtendedReportRunLengthChunk)('ones', 0b10101010101010)).toBe(runLengthOnesChunk);
});
test('createExtendedReportBitVectorChunk()', () => {
expect((0, chunks_1.createExtendedReportBitVectorChunk)(0b110101010101010)).toBe(bitVectorChunk);
});
});