93d4e050 by David LaPalomento

Merge pull request #288 from dmlap/ignore-nit2

Ignore nit2
2 parents ad2140d0 c61a7591
...@@ -221,6 +221,9 @@ ...@@ -221,6 +221,9 @@
221 patTableId, // :int 221 patTableId, // :int
222 patCurrentNextIndicator, // Boolean 222 patCurrentNextIndicator, // Boolean
223 patSectionLength, // :uint 223 patSectionLength, // :uint
224 programNumber, // :uint
225 programPid, // :uint
226 patEntriesEnd, // :uint
224 227
225 pesPacketSize, // :int, 228 pesPacketSize, // :int,
226 dataAlignmentIndicator, // :Boolean, 229 dataAlignmentIndicator, // :Boolean,
...@@ -293,6 +296,8 @@ ...@@ -293,6 +296,8 @@
293 if (patCurrentNextIndicator) { 296 if (patCurrentNextIndicator) {
294 // section_length specifies the number of bytes following 297 // section_length specifies the number of bytes following
295 // its position to the end of this section 298 // its position to the end of this section
299 // section_length = rest of header + (n * entry length) + CRC
300 // = 5 + (n * 4) + 4
296 patSectionLength = (data[offset + 1] & 0x0F) << 8 | data[offset + 2]; 301 patSectionLength = (data[offset + 1] & 0x0F) << 8 | data[offset + 2];
297 // move past the rest of the PSI header to the first program 302 // move past the rest of the PSI header to the first program
298 // map table entry 303 // map table entry
...@@ -300,15 +305,22 @@ ...@@ -300,15 +305,22 @@
300 305
301 // we don't handle streams with more than one program, so 306 // we don't handle streams with more than one program, so
302 // raise an exception if we encounter one 307 // raise an exception if we encounter one
303 // section_length = rest of header + (n * entry length) + CRC 308 patEntriesEnd = offset + (patSectionLength - 5 - 4);
304 // = 5 + (n * 4) + 4 309 for (; offset < patEntriesEnd; offset += 4) {
305 if ((patSectionLength - 5 - 4) / 4 !== 1) { 310 programNumber = (data[offset] << 8 | data[offset + 1]);
306 throw new Error("TS has more that 1 program"); 311 programPid = (data[offset + 2] & 0x1F) << 8 | data[offset + 3];
312 // network PID program number equals 0
313 // this is primarily an artifact of EBU DVB and can be ignored
314 if (programNumber === 0) {
315 self.stream.networkPid = programPid;
316 } else if (self.stream.pmtPid === undefined) {
317 // the Program Map Table (PMT) associates the underlying
318 // video and audio streams with a unique PID
319 self.stream.pmtPid = programPid;
320 } else if (self.stream.pmtPid !== programPid) {
321 throw new Error("TS has more that 1 program");
322 }
307 } 323 }
308
309 // the Program Map Table (PMT) associates the underlying
310 // video and audio streams with a unique PID
311 self.stream.pmtPid = (data[offset + 2] & 0x1F) << 8 | data[offset + 3];
312 } 324 }
313 } else if (pid === self.stream.programMapTable[STREAM_TYPES.h264] || 325 } else if (pid === self.stream.programMapTable[STREAM_TYPES.h264] ||
314 pid === self.stream.programMapTable[STREAM_TYPES.adts] || 326 pid === self.stream.programMapTable[STREAM_TYPES.adts] ||
...@@ -425,6 +437,9 @@ ...@@ -425,6 +437,9 @@
425 // rest of header + CRC = 9 + 4 437 // rest of header + CRC = 9 + 4
426 pmtSectionLength -= 13; 438 pmtSectionLength -= 13;
427 439
440 // capture the PID of PCR packets so we can ignore them if we see any
441 self.stream.programMapTable.pcrPid = (data[offset + 8] & 0x1f) << 8 | data[offset + 9];
442
428 // align offset to the first entry in the PMT 443 // align offset to the first entry in the PMT
429 offset += 12 + pmtProgramDescriptorsLength; 444 offset += 12 + pmtProgramDescriptorsLength;
430 445
...@@ -461,10 +476,16 @@ ...@@ -461,10 +476,16 @@
461 } 476 }
462 } 477 }
463 // We could test the CRC here to detect corruption with extra CPU cost 478 // We could test the CRC here to detect corruption with extra CPU cost
479 } else if (self.stream.networkPid === pid) {
480 // network information specific data (NIT) packet
464 } else if (0x0011 === pid) { 481 } else if (0x0011 === pid) {
465 // Service Description Table 482 // Service Description Table
466 } else if (0x1FFF === pid) { 483 } else if (0x1FFF === pid) {
467 // NULL packet 484 // NULL packet
485 } else if (self.stream.programMapTable.pcrPid) {
486 // program clock reference (PCR) PID for the primary program
487 // PTS values are sufficient to synchronize playback for us so
488 // we can safely ignore these
468 } else { 489 } else {
469 videojs.log("Unknown PID parsing TS packet: " + pid); 490 videojs.log("Unknown PID parsing TS packet: " + pid);
470 } 491 }
......
...@@ -64,12 +64,15 @@ ...@@ -64,12 +64,15 @@
64 makePmt = function(options) { 64 makePmt = function(options) {
65 var 65 var
66 result = [], 66 result = [],
67 pcr = options.pcr || 0,
67 entryCount = 0, 68 entryCount = 0,
68 k, 69 k,
69 sectionLength; 70 sectionLength;
70 71
71 for (k in options.pids) { 72 for (k in options.pids) {
72 entryCount++; 73 if (k !== 'pcr') {
74 entryCount++;
75 }
73 } 76 }
74 // table_id 77 // table_id
75 result.push(0x02); 78 result.push(0x02);
...@@ -88,8 +91,8 @@ ...@@ -88,8 +91,8 @@
88 // last_section_number 91 // last_section_number
89 result.push(0x00); 92 result.push(0x00);
90 // reserved PCR_PID 93 // reserved PCR_PID
91 result.push(0xe1); 94 result.push(0xe0 | (pcr & (0x1f << 8)));
92 result.push(0x00); 95 result.push(pcr & 0xff);
93 // reserved program_info_length 96 // reserved program_info_length
94 result.push(0xf0); 97 result.push(0xf0);
95 result.push(0x11); // hard-coded 17 byte descriptor 98 result.push(0x11); // hard-coded 17 byte descriptor
...@@ -121,13 +124,26 @@ ...@@ -121,13 +124,26 @@
121 makePat = function(options) { 124 makePat = function(options) {
122 var 125 var
123 result = [], 126 result = [],
127 programEntries = [],
128 sectionLength,
124 k; 129 k;
125 130
131 // build the program entries first
132 for (k in options.programs) {
133 // program_number
134 programEntries.push((k & 0xFF00) >>> 8);
135 programEntries.push(k & 0x00FF);
136 // reserved program_map_pid
137 programEntries.push((options.programs[k] & 0x1f00) >>> 8);
138 programEntries.push(options.programs[k] & 0xff);
139 }
140 sectionLength = programEntries.length + 5 + 4;
141
126 // table_id 142 // table_id
127 result.push(0x00); 143 result.push(0x00);
128 // section_syntax_indicator '0' reserved section_length 144 // section_syntax_indicator '0' reserved section_length
129 result.push(0x80); 145 result.push(0x80 | ((0x300 & sectionLength) >>> 8));
130 result.push(0x0d); // section_length for one program 146 result.push(0xff & sectionLength); // section_length
131 // transport_stream_id 147 // transport_stream_id
132 result.push(0x00); 148 result.push(0x00);
133 result.push(0x00); 149 result.push(0x00);
...@@ -137,14 +153,8 @@ ...@@ -137,14 +153,8 @@
137 result.push(0x00); 153 result.push(0x00);
138 // last_section_number 154 // last_section_number
139 result.push(0x00); 155 result.push(0x00);
140 for (k in options.programs) { 156 // program entries
141 // program_number 157 result = result.concat(programEntries);
142 result.push((k & 0xFF00) >>> 8);
143 result.push(k & 0x00FF);
144 // reserved program_map_pid
145 result.push((options.programs[k] & 0x1f00) >>> 8);
146 result.push(options.programs[k] & 0xff);
147 }
148 return result; 158 return result;
149 }; 159 };
150 160
...@@ -211,6 +221,30 @@ ...@@ -211,6 +221,30 @@
211 strictEqual(parser.stream.programMapTable[adtsType], 0x03, 'audio is PID 3'); 221 strictEqual(parser.stream.programMapTable[adtsType], 0x03, 'audio is PID 3');
212 }); 222 });
213 223
224 test('ignores network information specific data (NIT) in the PAT', function() {
225 parser.parseSegmentBinaryData(new Uint8Array(makePacket({
226 programs: {
227 0x01: [0x01],
228 0x00: [0x00] // a NIT has a reserved PID of 0x00
229 }
230 })));
231
232 ok(true, 'did not throw when a NIT is encountered');
233 });
234
235 test('ignores packets with PCR pids', function() {
236 parser.parseSegmentBinaryData(new Uint8Array(makePacket({
237 programs: {
238 0x01: [0x01]
239 }
240 }).concat(makePacket({
241 pid: 0x01,
242 pcr: 0x02
243 }))));
244
245 equal(parser.stream.programMapTable.pcrPid, 0x02, 'parsed the PCR pid');
246 });
247
214 test('recognizes metadata streams', function() { 248 test('recognizes metadata streams', function() {
215 parser.parseSegmentBinaryData(new Uint8Array(makePacket({ 249 parser.parseSegmentBinaryData(new Uint8Array(makePacket({
216 programs: { 250 programs: {
......