UNPKG

mp4box

Version:

JavaScript version of GPAC's MP4Box tool

488 lines (456 loc) 14.5 kB
/* * Copyright (c) Telecom ParisTech/TSI/MM/GPAC Cyril Concolato * License: BSD-3-Clause (see LICENSE file) */ BoxParser.Box.prototype.writeHeader = function(stream, msg) { this.size += 8; if (this.size > MAX_SIZE) { this.size += 8; } Log.d("BoxWriter", "Writing box "+this.type+" of size: "+this.size+" at position "+stream.position+(msg || "")); if (this.size > MAX_SIZE) { stream.writeUint32(1); } else { this.sizePosition = stream.position; stream.writeUint32(this.size); } stream.writeString(this.type, null, 4); if (this.size > MAX_SIZE) { stream.writeUint64(this.size); } } BoxParser.FullBox.prototype.writeHeader = function(stream) { this.size += 4; BoxParser.Box.prototype.writeHeader.call(this, stream, " v="+this.version+" f="+this.flags); stream.writeUint8(this.version); stream.writeUint24(this.flags); } BoxParser.Box.prototype.write = function(stream) { if (this.type === "mdat") { /* TODO: fix this */ if (this.data) { this.size = this.data.length; this.writeHeader(stream); stream.writeUint8Array(this.data); } } else { this.size = this.data.length; this.writeHeader(stream); stream.writeUint8Array(this.data); } } BoxParser.ContainerBox.prototype.write = function(stream) { this.size = 0; this.writeHeader(stream); for (var i=0; i<this.boxes.length; i++) { if (this.boxes[i]) { this.boxes[i].write(stream); this.size += this.boxes[i].size; } } /* adjusting the size, now that all sub-boxes are known */ Log.d("BoxWriter", "Adjusting box "+this.type+" with new size "+this.size); stream.adjustUint32(this.sizePosition, this.size); } BoxParser.TrackReferenceTypeBox.prototype.write = function(stream) { this.size = this.track_ids.length*4; this.writeHeader(stream); stream.writeUint32Array(this.track_ids); } BoxParser.ftypBox.prototype.write = function(stream) { this.size = 8+4*this.compatible_brands.length; this.writeHeader(stream); stream.writeString(this.major_brand, null, 4); stream.writeUint32(this.minor_version); for (var i = 0; i < this.compatible_brands.length; i++) { stream.writeString(this.compatible_brands[i], null, 4); } } BoxParser.mvhdBox.prototype.write = function(stream) { this.version = 0; this.flags = 0; this.size = 23*4+2*2; this.writeHeader(stream); stream.writeUint32(this.creation_time); stream.writeUint32(this.modification_time); stream.writeUint32(this.timescale); stream.writeUint32(this.duration); stream.writeUint32(this.rate); stream.writeUint16(this.volume<<8); stream.writeUint16(0); stream.writeUint32(0); stream.writeUint32(0); stream.writeUint32Array(this.matrix); stream.writeUint32(0); stream.writeUint32(0); stream.writeUint32(0); stream.writeUint32(0); stream.writeUint32(0); stream.writeUint32(0); stream.writeUint32(this.next_track_id); } BoxParser.tkhdBox.prototype.write = function(stream) { this.version = 0; //this.flags = 0; this.size = 4*18+2*4; this.writeHeader(stream); stream.writeUint32(this.creation_time); stream.writeUint32(this.modification_time); stream.writeUint32(this.track_id); stream.writeUint32(0); stream.writeUint32(this.duration); stream.writeUint32(0); stream.writeUint32(0); stream.writeInt16(this.layer); stream.writeInt16(this.alternate_group); stream.writeInt16(this.volume<<8); stream.writeUint16(0); stream.writeInt32Array(this.matrix); stream.writeUint32(this.width); stream.writeUint32(this.height); } BoxParser.mdhdBox.prototype.write = function(stream) { this.size = 4*4+2*2; this.flags = 0; this.version = 0; this.writeHeader(stream); stream.writeUint32(this.creation_time); stream.writeUint32(this.modification_time); stream.writeUint32(this.timescale); stream.writeUint32(this.duration); stream.writeUint16(this.language); stream.writeUint16(0); } BoxParser.hdlrBox.prototype.write = function(stream) { this.size = 5*4+this.name.length+1; this.version = 0; this.flags = 0; this.writeHeader(stream); stream.writeUint32(0); stream.writeString(this.handler, null, 4); stream.writeUint32(0); stream.writeUint32(0); stream.writeUint32(0); stream.writeCString(this.name); } BoxParser.stsdBox.prototype.write = function(stream) { var i; this.version = 0; this.flags = 0; this.size = 0; this.writeHeader(stream); stream.writeUint32(this.entries.length); this.size += 4; for (i = 0; i < this.entries.length; i++) { this.entries[i].write(stream); this.size += this.entries[i].size; } /* adjusting the size, now that all sub-boxes are known */ Log.d("BoxWriter", "Adjusting box "+this.type+" with new size "+this.size); stream.adjustUint32(this.sizePosition, this.size); } BoxParser.SampleEntry.prototype.writeHeader = function(stream) { this.size = 8; BoxParser.Box.prototype.writeHeader.call(this, stream); stream.writeUint8(0); stream.writeUint8(0); stream.writeUint8(0); stream.writeUint8(0); stream.writeUint8(0); stream.writeUint8(0); stream.writeUint16(this.data_reference_index); } BoxParser.SampleEntry.prototype.writeFooter = function(stream) { for (var i=0; i<this.boxes.length; i++) { this.boxes[i].write(stream); this.size += this.boxes[i].size; } Log.d("BoxWriter", "Adjusting box "+this.type+" with new size "+this.size); stream.adjustUint32(this.sizePosition, this.size); } BoxParser.SampleEntry.prototype.write = function(stream) { this.writeHeader(stream); this.writeFooter(stream); } BoxParser.VisualSampleEntry.prototype.write = function(stream) { this.writeHeader(stream); this.size += 2*7+6*4+32; stream.writeUint16(0); stream.writeUint16(0); stream.writeUint32(0); stream.writeUint32(0); stream.writeUint32(0); stream.writeUint16(this.width); stream.writeUint16(this.height); stream.writeUint32(this.horizresolution); stream.writeUint32(this.vertresolution); stream.writeUint32(0); stream.writeUint16(this.frame_count); stream.writeString(this.compressorname, null, 32); stream.writeUint16(this.depth); stream.writeInt16(-1); this.writeFooter(stream); } BoxParser.AudioSampleEntry.prototype.write = function(stream) { this.writeHeader(stream); this.size += 2*4+3*4; stream.writeUint32(0); stream.writeUint32(0); stream.writeUint16(this.channel_count); stream.writeUint16(this.samplesize); stream.writeUint16(0); stream.writeUint16(0); stream.writeUint32(this.samplerate<<16); this.writeFooter(stream); } BoxParser.avcCBox.prototype.write = function(stream) { var i; this.size = 7; for (i = 0; i < this.SPS.length; i++) { this.size += 2+this.SPS[i].length; } for (i = 0; i < this.PPS.length; i++) { this.size += 2+this.PPS[i].length; } if (this.ext) { this.size += this.ext.length; } this.writeHeader(stream); stream.writeUint8(this.configurationVersion); stream.writeUint8(this.AVCProfileIndication); stream.writeUint8(this.profile_compatibility); stream.writeUint8(this.AVCLevelIndication); stream.writeUint8(this.lengthSizeMinusOne + (63<<2)); stream.writeUint8(this.SPS.length + (7<<5)); for (i = 0; i < this.SPS.length; i++) { stream.writeUint16(this.SPS[i].length); stream.writeUint8Array(this.SPS[i]); } stream.writeUint8(this.PPS.length); for (i = 0; i < this.PPS.length; i++) { stream.writeUint16(this.PPS[i].length); stream.writeUint8Array(this.PPS[i]); } if (this.ext) { stream.writeUint8Array(this.ext); } } BoxParser.cttsBox.prototype.write = function(stream) { var i; this.version = 1; this.flags = 0; this.size = 4+8*this.sample_counts.length; this.writeHeader(stream); stream.writeUint32(this.sample_counts.length); for(i=0; i<this.sample_counts.length; i++) { stream.writeUint32(this.sample_counts[i]); stream.writeInt32(this.sample_offsets[i]); /* signed */ } } BoxParser.cslgBox.prototype.write = function(stream) { var i; this.version = 0; this.flags = 0; this.size = 4*5; this.writeHeader(stream); stream.writeInt32(this.compositionToDTSShift); stream.writeInt32(this.leastDecodeToDisplayDelta); stream.writeInt32(this.greatestDecodeToDisplayDelta); stream.writeInt32(this.compositionStartTime); stream.writeInt32(this.compositionEndTime); } BoxParser.sttsBox.prototype.write = function(stream) { var i; this.version = 0; this.flags = 0; this.size = 4+8*this.sample_counts.length; this.writeHeader(stream); stream.writeUint32(this.sample_counts.length); for(i=0; i<this.sample_counts.length; i++) { stream.writeUint32(this.sample_counts[i]); stream.writeUint32(this.sample_deltas[i]); } } BoxParser.stssBox.prototype.write = function(stream) { this.version = 0; this.flags = 0; this.size = 4+4*this.sample_numbers.length; this.writeHeader(stream); stream.writeUint32(this.sample_numbers.length); stream.writeUint32Array(this.sample_numbers); } BoxParser.stshBox.prototype.write = function(stream) { var i; this.version = 0; this.flags = 0; this.size = 4+8*this.shadowed_sample_numbers.length; this.writeHeader(stream); stream.writeUint32(this.shadowed_sample_numbers.length); for(i=0; i<this.shadowed_sample_numbers.length; i++) { stream.writeUint32(this.shadowed_sample_numbers[i]); stream.writeUint32(this.sync_sample_numbers[i]); } } BoxParser.stcoBox.prototype.write = function(stream) { this.version = 0; this.flags = 0; this.size = 4+4*this.chunk_offsets.length; this.writeHeader(stream); stream.writeUint32(this.chunk_offsets.length); stream.writeUint32Array(this.chunk_offsets); } BoxParser.co64Box.prototype.write = function(stream) { var i; this.version = 0; this.flags = 0; this.size = 4+8*this.chunk_offsets.length; this.writeHeader(stream); stream.writeUint32(this.chunk_offsets.length); for(i=0; i<this.chunk_offsets.length; i++) { stream.writeUint64(this.chunk_offsets[i]); } } BoxParser.stscBox.prototype.write = function(stream) { var i; this.version = 0; this.flags = 0; this.size = 4+12*this.first_chunk.length; this.writeHeader(stream); stream.writeUint32(this.first_chunk.length); for(i=0; i<this.first_chunk.length; i++) { stream.writeUint32(this.first_chunk[i]); stream.writeUint32(this.samples_per_chunk[i]); stream.writeUint32(this.sample_description_index[i]); } } BoxParser.stszBox.prototype.write = function(stream) { var i; this.version = 0; this.flags = 0; this.size = 8+12*this.sample_sizes.length; this.writeHeader(stream); stream.writeUint32(0); stream.writeUint32(this.sample_sizes.length); stream.writeUint32Array(this.sample_sizes); } BoxParser.mehdBox.prototype.write = function(stream) { this.version = 0; this.flags = 0; this.size = 4; this.writeHeader(stream); stream.writeUint32(this.fragment_duration); } BoxParser.trexBox.prototype.write = function(stream) { this.version = 0; this.flags = 0; this.size = 4*5; this.writeHeader(stream); stream.writeUint32(this.track_id); stream.writeUint32(this.default_sample_description_index); stream.writeUint32(this.default_sample_duration); stream.writeUint32(this.default_sample_size); stream.writeUint32(this.default_sample_flags); } BoxParser.mfhdBox.prototype.write = function(stream) { this.version = 0; this.flags = 0; this.size = 4; this.writeHeader(stream); stream.writeUint32(this.sequence_number); } BoxParser.tfhdBox.prototype.write = function(stream) { this.version = 0; this.size = 4; if (this.flags & BoxParser.TFHD_FLAG_BASE_OFFSET) { this.size += 8; } if (this.flags & BoxParser.TFHD_FLAG_SAMPLE_DESC) { this.size += 4; } if (this.flags & BoxParser.TFHD_FLAG_SAMPLE_DUR) { this.size += 4; } if (this.flags & BoxParser.TFHD_FLAG_SAMPLE_SIZE) { this.size += 4; } if (this.flags & BoxParser.TFHD_FLAG_SAMPLE_FLAGS) { this.size += 4; } this.writeHeader(stream); stream.writeUint32(this.track_id); if (this.flags & BoxParser.TFHD_FLAG_BASE_OFFSET) { stream.writeUint64(this.base_data_offset); } if (this.flags & BoxParser.TFHD_FLAG_SAMPLE_DESC) { stream.writeUint32(this.default_sample_description_index); } if (this.flags & BoxParser.TFHD_FLAG_SAMPLE_DUR) { stream.writeUint32(this.default_sample_duration); } if (this.flags & BoxParser.TFHD_FLAG_SAMPLE_SIZE) { stream.writeUint32(this.default_sample_size); } if (this.flags & BoxParser.TFHD_FLAG_SAMPLE_FLAGS) { stream.writeUint32(this.default_sample_flags); } } BoxParser.trunBox.prototype.write = function(stream) { this.version = 0; this.size = 4; if (this.flags & BoxParser.TRUN_FLAGS_DATA_OFFSET) { this.size += 4; } if (this.flags & BoxParser.TRUN_FLAGS_FIRST_FLAG) { this.size += 4; } if (this.flags & BoxParser.TRUN_FLAGS_DURATION) { this.size += 4*this.sample_duration.length; } if (this.flags & BoxParser.TRUN_FLAGS_SIZE) { this.size += 4*this.sample_size.length; } if (this.flags & BoxParser.TRUN_FLAGS_FLAGS) { this.size += 4*this.sample_flags.length; } if (this.flags & BoxParser.TRUN_FLAGS_CTS_OFFSET) { this.size += 4*this.sample_composition_time_offset.length; } this.writeHeader(stream); stream.writeUint32(this.sample_count); if (this.flags & BoxParser.TRUN_FLAGS_DATA_OFFSET) { this.data_offset_position = stream.position; stream.writeInt32(this.data_offset); //signed } if (this.flags & BoxParser.TRUN_FLAGS_FIRST_FLAG) { stream.writeUint32(this.first_sample_flags); } for (var i = 0; i < this.sample_count; i++) { if (this.flags & BoxParser.TRUN_FLAGS_DURATION) { stream.writeUint32(this.sample_duration[i]); } if (this.flags & BoxParser.TRUN_FLAGS_SIZE) { stream.writeUint32(this.sample_size[i]); } if (this.flags & BoxParser.TRUN_FLAGS_FLAGS) { stream.writeUint32(this.sample_flags[i]); } if (this.flags & BoxParser.TRUN_FLAGS_CTS_OFFSET) { if (this.version === 0) { stream.writeUint32(this.sample_composition_time_offset[i]); } else { stream.writeInt32(this.sample_composition_time_offset[i]); //signed } } } } BoxParser.tfdtBox.prototype.write = function(stream) { this.version = 0; this.flags = 0; this.size = 4; this.writeHeader(stream); if (this.version == 1) { stream.writeUint64(this.baseMediaDecodeTime); } else { stream.writeUint32(this.baseMediaDecodeTime); } }