666609bd by David LaPalomento

Generate an mfhd with a valid sequence number

Allow sequence numbers to be passed in during moof generation. Hook up the transmuxer to specify increasing sequence numbers as media segments are built.
1 parent 49e93b2e
(function(window, videojs, undefined) {
'use strict';
var box, dinf, ftyp, mdat, minf, moof, moov, mvex, mvhd, trak, tkhd, mdia, mdhd, hdlr, stbl,
var box, dinf, ftyp, mdat, mfhd, minf, moof, moov, mvex, mvhd, trak, tkhd, mdia, mdhd, hdlr, stbl,
stsd, styp, types, MAJOR_BRAND, MINOR_VERSION, VIDEO_HDLR, AUDIO_HDLR, HDLR_TYPES, VMHD, DREF, STCO, STSC, STSZ, STTS, TREX,
Uint8Array, DataView;
......@@ -188,10 +188,20 @@ mdhd = function(duration) {
mdia = function(duration, width, height, type) {
return box(types.mdia, mdhd(duration), hdlr(type), minf(width, height));
};
mfhd = function(sequenceNumber) {
return box(types.mfhd, new Uint8Array([
0x00,
0x00, 0x00, 0x00, // flags
(sequenceNumber & 0xFF000000) >> 24,
(sequenceNumber & 0xFF0000) >> 16,
(sequenceNumber & 0xFF00) >> 8,
sequenceNumber & 0xFF, // sequence_number
]));
};
minf = function(width, height) {
return box(types.minf, box(types.vmhd, VMHD), dinf(), stbl(width, height));
};
moof = function(tracks) {
moof = function(sequenceNumber, tracks) {
var
trafCall = [],
i = tracks.length;
......@@ -208,7 +218,7 @@ moof = function(tracks) {
}
trafCall.unshift(types.traf);
return box(types.moof,
box(types.mfhd),
mfhd(sequenceNumber),
box.apply(null, trafCall));
};
moov = function(duration, width, height, type) {
......
......@@ -421,7 +421,10 @@ H264Stream.prototype = new videojs.Hls.Stream();
Transmuxer = function() {
var self = this, packetStream, parseStream, programStream, aacStream, h264Stream;
var
self = this,
sequenceNumber = 0,
packetStream, parseStream, programStream, aacStream, h264Stream;
Transmuxer.prototype.init.call(this);
// set up the parsing pipeline
......@@ -443,10 +446,15 @@ Transmuxer = function() {
});
h264Stream.on('data', function(data) {
var
moof = mp4.moof([]),
moof = mp4.moof(sequenceNumber, []),
mdat = mp4.mdat(data.data),
// it would be great to allocate this array up front instead of
// throwing away hundreds of media segment fragments
boxes = new Uint8Array(moof.byteLength + mdat.byteLength);
// bump the sequence number for next time
sequenceNumber++;
boxes.set(moof);
boxes.set(mdat, moof.byteLength);
......
......@@ -246,7 +246,7 @@ test('generates an initialization segment', function() {
test('generates a minimal moof', function() {
var
data = mp4.moof([{
data = mp4.moof(7, [{
trackId: 1
}, {
trackId: 2
......@@ -257,6 +257,7 @@ test('generates a minimal moof', function() {
equal(moof[0].type, 'moof', 'generated a moof box');
equal(moof[0].boxes.length, 2, 'generated two child boxes');
equal(moof[0].boxes[0].type, 'mfhd', 'generated an mfhd box');
equal(moof[0].boxes[0].sequenceNumber, 7, 'included the sequence_number');
equal(moof[0].boxes[1].type, 'traf', 'generated a traf box');
equal(moof[0].boxes[1].boxes.length, 2, 'generated two fragment headers');
equal(moof[0].boxes[1].boxes[0].type, 'tfhd', 'generated a tfhd box');
......@@ -274,5 +275,4 @@ test('generates an mdat', function() {
deepEqual(mdat[0].byteLength, 4, 'encapsulated the data');
});
})(window, window.videojs);
......
......@@ -643,7 +643,10 @@ test('generates an init segment', function() {
});
test('parses an example mp2t file and generates media segments', function() {
var segments = [], i, boxes;
var
segments = [],
sequenceNumber = window.Infinity,
i, boxes, mfhd, traf, mdat;
transmuxer.on('data', function(segment) {
segments.push(segment);
});
......@@ -656,9 +659,16 @@ test('parses an example mp2t file and generates media segments', function() {
boxes = videojs.inspectMp4(segments[i].data);
equal(boxes.length, 2, 'segments are composed of two boxes');
equal(boxes[0].type, 'moof', 'first box is a moof');
equal(boxes[0].boxes.length, 2, 'moof has three children');
equal(boxes[0].boxes[0].type, 'mfhd', 'mfhd is a child of the moof');
equal(boxes[0].boxes[1].type, 'traf', 'traf is a child of the moof');
equal(boxes[0].boxes.length, 2, 'the moof has two children');
mfhd = boxes[0].boxes[0];
equal(mfhd.type, 'mfhd', 'mfhd is a child of the moof');
ok(mfhd.sequenceNumber < sequenceNumber, 'sequence numbers are increasing');
sequenceNumber = mfhd.sequenceNumber;
traf = boxes[0].boxes[1];
equal(traf.type, 'traf', 'traf is a child of the moof');
equal(boxes[1].type, 'mdat', 'second box is an mdat');
}
});
......