Skip to content
This repository has been archived by the owner on Jan 12, 2019. It is now read-only.

Ignore nit #284

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions src/segment-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@
patTableId, // :int
patCurrentNextIndicator, // Boolean
patSectionLength, // :uint
programNumber, // :uint
programPid, // :uint
patEntriesEnd, // :uint

pesPacketSize, // :int,
dataAlignmentIndicator, // :Boolean,
Expand Down Expand Up @@ -293,22 +296,31 @@
if (patCurrentNextIndicator) {
// section_length specifies the number of bytes following
// its position to the end of this section
// section_length = rest of header + (n * entry length) + CRC
// = 5 + (n * 4) + 4
patSectionLength = (data[offset + 1] & 0x0F) << 8 | data[offset + 2];
// move past the rest of the PSI header to the first program
// map table entry
offset += 8;

// we don't handle streams with more than one program, so
// raise an exception if we encounter one
// section_length = rest of header + (n * entry length) + CRC
// = 5 + (n * 4) + 4
if ((patSectionLength - 5 - 4) / 4 !== 1) {
throw new Error("TS has more that 1 program");
patEntriesEnd = offset + (patSectionLength - 5 - 4);
for (; offset < patEntriesEnd; offset += 4) {
programNumber = (data[offset] << 8 | data[offset + 1]);
programPid = (data[offset + 2] & 0x1F) << 8 | data[offset + 3];
// network PID program number equals 0
// this is primarily an artifact of EBU DVB and can be ignored
if (programNumber === 0) {
self.stream.networkPid = programPid;
} else if (self.stream.pmtPid === undefined) {
// the Program Map Table (PMT) associates the underlying
// video and audio streams with a unique PID
self.stream.pmtPid = programPid;
} else if (self.stream.pmtPid !== programPid) {
throw new Error("TS has more that 1 program");
}
}

// the Program Map Table (PMT) associates the underlying
// video and audio streams with a unique PID
self.stream.pmtPid = (data[offset + 2] & 0x1F) << 8 | data[offset + 3];
}
} else if (pid === self.stream.programMapTable[STREAM_TYPES.h264] ||
pid === self.stream.programMapTable[STREAM_TYPES.adts] ||
Expand Down Expand Up @@ -425,6 +437,9 @@
// rest of header + CRC = 9 + 4
pmtSectionLength -= 13;

// capture the PID of PCR packets so we can ignore them if we see any
self.stream.programMapTable.pcrPid = (data[offset + 8] & 0x1f) << 8 | data[offset + 9];

// align offset to the first entry in the PMT
offset += 12 + pmtProgramDescriptorsLength;

Expand Down Expand Up @@ -461,10 +476,16 @@
}
}
// We could test the CRC here to detect corruption with extra CPU cost
} else if (self.stream.networkPid === pid) {
// network information specific data (NIT) packet
} else if (0x0011 === pid) {
// Service Description Table
} else if (0x1FFF === pid) {
// NULL packet
} else if (self.stream.programMapTable.pcrPid) {
// program clock reference (PCR) PID for the primary program
// PTS values are sufficient to synchronize playback for us so
// we can safely ignore these
} else {
videojs.log("Unknown PID parsing TS packet: " + pid);
}
Expand Down
60 changes: 47 additions & 13 deletions test/segment-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,15 @@
makePmt = function(options) {
var
result = [],
pcr = options.pcr || 0,
entryCount = 0,
k,
sectionLength;

for (k in options.pids) {
entryCount++;
if (k !== 'pcr') {
entryCount++;
}
}
// table_id
result.push(0x02);
Expand All @@ -88,8 +91,8 @@
// last_section_number
result.push(0x00);
// reserved PCR_PID
result.push(0xe1);
result.push(0x00);
result.push(0xe0 | (pcr & (0x1f << 8)));
result.push(pcr & 0xff);
// reserved program_info_length
result.push(0xf0);
result.push(0x11); // hard-coded 17 byte descriptor
Expand Down Expand Up @@ -121,13 +124,26 @@
makePat = function(options) {
var
result = [],
programEntries = [],
sectionLength,
k;

// build the program entries first
for (k in options.programs) {
// program_number
programEntries.push((k & 0xFF00) >>> 8);
programEntries.push(k & 0x00FF);
// reserved program_map_pid
programEntries.push((options.programs[k] & 0x1f00) >>> 8);
programEntries.push(options.programs[k] & 0xff);
}
sectionLength = programEntries.length + 5 + 4;

// table_id
result.push(0x00);
// section_syntax_indicator '0' reserved section_length
result.push(0x80);
result.push(0x0d); // section_length for one program
result.push(0x80 | ((0x300 & sectionLength) >>> 8));
result.push(0xff & sectionLength); // section_length
// transport_stream_id
result.push(0x00);
result.push(0x00);
Expand All @@ -137,14 +153,8 @@
result.push(0x00);
// last_section_number
result.push(0x00);
for (k in options.programs) {
// program_number
result.push((k & 0xFF00) >>> 8);
result.push(k & 0x00FF);
// reserved program_map_pid
result.push((options.programs[k] & 0x1f00) >>> 8);
result.push(options.programs[k] & 0xff);
}
// program entries
result = result.concat(programEntries);
return result;
};

Expand Down Expand Up @@ -211,6 +221,30 @@
strictEqual(parser.stream.programMapTable[adtsType], 0x03, 'audio is PID 3');
});

test('ignores network information specific data (NIT) in the PAT', function() {
parser.parseSegmentBinaryData(new Uint8Array(makePacket({
programs: {
0x01: [0x01],
0x00: [0x00] // a NIT has a reserved PID of 0x00
}
})));

ok(true, 'did not throw when a NIT is encountered');
});

test('ignores packets with PCR pids', function() {
parser.parseSegmentBinaryData(new Uint8Array(makePacket({
programs: {
0x01: [0x01]
}
}).concat(makePacket({
pid: 0x01,
pcr: 0x02
}))));

equal(parser.stream.programMapTable.pcrPid, 0x02, 'parsed the PCR pid');
});

test('recognizes metadata streams', function() {
parser.parseSegmentBinaryData(new Uint8Array(makePacket({
programs: {
Expand Down