93d4e050 by David LaPalomento

Merge pull request #288 from dmlap/ignore-nit2

Ignore nit2
2 parents ad2140d0 c61a7591
......@@ -221,6 +221,9 @@
patTableId, // :int
patCurrentNextIndicator, // Boolean
patSectionLength, // :uint
programNumber, // :uint
programPid, // :uint
patEntriesEnd, // :uint
pesPacketSize, // :int,
dataAlignmentIndicator, // :Boolean,
......@@ -293,6 +296,8 @@
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
......@@ -300,15 +305,22 @@
// 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 = (data[offset + 2] & 0x1F) << 8 | data[offset + 3];
self.stream.pmtPid = programPid;
} else if (self.stream.pmtPid !== programPid) {
throw new Error("TS has more that 1 program");
}
}
}
} else if (pid === self.stream.programMapTable[STREAM_TYPES.h264] ||
pid === self.stream.programMapTable[STREAM_TYPES.adts] ||
......@@ -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;
......@@ -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);
}
......
......@@ -64,13 +64,16 @@
makePmt = function(options) {
var
result = [],
pcr = options.pcr || 0,
entryCount = 0,
k,
sectionLength;
for (k in options.pids) {
if (k !== 'pcr') {
entryCount++;
}
}
// table_id
result.push(0x02);
// section_syntax_indicator '0' reserved section_length
......@@ -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
......@@ -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);
......@@ -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;
};
......@@ -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: {
......