update hlsjs

This commit is contained in:
Luke Pulverenti 2015-12-21 14:09:46 -05:00
parent 0b318b6cb2
commit 40baf2dcca
9 changed files with 201 additions and 153 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "hls.js", "name": "hls.js",
"version": "0.3.13", "version": "0.3.14",
"description": "Media Source Extension - HLS library, by/for Dailymotion", "description": "Media Source Extension - HLS library, by/for Dailymotion",
"homepage": "https://github.com/dailymotion/hls.js", "homepage": "https://github.com/dailymotion/hls.js",
"authors": [ "authors": [
@ -15,11 +15,11 @@
"test", "test",
"tests" "tests"
], ],
"_release": "0.3.13", "_release": "0.3.14",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "v0.3.13", "tag": "v0.3.14",
"commit": "a7aa29605b6814b2f99c1e07db0fcb5bf9cd890a" "commit": "1806e59551b0639c50efa348cac92dc41c8a7dea"
}, },
"_source": "git://github.com/dailymotion/hls.js.git", "_source": "git://github.com/dailymotion/hls.js.git",
"_target": "~0.3.11", "_target": "~0.3.11",

View File

@ -197,7 +197,7 @@ configuration parameters could be provided to hls.js upon instantiation of Hls O
manifestLoadingRetryDelay : 500, manifestLoadingRetryDelay : 500,
fpsDroppedMonitoringPeriod : 5000, fpsDroppedMonitoringPeriod : 5000,
fpsDroppedMonitoringThreshold : 0.2, fpsDroppedMonitoringThreshold : 0.2,
appendErrorMaxRetry : 200, appendErrorMaxRetry : 3,
loader : customLoader, loader : customLoader,
fLoader: customFragmentLoader, fLoader: customFragmentLoader,
pLoader: customPlaylistLoader, pLoader: customPlaylistLoader,
@ -275,7 +275,7 @@ any I/O error will trigger retries every 500ms,1s,2s,4s,8s, ... capped to 64s (e
max nb of append retry max nb of append retry
#### ```appendErrorMaxRetry``` #### ```appendErrorMaxRetry```
(default 200) (default 3)
max number of sourceBuffer.appendBuffer() retry upon error. max number of sourceBuffer.appendBuffer() retry upon error.
such error could happen in loop with UHD streams, when internal buffer is full. (Quota Exceeding Error will be triggered). in that case we need to wait for the browser to evict some data before being able to append buffer correctly. such error could happen in loop with UHD streams, when internal buffer is full. (Quota Exceeding Error will be triggered). in that case we need to wait for the browser to evict some data before being able to append buffer correctly.

View File

@ -1194,26 +1194,30 @@ var MSEMediaController = (function () {
this.appendError = 0; this.appendError = 0;
} catch (err) { } catch (err) {
// in case any error occured while appending, put back segment in mp4segments table // in case any error occured while appending, put back segment in mp4segments table
//logger.error(`error while trying to append buffer:${err.message},try appending later`); _utilsLogger.logger.error('error while trying to append buffer:' + err.message + ',try appending later');
this.mp4segments.unshift(segment); this.mp4segments.unshift(segment);
if (this.appendError) { // just discard QuotaExceededError for now, and wait for the natural browser buffer eviction
this.appendError++; //http://www.w3.org/TR/html5/infrastructure.html#quotaexceedederror
} else { if (err.code !== 22) {
this.appendError = 1; if (this.appendError) {
} this.appendError++;
var event = { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.BUFFER_APPEND_ERROR, frag: this.fragCurrent }; } else {
/* with UHD content, we could get loop of quota exceeded error until this.appendError = 1;
browser is able to evict some data from sourcebuffer. retrying help recovering this }
*/ var event = { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.BUFFER_APPEND_ERROR, frag: this.fragCurrent };
if (this.appendError > this.config.appendErrorMaxRetry) { /* with UHD content, we could get loop of quota exceeded error until
_utilsLogger.logger.log('fail ' + this.config.appendErrorMaxRetry + ' times to append segment in sourceBuffer'); browser is able to evict some data from sourcebuffer. retrying help recovering this
event.fatal = true; */
hls.trigger(_events2['default'].ERROR, event); if (this.appendError > this.config.appendErrorMaxRetry) {
this.state = State.ERROR; _utilsLogger.logger.log('fail ' + this.config.appendErrorMaxRetry + ' times to append segment in sourceBuffer');
return; event.fatal = true;
} else { hls.trigger(_events2['default'].ERROR, event);
event.fatal = false; this.state = State.ERROR;
hls.trigger(_events2['default'].ERROR, event); return;
} else {
event.fatal = false;
hls.trigger(_events2['default'].ERROR, event);
}
} }
} }
this.state = State.APPENDING; this.state = State.APPENDING;
@ -4760,7 +4764,7 @@ var Hls = (function () {
manifestLoadingRetryDelay: 1000, manifestLoadingRetryDelay: 1000,
// fpsDroppedMonitoringPeriod: 5000, // fpsDroppedMonitoringPeriod: 5000,
// fpsDroppedMonitoringThreshold: 0.2, // fpsDroppedMonitoringThreshold: 0.2,
appendErrorMaxRetry: 200, appendErrorMaxRetry: 3,
loader: _utilsXhrLoader2['default'], loader: _utilsXhrLoader2['default'],
fLoader: undefined, fLoader: undefined,
pLoader: undefined, pLoader: undefined,
@ -5657,6 +5661,7 @@ var MP4 = (function () {
var payload = Array.prototype.slice.call(arguments, 1), var payload = Array.prototype.slice.call(arguments, 1),
size = 0, size = 0,
i = payload.length, i = payload.length,
len = i,
result, result,
view; view;
// calculate the total size we need to allocate // calculate the total size we need to allocate
@ -5668,7 +5673,7 @@ var MP4 = (function () {
view.setUint32(0, result.byteLength); view.setUint32(0, result.byteLength);
result.set(type, 4); result.set(type, 4);
// copy the payload into the result // copy the payload into the result
for (i = 0, size = 8; i < payload.length; i++) { for (i = 0, size = 8; i < len; i++) {
result.set(payload[i], size); result.set(payload[i], size);
size += payload[i].byteLength; size += payload[i].byteLength;
} }
@ -5824,7 +5829,10 @@ var MP4 = (function () {
0xfc | 3, // lengthSizeMinusOne, hard-coded to 4 bytes 0xfc | 3, // lengthSizeMinusOne, hard-coded to 4 bytes
0xE0 | track.sps.length // 3bit reserved (111) + numOfSequenceParameterSets 0xE0 | track.sps.length // 3bit reserved (111) + numOfSequenceParameterSets
].concat(sps).concat([track.pps.length // numOfPictureParameterSets ].concat(sps).concat([track.pps.length // numOfPictureParameterSets
]).concat(pps))); // "PPS" ]).concat(pps))),
// "PPS"
width = track.width,
height = track.height;
//console.log('avcc:' + Hex.hexDump(avcc)); //console.log('avcc:' + Hex.hexDump(avcc));
return MP4.box(MP4.types.avc1, new Uint8Array([0x00, 0x00, 0x00, // reserved return MP4.box(MP4.types.avc1, new Uint8Array([0x00, 0x00, 0x00, // reserved
0x00, 0x00, 0x00, // reserved 0x00, 0x00, 0x00, // reserved
@ -5832,8 +5840,8 @@ var MP4 = (function () {
0x00, 0x00, // pre_defined 0x00, 0x00, // pre_defined
0x00, 0x00, // reserved 0x00, 0x00, // reserved
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // pre_defined 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // pre_defined
track.width >> 8 & 0xFF, track.width & 0xff, // width width >> 8 & 0xFF, width & 0xff, // width
track.height >> 8 & 0xFF, track.height & 0xff, // height height >> 8 & 0xFF, height & 0xff, // height
0x00, 0x48, 0x00, 0x00, // horizresolution 0x00, 0x48, 0x00, 0x00, // horizresolution
0x00, 0x48, 0x00, 0x00, // vertresolution 0x00, 0x48, 0x00, 0x00, // vertresolution
0x00, 0x00, 0x00, 0x00, // reserved 0x00, 0x00, 0x00, 0x00, // reserved
@ -5849,16 +5857,17 @@ var MP4 = (function () {
}, { }, {
key: 'esds', key: 'esds',
value: function esds(track) { value: function esds(track) {
var configlen = track.config.length;
return new Uint8Array([0x00, // version 0 return new Uint8Array([0x00, // version 0
0x00, 0x00, 0x00, // flags 0x00, 0x00, 0x00, // flags
0x03, // descriptor_type 0x03, // descriptor_type
0x17 + track.config.length, // length 0x17 + configlen, // length
0x00, 0x01, //es_id 0x00, 0x01, //es_id
0x00, // stream_priority 0x00, // stream_priority
0x04, // descriptor_type 0x04, // descriptor_type
0x0f + track.config.length, // length 0x0f + configlen, // length
0x40, //codec : mpeg4_audio 0x40, //codec : mpeg4_audio
0x15, // stream_type 0x15, // stream_type
0x00, 0x00, 0x00, // buffer_size 0x00, 0x00, 0x00, // buffer_size
@ -5866,11 +5875,12 @@ var MP4 = (function () {
0x00, 0x00, 0x00, 0x00, // avgBitrate 0x00, 0x00, 0x00, 0x00, // avgBitrate
0x05 // descriptor_type 0x05 // descriptor_type
].concat([track.config.length]).concat(track.config).concat([0x06, 0x01, 0x02])); // GASpecificConfig)); // length + audio config descriptor ].concat([configlen]).concat(track.config).concat([0x06, 0x01, 0x02])); // GASpecificConfig)); // length + audio config descriptor
} }
}, { }, {
key: 'mp4a', key: 'mp4a',
value: function mp4a(track) { value: function mp4a(track) {
var audiosamplerate = track.audiosamplerate;
return MP4.box(MP4.types.mp4a, new Uint8Array([0x00, 0x00, 0x00, // reserved return MP4.box(MP4.types.mp4a, new Uint8Array([0x00, 0x00, 0x00, // reserved
0x00, 0x00, 0x00, // reserved 0x00, 0x00, 0x00, // reserved
0x00, 0x01, // data_reference_index 0x00, 0x01, // data_reference_index
@ -5878,7 +5888,7 @@ var MP4 = (function () {
0x00, track.channelCount, // channelcount 0x00, track.channelCount, // channelcount
0x00, 0x10, // sampleSize:16bits 0x00, 0x10, // sampleSize:16bits
0x00, 0x00, 0x00, 0x00, // reserved2 0x00, 0x00, 0x00, 0x00, // reserved2
track.audiosamplerate >> 8 & 0xFF, track.audiosamplerate & 0xff, // audiosamplerate >> 8 & 0xFF, audiosamplerate & 0xff, //
0x00, 0x00]), MP4.box(MP4.types.esds, MP4.esds(track))); 0x00, 0x00]), MP4.box(MP4.types.esds, MP4.esds(track)));
} }
}, { }, {
@ -5893,30 +5903,35 @@ var MP4 = (function () {
}, { }, {
key: 'tkhd', key: 'tkhd',
value: function tkhd(track) { value: function tkhd(track) {
var id = track.id,
duration = track.duration,
width = track.width,
height = track.height;
return MP4.box(MP4.types.tkhd, new Uint8Array([0x00, // version 0 return MP4.box(MP4.types.tkhd, new Uint8Array([0x00, // version 0
0x00, 0x00, 0x07, // flags 0x00, 0x00, 0x07, // flags
0x00, 0x00, 0x00, 0x00, // creation_time 0x00, 0x00, 0x00, 0x00, // creation_time
0x00, 0x00, 0x00, 0x00, // modification_time 0x00, 0x00, 0x00, 0x00, // modification_time
track.id >> 24 & 0xFF, track.id >> 16 & 0xFF, track.id >> 8 & 0xFF, track.id & 0xFF, // track_ID id >> 24 & 0xFF, id >> 16 & 0xFF, id >> 8 & 0xFF, id & 0xFF, // track_ID
0x00, 0x00, 0x00, 0x00, // reserved 0x00, 0x00, 0x00, 0x00, // reserved
track.duration >> 24, track.duration >> 16 & 0xFF, track.duration >> 8 & 0xFF, track.duration & 0xFF, // duration duration >> 24, duration >> 16 & 0xFF, duration >> 8 & 0xFF, duration & 0xFF, // duration
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved
0x00, 0x00, // layer 0x00, 0x00, // layer
0x00, 0x00, // alternate_group 0x00, 0x00, // alternate_group
0x00, 0x00, // non-audio track volume 0x00, 0x00, // non-audio track volume
0x00, 0x00, // reserved 0x00, 0x00, // reserved
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix
track.width >> 8 & 0xFF, track.width & 0xFF, 0x00, 0x00, // width width >> 8 & 0xFF, width & 0xFF, 0x00, 0x00, // width
track.height >> 8 & 0xFF, track.height & 0xFF, 0x00, 0x00 // height height >> 8 & 0xFF, height & 0xFF, 0x00, 0x00 // height
])); ]));
} }
}, { }, {
key: 'traf', key: 'traf',
value: function traf(track, baseMediaDecodeTime) { value: function traf(track, baseMediaDecodeTime) {
var sampleDependencyTable = MP4.sdtp(track); var sampleDependencyTable = MP4.sdtp(track),
id = track.id;
return MP4.box(MP4.types.traf, MP4.box(MP4.types.tfhd, new Uint8Array([0x00, // version 0 return MP4.box(MP4.types.traf, MP4.box(MP4.types.tfhd, new Uint8Array([0x00, // version 0
0x00, 0x00, 0x00, // flags 0x00, 0x00, 0x00, // flags
track.id >> 24, track.id >> 16 & 0XFF, track.id >> 8 & 0XFF, track.id & 0xFF])), // track_ID id >> 24, id >> 16 & 0XFF, id >> 8 & 0XFF, id & 0xFF])), // track_ID
MP4.box(MP4.types.tfdt, new Uint8Array([0x00, // version 0 MP4.box(MP4.types.tfdt, new Uint8Array([0x00, // version 0
0x00, 0x00, 0x00, // flags 0x00, 0x00, 0x00, // flags
baseMediaDecodeTime >> 24, baseMediaDecodeTime >> 16 & 0XFF, baseMediaDecodeTime >> 8 & 0XFF, baseMediaDecodeTime & 0xFF])), // baseMediaDecodeTime baseMediaDecodeTime >> 24, baseMediaDecodeTime >> 16 & 0XFF, baseMediaDecodeTime >> 8 & 0XFF, baseMediaDecodeTime & 0xFF])), // baseMediaDecodeTime
@ -5943,9 +5958,10 @@ var MP4 = (function () {
}, { }, {
key: 'trex', key: 'trex',
value: function trex(track) { value: function trex(track) {
var id = track.id;
return MP4.box(MP4.types.trex, new Uint8Array([0x00, // version 0 return MP4.box(MP4.types.trex, new Uint8Array([0x00, // version 0
0x00, 0x00, 0x00, // flags 0x00, 0x00, 0x00, // flags
track.id >> 24, track.id >> 16 & 0XFF, track.id >> 8 & 0XFF, track.id & 0xFF, // track_ID id >> 24, id >> 16 & 0XFF, id >> 8 & 0XFF, id & 0xFF, // track_ID
0x00, 0x00, 0x00, 0x01, // default_sample_description_index 0x00, 0x00, 0x00, 0x01, // default_sample_description_index
0x00, 0x00, 0x00, 0x00, // default_sample_duration 0x00, 0x00, 0x00, 0x00, // default_sample_duration
0x00, 0x00, 0x00, 0x00, // default_sample_size 0x00, 0x00, 0x00, 0x00, // default_sample_size
@ -5955,21 +5971,32 @@ var MP4 = (function () {
}, { }, {
key: 'trun', key: 'trun',
value: function trun(track, offset) { value: function trun(track, offset) {
var samples, sample, i, array; var samples = track.samples || [],
samples = track.samples || []; len = samples.length,
array = new Uint8Array(12 + 16 * samples.length); arraylen = 12 + 16 * len,
offset += 8 + array.byteLength; array = new Uint8Array(arraylen),
i,
sample,
duration,
size,
flags,
cts;
offset += 8 + arraylen;
array.set([0x00, // version 0 array.set([0x00, // version 0
0x00, 0x0f, 0x01, // flags 0x00, 0x0f, 0x01, // flags
samples.length >>> 24 & 0xFF, samples.length >>> 16 & 0xFF, samples.length >>> 8 & 0xFF, samples.length & 0xFF, // sample_count len >>> 24 & 0xFF, len >>> 16 & 0xFF, len >>> 8 & 0xFF, len & 0xFF, // sample_count
offset >>> 24 & 0xFF, offset >>> 16 & 0xFF, offset >>> 8 & 0xFF, offset & 0xFF // data_offset offset >>> 24 & 0xFF, offset >>> 16 & 0xFF, offset >>> 8 & 0xFF, offset & 0xFF // data_offset
], 0); ], 0);
for (i = 0; i < samples.length; i++) { for (i = 0; i < len; i++) {
sample = samples[i]; sample = samples[i];
array.set([sample.duration >>> 24 & 0xFF, sample.duration >>> 16 & 0xFF, sample.duration >>> 8 & 0xFF, sample.duration & 0xFF, // sample_duration duration = sample.duration;
sample.size >>> 24 & 0xFF, sample.size >>> 16 & 0xFF, sample.size >>> 8 & 0xFF, sample.size & 0xFF, // sample_size size = sample.size;
sample.flags.isLeading << 2 | sample.flags.dependsOn, sample.flags.isDependedOn << 6 | sample.flags.hasRedundancy << 4 | sample.flags.paddingValue << 1 | sample.flags.isNonSync, sample.flags.degradPrio & 0xF0 << 8, sample.flags.degradPrio & 0x0F, // sample_flags flags = sample.flags;
sample.cts >>> 24 & 0xFF, sample.cts >>> 16 & 0xFF, sample.cts >>> 8 & 0xFF, sample.cts & 0xFF // sample_composition_time_offset cts = sample.cts;
array.set([duration >>> 24 & 0xFF, duration >>> 16 & 0xFF, duration >>> 8 & 0xFF, duration & 0xFF, // sample_duration
size >>> 24 & 0xFF, size >>> 16 & 0xFF, size >>> 8 & 0xFF, size & 0xFF, // sample_size
flags.isLeading << 2 | sample.flags.dependsOn, flags.isDependedOn << 6 | flags.hasRedundancy << 4 | flags.paddingValue << 1 | flags.isNonSync, flags.degradPrio & 0xF0 << 8, flags.degradPrio & 0x0F, // sample_flags
cts >>> 24 & 0xFF, cts >>> 16 & 0xFF, cts >>> 8 & 0xFF, cts & 0xFF // sample_composition_time_offset
], 12 + 16 * i); ], 12 + 16 * i);
} }
return MP4.box(MP4.types.trun, array); return MP4.box(MP4.types.trun, array);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -391,26 +391,30 @@ class MSEMediaController {
this.appendError = 0; this.appendError = 0;
} catch(err) { } catch(err) {
// in case any error occured while appending, put back segment in mp4segments table // in case any error occured while appending, put back segment in mp4segments table
//logger.error(`error while trying to append buffer:${err.message},try appending later`); logger.error(`error while trying to append buffer:${err.message},try appending later`);
this.mp4segments.unshift(segment); this.mp4segments.unshift(segment);
if (this.appendError) { // just discard QuotaExceededError for now, and wait for the natural browser buffer eviction
this.appendError++; //http://www.w3.org/TR/html5/infrastructure.html#quotaexceedederror
} else { if(err.code !== 22) {
this.appendError = 1; if (this.appendError) {
} this.appendError++;
var event = {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.BUFFER_APPEND_ERROR, frag: this.fragCurrent}; } else {
/* with UHD content, we could get loop of quota exceeded error until this.appendError = 1;
browser is able to evict some data from sourcebuffer. retrying help recovering this }
*/ var event = {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.BUFFER_APPEND_ERROR, frag: this.fragCurrent};
if (this.appendError > this.config.appendErrorMaxRetry) { /* with UHD content, we could get loop of quota exceeded error until
logger.log(`fail ${this.config.appendErrorMaxRetry} times to append segment in sourceBuffer`); browser is able to evict some data from sourcebuffer. retrying help recovering this
event.fatal = true; */
hls.trigger(Event.ERROR, event); if (this.appendError > this.config.appendErrorMaxRetry) {
this.state = State.ERROR; logger.log(`fail ${this.config.appendErrorMaxRetry} times to append segment in sourceBuffer`);
return; event.fatal = true;
} else { hls.trigger(Event.ERROR, event);
event.fatal = false; this.state = State.ERROR;
hls.trigger(Event.ERROR, event); return;
} else {
event.fatal = false;
hls.trigger(Event.ERROR, event);
}
} }
} }
this.state = State.APPENDING; this.state = State.APPENDING;

View File

@ -54,7 +54,7 @@ class Hls {
manifestLoadingRetryDelay: 1000, manifestLoadingRetryDelay: 1000,
// fpsDroppedMonitoringPeriod: 5000, // fpsDroppedMonitoringPeriod: 5000,
// fpsDroppedMonitoringThreshold: 0.2, // fpsDroppedMonitoringThreshold: 0.2,
appendErrorMaxRetry: 200, appendErrorMaxRetry: 3,
loader: XhrLoader, loader: XhrLoader,
fLoader: undefined, fLoader: undefined,
pLoader: undefined, pLoader: undefined,

View File

@ -152,6 +152,7 @@ class MP4 {
payload = Array.prototype.slice.call(arguments, 1), payload = Array.prototype.slice.call(arguments, 1),
size = 0, size = 0,
i = payload.length, i = payload.length,
len = i,
result, result,
view; view;
// calculate the total size we need to allocate // calculate the total size we need to allocate
@ -163,7 +164,7 @@ class MP4 {
view.setUint32(0, result.byteLength); view.setUint32(0, result.byteLength);
result.set(type, 4); result.set(type, 4);
// copy the payload into the result // copy the payload into the result
for (i = 0, size = 8; i < payload.length; i++) { for (i = 0, size = 8; i < len; i++) {
result.set(payload[i], size); result.set(payload[i], size);
size += payload[i].byteLength; size += payload[i].byteLength;
} }
@ -341,7 +342,9 @@ class MP4 {
0xE0 | track.sps.length // 3bit reserved (111) + numOfSequenceParameterSets 0xE0 | track.sps.length // 3bit reserved (111) + numOfSequenceParameterSets
].concat(sps).concat([ ].concat(sps).concat([
track.pps.length // numOfPictureParameterSets track.pps.length // numOfPictureParameterSets
]).concat(pps))); // "PPS" ]).concat(pps))), // "PPS"
width = track.width,
height = track.height;
//console.log('avcc:' + Hex.hexDump(avcc)); //console.log('avcc:' + Hex.hexDump(avcc));
return MP4.box(MP4.types.avc1, new Uint8Array([ return MP4.box(MP4.types.avc1, new Uint8Array([
0x00, 0x00, 0x00, // reserved 0x00, 0x00, 0x00, // reserved
@ -352,10 +355,10 @@ class MP4 {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, // pre_defined 0x00, 0x00, 0x00, 0x00, // pre_defined
(track.width >> 8) & 0xFF, (width >> 8) & 0xFF,
track.width & 0xff, // width width & 0xff, // width
(track.height >> 8) & 0xFF, (height >> 8) & 0xFF,
track.height & 0xff, // height height & 0xff, // height
0x00, 0x48, 0x00, 0x00, // horizresolution 0x00, 0x48, 0x00, 0x00, // horizresolution
0x00, 0x48, 0x00, 0x00, // vertresolution 0x00, 0x48, 0x00, 0x00, // vertresolution
0x00, 0x00, 0x00, 0x00, // reserved 0x00, 0x00, 0x00, 0x00, // reserved
@ -380,17 +383,18 @@ class MP4 {
} }
static esds(track) { static esds(track) {
var configlen = track.config.length;
return new Uint8Array([ return new Uint8Array([
0x00, // version 0 0x00, // version 0
0x00, 0x00, 0x00, // flags 0x00, 0x00, 0x00, // flags
0x03, // descriptor_type 0x03, // descriptor_type
0x17+track.config.length, // length 0x17+configlen, // length
0x00, 0x01, //es_id 0x00, 0x01, //es_id
0x00, // stream_priority 0x00, // stream_priority
0x04, // descriptor_type 0x04, // descriptor_type
0x0f+track.config.length, // length 0x0f+configlen, // length
0x40, //codec : mpeg4_audio 0x40, //codec : mpeg4_audio
0x15, // stream_type 0x15, // stream_type
0x00, 0x00, 0x00, // buffer_size 0x00, 0x00, 0x00, // buffer_size
@ -398,23 +402,24 @@ class MP4 {
0x00, 0x00, 0x00, 0x00, // avgBitrate 0x00, 0x00, 0x00, 0x00, // avgBitrate
0x05 // descriptor_type 0x05 // descriptor_type
].concat([track.config.length]).concat(track.config).concat([0x06, 0x01, 0x02])); // GASpecificConfig)); // length + audio config descriptor ].concat([configlen]).concat(track.config).concat([0x06, 0x01, 0x02])); // GASpecificConfig)); // length + audio config descriptor
} }
static mp4a(track) { static mp4a(track) {
return MP4.box(MP4.types.mp4a, new Uint8Array([ var audiosamplerate = track.audiosamplerate;
0x00, 0x00, 0x00, // reserved return MP4.box(MP4.types.mp4a, new Uint8Array([
0x00, 0x00, 0x00, // reserved 0x00, 0x00, 0x00, // reserved
0x00, 0x01, // data_reference_index 0x00, 0x00, 0x00, // reserved
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // data_reference_index
0x00, 0x00, 0x00, 0x00, // reserved 0x00, 0x00, 0x00, 0x00,
0x00, track.channelCount, // channelcount 0x00, 0x00, 0x00, 0x00, // reserved
0x00, 0x10, // sampleSize:16bits 0x00, track.channelCount, // channelcount
0x00, 0x00, 0x00, 0x00, // reserved2 0x00, 0x10, // sampleSize:16bits
(track.audiosamplerate >> 8) & 0xFF, 0x00, 0x00, 0x00, 0x00, // reserved2
track.audiosamplerate & 0xff, // (audiosamplerate >> 8) & 0xFF,
0x00, 0x00]), audiosamplerate & 0xff, //
MP4.box(MP4.types.esds, MP4.esds(track))); 0x00, 0x00]),
MP4.box(MP4.types.esds, MP4.esds(track)));
} }
static stsd(track) { static stsd(track) {
@ -426,20 +431,24 @@ class MP4 {
} }
static tkhd(track) { static tkhd(track) {
var id = track.id,
duration = track.duration,
width = track.width,
height = track.height;
return MP4.box(MP4.types.tkhd, new Uint8Array([ return MP4.box(MP4.types.tkhd, new Uint8Array([
0x00, // version 0 0x00, // version 0
0x00, 0x00, 0x07, // flags 0x00, 0x00, 0x07, // flags
0x00, 0x00, 0x00, 0x00, // creation_time 0x00, 0x00, 0x00, 0x00, // creation_time
0x00, 0x00, 0x00, 0x00, // modification_time 0x00, 0x00, 0x00, 0x00, // modification_time
(track.id >> 24) & 0xFF, (id >> 24) & 0xFF,
(track.id >> 16) & 0xFF, (id >> 16) & 0xFF,
(track.id >> 8) & 0xFF, (id >> 8) & 0xFF,
track.id & 0xFF, // track_ID id & 0xFF, // track_ID
0x00, 0x00, 0x00, 0x00, // reserved 0x00, 0x00, 0x00, 0x00, // reserved
(track.duration >> 24), (duration >> 24),
(track.duration >> 16) & 0xFF, (duration >> 16) & 0xFF,
(track.duration >> 8) & 0xFF, (duration >> 8) & 0xFF,
track.duration & 0xFF, // duration duration & 0xFF, // duration
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, // reserved 0x00, 0x00, 0x00, 0x00, // reserved
0x00, 0x00, // layer 0x00, 0x00, // layer
@ -455,25 +464,26 @@ class MP4 {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, // transformation: unity matrix 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix
(track.width >> 8) & 0xFF, (width >> 8) & 0xFF,
track.width & 0xFF, width & 0xFF,
0x00, 0x00, // width 0x00, 0x00, // width
(track.height >> 8) & 0xFF, (height >> 8) & 0xFF,
track.height & 0xFF, height & 0xFF,
0x00, 0x00 // height 0x00, 0x00 // height
])); ]));
} }
static traf(track,baseMediaDecodeTime) { static traf(track,baseMediaDecodeTime) {
var sampleDependencyTable = MP4.sdtp(track); var sampleDependencyTable = MP4.sdtp(track),
id = track.id;
return MP4.box(MP4.types.traf, return MP4.box(MP4.types.traf,
MP4.box(MP4.types.tfhd, new Uint8Array([ MP4.box(MP4.types.tfhd, new Uint8Array([
0x00, // version 0 0x00, // version 0
0x00, 0x00, 0x00, // flags 0x00, 0x00, 0x00, // flags
(track.id >> 24), (id >> 24),
(track.id >> 16) & 0XFF, (id >> 16) & 0XFF,
(track.id >> 8) & 0XFF, (id >> 8) & 0XFF,
(track.id & 0xFF) // track_ID (id & 0xFF) // track_ID
])), ])),
MP4.box(MP4.types.tfdt, new Uint8Array([ MP4.box(MP4.types.tfdt, new Uint8Array([
0x00, // version 0 0x00, // version 0
@ -505,13 +515,14 @@ class MP4 {
} }
static trex(track) { static trex(track) {
var id = track.id;
return MP4.box(MP4.types.trex, new Uint8Array([ return MP4.box(MP4.types.trex, new Uint8Array([
0x00, // version 0 0x00, // version 0
0x00, 0x00, 0x00, // flags 0x00, 0x00, 0x00, // flags
(track.id >> 24), (id >> 24),
(track.id >> 16) & 0XFF, (id >> 16) & 0XFF,
(track.id >> 8) & 0XFF, (id >> 8) & 0XFF,
(track.id & 0xFF), // track_ID (id & 0xFF), // track_ID
0x00, 0x00, 0x00, 0x01, // default_sample_description_index 0x00, 0x00, 0x00, 0x01, // default_sample_description_index
0x00, 0x00, 0x00, 0x00, // default_sample_duration 0x00, 0x00, 0x00, 0x00, // default_sample_duration
0x00, 0x00, 0x00, 0x00, // default_sample_size 0x00, 0x00, 0x00, 0x00, // default_sample_size
@ -520,44 +531,50 @@ class MP4 {
} }
static trun(track, offset) { static trun(track, offset) {
var samples, sample, i, array; var samples= track.samples || [],
samples = track.samples || []; len = samples.length,
array = new Uint8Array(12 + (16 * samples.length)); arraylen = 12 + (16 * len),
offset += 8 + array.byteLength; array = new Uint8Array(arraylen),
i,sample,duration,size,flags,cts;
offset += 8 + arraylen;
array.set([ array.set([
0x00, // version 0 0x00, // version 0
0x00, 0x0f, 0x01, // flags 0x00, 0x0f, 0x01, // flags
(samples.length >>> 24) & 0xFF, (len >>> 24) & 0xFF,
(samples.length >>> 16) & 0xFF, (len >>> 16) & 0xFF,
(samples.length >>> 8) & 0xFF, (len >>> 8) & 0xFF,
samples.length & 0xFF, // sample_count len & 0xFF, // sample_count
(offset >>> 24) & 0xFF, (offset >>> 24) & 0xFF,
(offset >>> 16) & 0xFF, (offset >>> 16) & 0xFF,
(offset >>> 8) & 0xFF, (offset >>> 8) & 0xFF,
offset & 0xFF // data_offset offset & 0xFF // data_offset
],0); ],0);
for (i = 0; i < samples.length; i++) { for (i = 0; i < len; i++) {
sample = samples[i]; sample = samples[i];
duration = sample.duration;
size = sample.size;
flags = sample.flags;
cts = sample.cts;
array.set([ array.set([
(sample.duration >>> 24) & 0xFF, (duration >>> 24) & 0xFF,
(sample.duration >>> 16) & 0xFF, (duration >>> 16) & 0xFF,
(sample.duration >>> 8) & 0xFF, (duration >>> 8) & 0xFF,
sample.duration & 0xFF, // sample_duration duration & 0xFF, // sample_duration
(sample.size >>> 24) & 0xFF, (size >>> 24) & 0xFF,
(sample.size >>> 16) & 0xFF, (size >>> 16) & 0xFF,
(sample.size >>> 8) & 0xFF, (size >>> 8) & 0xFF,
sample.size & 0xFF, // sample_size size & 0xFF, // sample_size
(sample.flags.isLeading << 2) | sample.flags.dependsOn, (flags.isLeading << 2) | sample.flags.dependsOn,
(sample.flags.isDependedOn << 6) | (flags.isDependedOn << 6) |
(sample.flags.hasRedundancy << 4) | (flags.hasRedundancy << 4) |
(sample.flags.paddingValue << 1) | (flags.paddingValue << 1) |
sample.flags.isNonSync, flags.isNonSync,
sample.flags.degradPrio & 0xF0 << 8, flags.degradPrio & 0xF0 << 8,
sample.flags.degradPrio & 0x0F, // sample_flags flags.degradPrio & 0x0F, // sample_flags
(sample.cts >>> 24) & 0xFF, (cts >>> 24) & 0xFF,
(sample.cts >>> 16) & 0xFF, (cts >>> 16) & 0xFF,
(sample.cts >>> 8) & 0xFF, (cts >>> 8) & 0xFF,
sample.cts & 0xFF // sample_composition_time_offset cts & 0xFF // sample_composition_time_offset
],12+16*i); ],12+16*i);
} }
return MP4.box(MP4.types.trun, array); return MP4.box(MP4.types.trun, array);

View File

@ -32,14 +32,14 @@
"iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0" "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0"
}, },
"ignore": [], "ignore": [],
"homepage": "https://github.com/polymerelements/paper-ripple", "homepage": "https://github.com/PolymerElements/paper-ripple",
"_release": "1.0.5", "_release": "1.0.5",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "v1.0.5", "tag": "v1.0.5",
"commit": "d72e7a9a8ab518b901ed18dde492df3b87a93be5" "commit": "d72e7a9a8ab518b901ed18dde492df3b87a93be5"
}, },
"_source": "git://github.com/polymerelements/paper-ripple.git", "_source": "git://github.com/PolymerElements/paper-ripple.git",
"_target": "^1.0.0", "_target": "^1.0.0",
"_originalSource": "polymerelements/paper-ripple" "_originalSource": "PolymerElements/paper-ripple"
} }