2bffee85 by David LaPalomento

NAL units may have unlimited trailing zeroes

When a NAL unit had trailing zeroes that were split across pushes to the H264Stream, the parser would go into an infinite loop. Instead, make sure we never advance the parser beyond the current push and advance the sync point to a valid position before starting processing. Add HTML-HLS dependencies to the example page.
1 parent 83153981
...@@ -34,6 +34,9 @@ ...@@ -34,6 +34,9 @@
34 <script src="node_modules/pkcs7/dist/pkcs7.unpad.js"></script> 34 <script src="node_modules/pkcs7/dist/pkcs7.unpad.js"></script>
35 <script src="src/decrypter.js"></script> 35 <script src="src/decrypter.js"></script>
36 36
37 <script src="../src/mp4-generator.js"></script>
38 <script src="../src/transmuxer.js"></script>
39
37 <script src="src/bin-utils.js"></script> 40 <script src="src/bin-utils.js"></script>
38 41
39 <!-- example MPEG2-TS segments --> 42 <!-- example MPEG2-TS segments -->
......
...@@ -522,8 +522,8 @@ AudioSegmentStream.prototype = new videojs.Hls.Stream(); ...@@ -522,8 +522,8 @@ AudioSegmentStream.prototype = new videojs.Hls.Stream();
522 */ 522 */
523 NalByteStream = function() { 523 NalByteStream = function() {
524 var 524 var
525 i = 6,
526 syncPoint = 1, 525 syncPoint = 1,
526 i,
527 buffer; 527 buffer;
528 NalByteStream.prototype.init.call(this); 528 NalByteStream.prototype.init.call(this);
529 529
...@@ -548,6 +548,16 @@ NalByteStream = function() { ...@@ -548,6 +548,16 @@ NalByteStream = function() {
548 // or this: 548 // or this:
549 // 0 0 1 .. NAL .. 0 0 0 549 // 0 0 1 .. NAL .. 0 0 0
550 // ^ sync point ^ i 550 // ^ sync point ^ i
551
552 // advance the sync point to a NAL start, if necessary
553 for (; syncPoint < buffer.byteLength - 3; syncPoint++) {
554 if (buffer[syncPoint + 2] === 1) {
555 // the sync point is properly aligned
556 i = syncPoint + 5;
557 break;
558 }
559 }
560
551 while (i < buffer.byteLength) { 561 while (i < buffer.byteLength) {
552 // look at the current byte to determine if we've hit the end of 562 // look at the current byte to determine if we've hit the end of
553 // a NAL unit boundary 563 // a NAL unit boundary
...@@ -568,7 +578,7 @@ NalByteStream = function() { ...@@ -568,7 +578,7 @@ NalByteStream = function() {
568 // drop trailing zeroes 578 // drop trailing zeroes
569 do { 579 do {
570 i++; 580 i++;
571 } while (buffer[i] !== 1); 581 } while (buffer[i] !== 1 && i < buffer.length);
572 syncPoint = i - 2; 582 syncPoint = i - 2;
573 i += 3; 583 i += 3;
574 break; 584 break;
......
...@@ -741,23 +741,60 @@ test('unpacks nal units from byte streams split across pushes', function() { ...@@ -741,23 +741,60 @@ test('unpacks nal units from byte streams split across pushes', function() {
741 type: 'video', 741 type: 'video',
742 data: new Uint8Array([ 742 data: new Uint8Array([
743 0x00, 0x00, 0x00, 0x01, 743 0x00, 0x00, 0x00, 0x01,
744 0x09]) 744 0x09, 0x07, 0x06, 0x05,
745 0x04
746 ])
745 }); 747 });
746 ok(!data, 'buffers NAL units across events'); 748 ok(!data, 'buffers NAL units across events');
747 749
748 h264Stream.push({ 750 h264Stream.push({
749 type: 'video', 751 type: 'video',
750 data: new Uint8Array([ 752 data: new Uint8Array([
751 0x07, 753 0x03, 0x02, 0x01,
752 0x00, 0x00, 0x01 754 0x00, 0x00, 0x01
753 ]) 755 ])
754 }); 756 });
755 ok(data, 'generated a data event'); 757 ok(data, 'generated a data event');
756 equal(data.nalUnitType, 'access_unit_delimiter_rbsp', 'identified an access unit delimiter'); 758 equal(data.nalUnitType, 'access_unit_delimiter_rbsp', 'identified an access unit delimiter');
757 equal(data.data.length, 2, 'calculated nal unit length'); 759 equal(data.data.length, 8, 'calculated nal unit length');
758 equal(data.data[1], 7, 'read a payload byte'); 760 equal(data.data[1], 7, 'read a payload byte');
759 }); 761 });
760 762
763 test('buffers nal unit trailing zeros across pushes', function() {
764 var data = [];
765 h264Stream.on('data', function(event) {
766 data.push(event);
767 });
768
769 // lots of zeros after the nal, stretching into the next push
770 h264Stream.push({
771 type: 'video',
772 data: new Uint8Array([
773 0x00, 0x00, 0x00, 0x01,
774 0x09, 0x07, 0x00, 0x00,
775 0x00, 0x00, 0x00, 0x00,
776 0x00, 0x00, 0x00, 0x00,
777 0x00
778 ])
779 });
780 equal(data.length, 1, 'delivered the first nal');
781
782 h264Stream.push({
783 type: 'video',
784 data: new Uint8Array([
785 0x00, 0x00,
786 0x00, 0x00, 0x01,
787 0x09, 0x06,
788 0x00, 0x00, 0x01
789 ])
790 });
791 equal(data.length, 2, 'generated data events');
792 equal(data[0].data.length, 2, 'ignored trailing zeros');
793 equal(data[0].data[0], 0x09, 'found the first nal start');
794 equal(data[1].data.length, 2, 'found the following nal start');
795 equal(data[1].data[0], 0x09, 'found the second nal start');
796 });
797
761 test('unpacks nal units from byte streams with split sync points', function() { 798 test('unpacks nal units from byte streams with split sync points', function() {
762 var data; 799 var data;
763 h264Stream.on('data', function(event) { 800 h264Stream.on('data', function(event) {
......