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 @@
<script src="node_modules/pkcs7/dist/pkcs7.unpad.js"></script>
<script src="src/decrypter.js"></script>
<script src="../src/mp4-generator.js"></script>
<script src="../src/transmuxer.js"></script>
<script src="src/bin-utils.js"></script>
<!-- example MPEG2-TS segments -->
......
......@@ -522,8 +522,8 @@ AudioSegmentStream.prototype = new videojs.Hls.Stream();
*/
NalByteStream = function() {
var
i = 6,
syncPoint = 1,
i,
buffer;
NalByteStream.prototype.init.call(this);
......@@ -548,6 +548,16 @@ NalByteStream = function() {
// or this:
// 0 0 1 .. NAL .. 0 0 0
// ^ sync point ^ i
// advance the sync point to a NAL start, if necessary
for (; syncPoint < buffer.byteLength - 3; syncPoint++) {
if (buffer[syncPoint + 2] === 1) {
// the sync point is properly aligned
i = syncPoint + 5;
break;
}
}
while (i < buffer.byteLength) {
// look at the current byte to determine if we've hit the end of
// a NAL unit boundary
......@@ -568,7 +578,7 @@ NalByteStream = function() {
// drop trailing zeroes
do {
i++;
} while (buffer[i] !== 1);
} while (buffer[i] !== 1 && i < buffer.length);
syncPoint = i - 2;
i += 3;
break;
......
......@@ -741,23 +741,60 @@ test('unpacks nal units from byte streams split across pushes', function() {
type: 'video',
data: new Uint8Array([
0x00, 0x00, 0x00, 0x01,
0x09])
0x09, 0x07, 0x06, 0x05,
0x04
])
});
ok(!data, 'buffers NAL units across events');
h264Stream.push({
type: 'video',
data: new Uint8Array([
0x07,
0x03, 0x02, 0x01,
0x00, 0x00, 0x01
])
});
ok(data, 'generated a data event');
equal(data.nalUnitType, 'access_unit_delimiter_rbsp', 'identified an access unit delimiter');
equal(data.data.length, 2, 'calculated nal unit length');
equal(data.data.length, 8, 'calculated nal unit length');
equal(data.data[1], 7, 'read a payload byte');
});
test('buffers nal unit trailing zeros across pushes', function() {
var data = [];
h264Stream.on('data', function(event) {
data.push(event);
});
// lots of zeros after the nal, stretching into the next push
h264Stream.push({
type: 'video',
data: new Uint8Array([
0x00, 0x00, 0x00, 0x01,
0x09, 0x07, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00
])
});
equal(data.length, 1, 'delivered the first nal');
h264Stream.push({
type: 'video',
data: new Uint8Array([
0x00, 0x00,
0x00, 0x00, 0x01,
0x09, 0x06,
0x00, 0x00, 0x01
])
});
equal(data.length, 2, 'generated data events');
equal(data[0].data.length, 2, 'ignored trailing zeros');
equal(data[0].data[0], 0x09, 'found the first nal start');
equal(data[1].data.length, 2, 'found the following nal start');
equal(data[1].data[0], 0x09, 'found the second nal start');
});
test('unpacks nal units from byte streams with split sync points', function() {
var data;
h264Stream.on('data', function(event) {
......