rtp.js
Version:
RTP stack for Node.js and browser written in TypeScript
317 lines (316 loc) • 12.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const SenderReportPacket_1 = require("../../../packets/RTCP/SenderReportPacket");
const ReceiverReportPacket_1 = require("../../../packets/RTCP/ReceiverReportPacket");
const RtcpPacket_1 = require("../../../packets/RTCP/RtcpPacket");
const helpers_1 = require("../../../utils/helpers");
const receptionReportDump1 = {
byteLength: 24,
ssrc: 0x01932db4,
fractionLost: 80,
totalLost: 216,
highestSeq: 342342,
jitter: 0,
lsr: 8234,
dlsr: 5,
};
describe('parse RTCP Sender Report packet', () => {
// Sender info.
const ssrc = 0x5d931534;
const ntpSeconds = 3711615412;
const ntpFraction = 1985245553;
const rtpTimestamp = 577280;
const packetCount = 3608;
const octetCount = 577280;
const array = new Uint8Array([
0x81,
0xc8,
0x00,
0x0c, // Type: 200 (Sender Report), Count: 1, Length: 12
0x5d,
0x93,
0x15,
0x34, // SSRC: 0x5d931534
0xdd,
0x3a,
0xc1,
0xb4, // NTP Sec: 3711615412
0x76,
0x54,
0x71,
0x71, // NTP Frac: 1985245553
0x00,
0x08,
0xcf,
0x00, // RTP timestamp: 577280
0x00,
0x00,
0x0e,
0x18, // Packet count: 3608
0x00,
0x08,
0xcf,
0x00, // Octet count: 577280
// Reception Report
0x01,
0x93,
0x2d,
0xb4, // SSRC: 0x01932db4
0x50,
0x00,
0x00,
0xd8, // Fraction lost: 0, Total lost: 1
0x00,
0x05,
0x39,
0x46, // Extended highest sequence number: 0
0x00,
0x00,
0x00,
0x00, // Jitter: 0
0x00,
0x00,
0x20,
0x2a, // Last SR: 8234
0x00,
0x00,
0x00,
0x05, // DLSR: 5
]);
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 SenderReportPacket_1.SenderReportPacket(view);
expect(packet.needsSerialization()).toBe(false);
// Byte length must be 28 (fixed header) + 24 (1 report) = 52.
expect(packet.getByteLength()).toBe(52);
expect(packet.getPacketType()).toBe(RtcpPacket_1.RtcpPacketType.SR);
expect(packet.getCount()).toBe(1);
expect(packet.getPadding()).toBe(0);
expect(packet.getSsrc()).toBe(ssrc);
expect(packet.getNtpSeconds()).toBe(ntpSeconds);
expect(packet.getNtpFraction()).toBe(ntpFraction);
expect(packet.getRtpTimestamp()).toBe(rtpTimestamp);
expect(packet.getPacketCount()).toBe(packetCount);
expect(packet.getOctetCount()).toBe(octetCount);
expect((0, helpers_1.areDataViewsEqual)(packet.getView(), view)).toBe(true);
const report1 = packet.getReports()[0];
expect(report1.dump()).toEqual(receptionReportDump1);
// Also test the same after serializing.
packet.serialize();
expect(packet.needsSerialization()).toBe(false);
// Byte length must be 28 (fixed header) + 24 (1 report) = 52.
expect(packet.getByteLength()).toBe(52);
expect(packet.getPacketType()).toBe(RtcpPacket_1.RtcpPacketType.SR);
expect(packet.getCount()).toBe(1);
expect(packet.getPadding()).toBe(0);
expect(packet.getSsrc()).toBe(ssrc);
expect(packet.getNtpSeconds()).toBe(ntpSeconds);
expect(packet.getNtpFraction()).toBe(ntpFraction);
expect(packet.getRtpTimestamp()).toBe(rtpTimestamp);
expect(packet.getPacketCount()).toBe(packetCount);
expect(packet.getOctetCount()).toBe(octetCount);
expect((0, helpers_1.areDataViewsEqual)(packet.getView(), view)).toBe(true);
const report1B = packet.getReports()[0];
expect(report1B.dump()).toEqual(receptionReportDump1);
// If a change is done in a Reception Report, the Receiver Report packet must
// need serialization.
report1B.setDelaySinceLastSR(6);
expect(report1B.needsSerialization()).toBe(true);
expect(packet.needsSerialization()).toBe(true);
// And if we serialize the packet, it should unset the serialization needed
// flag.
packet.serialize();
expect(report1B.needsSerialization()).toBe(false);
expect(packet.needsSerialization()).toBe(false);
});
test('packet processing succeeds for a buffer view with padding', () => {
const array2 = new Uint8Array([
0xa0,
0xc8,
0x00,
0x07, // Padding, Type: 200, Count: 0, Length: 7
0x5d,
0x93,
0x15,
0x34, // SSRC: 0x5d931534
0xdd,
0x3a,
0xc1,
0xb4, // NTP Sec: 3711615412
0x76,
0x54,
0x71,
0x71, // NTP Frac: 1985245553
0x00,
0x08,
0xcf,
0x00, // RTP timestamp: 577280
0x00,
0x00,
0x0e,
0x18, // Packet count: 3608
0x00,
0x08,
0xcf,
0x00, // Octet count: 577280
0x00,
0x00,
0x00,
0x04, // Padding (4 bytes)
]);
const view2 = new DataView(array2.buffer, array2.byteOffset, array2.byteLength);
const packet = new SenderReportPacket_1.SenderReportPacket(view2);
expect(packet.needsSerialization()).toBe(false);
// Byte length must be 28 (fixed header) + 4 (padding) = 32.
expect(packet.getByteLength()).toBe(32);
expect(packet.getPacketType()).toBe(RtcpPacket_1.RtcpPacketType.SR);
expect(packet.getCount()).toBe(0);
expect(packet.getPadding()).toBe(4);
expect(packet.getSsrc()).toBe(ssrc);
expect(packet.getNtpSeconds()).toBe(ntpSeconds);
expect(packet.getNtpFraction()).toBe(ntpFraction);
expect(packet.getRtpTimestamp()).toBe(rtpTimestamp);
expect(packet.getPacketCount()).toBe(packetCount);
expect(packet.getOctetCount()).toBe(octetCount);
expect((0, helpers_1.areDataViewsEqual)(packet.getView(), view2)).toBe(true);
});
test('parsing a buffer view which length does not fit the indicated count throws', () => {
// Parse the first 8 bytes of buffer, indicating 1 Reception Report and
// holding no report at all.
const view3 = new DataView(array.buffer, array.byteOffset, 8);
expect(() => new SenderReportPacket_1.SenderReportPacket(view3)).toThrow(RangeError);
});
});
describe('create RTCP Sender Report packet', () => {
test('creating a Sender Report packet succeeds', () => {
const packet = new SenderReportPacket_1.SenderReportPacket();
expect((0, RtcpPacket_1.isRtcp)(packet.getView())).toBe(true);
expect(packet.needsSerialization()).toBe(false);
// Byte length must be 28 (fixed header).
expect(packet.getByteLength()).toBe(28);
expect(packet.getPacketType()).toBe(RtcpPacket_1.RtcpPacketType.SR);
expect(packet.getCount()).toBe(0);
expect(packet.getPadding()).toBe(0);
expect(packet.getSsrc()).toBe(0);
expect(packet.getNtpSeconds()).toBe(0);
expect(packet.getNtpFraction()).toBe(0);
expect(packet.getRtpTimestamp()).toBe(0);
expect(packet.getPacketCount()).toBe(0);
expect(packet.getOctetCount()).toBe(0);
expect(packet.needsSerialization()).toBe(false);
packet.setSsrc(1111);
packet.setNtpSeconds(1234);
packet.setNtpFraction(2345);
packet.setRtpTimestamp(123456789);
packet.setPacketCount(666);
packet.setOctetCount(999);
expect(packet.getSsrc()).toBe(1111);
expect(packet.getNtpSeconds()).toBe(1234);
expect(packet.getNtpFraction()).toBe(2345);
expect(packet.getRtpTimestamp()).toBe(123456789);
expect(packet.getPacketCount()).toBe(666);
expect(packet.getOctetCount()).toBe(999);
packet.padTo4Bytes();
// After padding to 4 bytes, nothing should change since the rest of the
// packet always fits into groups of 4 bytes.
expect(packet.needsSerialization()).toBe(false);
expect(packet.getByteLength()).toBe(28);
expect(packet.getPacketType()).toBe(RtcpPacket_1.RtcpPacketType.SR);
expect(packet.getCount()).toBe(0);
expect(packet.getPadding()).toBe(0);
expect(packet.getSsrc()).toBe(1111);
expect(packet.getNtpSeconds()).toBe(1234);
expect(packet.getNtpFraction()).toBe(2345);
expect(packet.getRtpTimestamp()).toBe(123456789);
expect(packet.getPacketCount()).toBe(666);
expect(packet.getOctetCount()).toBe(999);
expect(packet.needsSerialization()).toBe(false);
packet.serialize();
expect(packet.needsSerialization()).toBe(false);
expect(packet.getByteLength()).toBe(28);
expect(packet.getPacketType()).toBe(RtcpPacket_1.RtcpPacketType.SR);
expect(packet.getCount()).toBe(0);
expect(packet.getPadding()).toBe(0);
expect(packet.getSsrc()).toBe(1111);
expect(packet.getNtpSeconds()).toBe(1234);
expect(packet.getNtpFraction()).toBe(2345);
expect(packet.getRtpTimestamp()).toBe(123456789);
expect(packet.getPacketCount()).toBe(666);
expect(packet.getOctetCount()).toBe(999);
expect(packet.needsSerialization()).toBe(false);
expect((0, RtcpPacket_1.isRtcp)(packet.getView())).toBe(true);
const report = new ReceiverReportPacket_1.ReceptionReport();
report.setSsrc(1234);
report.setFractionLost(50);
report.setTotalLost(4);
report.setHighestSeqNumber(5663);
report.setJitter(43);
report.setLastSRTimestamp(10012312);
report.setDelaySinceLastSR(999983432);
packet.setReports([report]);
expect((0, RtcpPacket_1.isRtcp)(packet.getView())).toBe(true);
const clonedPacket = packet.clone();
expect((0, RtcpPacket_1.isRtcp)(clonedPacket.getView())).toBe(true);
expect(clonedPacket.dump()).toEqual(packet.dump());
expect((0, helpers_1.areDataViewsEqual)(clonedPacket.getView(), packet.getView())).toBe(true);
});
test('packet.clone() succeeds', () => {
const array = new Uint8Array([
0xa0,
0xc8,
0x00,
0x08, // Padding, Type: 200, Count: 0, Length: 8
0x5d,
0x93,
0x15,
0x34, // SSRC: 0x5d931534
0xdd,
0x3a,
0xc1,
0xb4, // NTP Sec: 3711615412
0x76,
0x54,
0x71,
0x71, // NTP Frac: 1985245553
0x00,
0x08,
0xcf,
0x00, // RTP timestamp: 577280
0x00,
0x00,
0x0e,
0x18, // Packet count: 3608
0x00,
0x08,
0xcf,
0x00, // Octet count: 577280
0x00,
0x00,
0x00,
0x00, // Padding (8 bytes)
0x00,
0x00,
0x00,
0x08,
]);
const view = new DataView(array.buffer, array.byteOffset, array.byteLength);
const packet = new SenderReportPacket_1.SenderReportPacket(view);
const clonedPacket = packet.clone();
expect(clonedPacket.needsSerialization()).toBe(false);
expect(clonedPacket.getByteLength()).toBe(36);
expect(clonedPacket.getPacketType()).toBe(RtcpPacket_1.RtcpPacketType.SR);
expect(clonedPacket.getCount()).toBe(0);
expect(clonedPacket.getPadding()).toBe(8);
expect(packet.getSsrc()).toBe(0x5d931534);
expect(packet.getNtpSeconds()).toBe(3711615412);
expect(packet.getNtpFraction()).toBe(1985245553);
expect(packet.getRtpTimestamp()).toBe(577280);
expect(packet.getPacketCount()).toBe(3608);
expect(packet.getOctetCount()).toBe(577280);
expect(clonedPacket.dump()).toEqual(packet.dump());
expect((0, helpers_1.areDataViewsEqual)(clonedPacket.getView(), packet.getView())).toBe(true);
});
});