diff --git a/src/box-codecs.js b/src/box-codecs.js index 24743823..0d76494b 100644 --- a/src/box-codecs.js +++ b/src/box-codecs.js @@ -263,3 +263,17 @@ BoxParser.av01SampleEntry.prototype.getCodec = function() { // TODO need to parse the SH to find color config return baseCodec+"."+this.av1C.seq_profile+"."+level+(this.av1C.seq_tier_0?"H":"M")+"."+bitdepth;//+"."+this.av1C.monochrome+"."+this.av1C.chroma_subsampling_x+""+this.av1C.chroma_subsampling_y+""+this.av1C.chroma_sample_position; } + +BoxParser.avs3SampleEntry.prototype.getCodec = function() { + var baseCodec = BoxParser.SampleEntry.prototype.getCodec.call(this); + return baseCodec + '.' + (this.av3c.profile_id ? this.av3c.profile_id.get().toString(16) : 'XX') + + '.' + (this.av3c.level_id ? this.av3c.level_id.get().toString(16) : 'XX'); +} + +/* TODO.AVS3A - activate whem test streams are available +BoxParser.a3asSampleEntry.prototype.getCodec = */ +BoxParser.av3aSampleEntry.prototype.getCodec = function() { + var baseCodec = BoxParser.SampleEntry.prototype.getCodec.call(this); + var codec_id_str = this.dca3.audio_codec_id ? ("" +this.dca3.audio_codec_id.get()).padStart(2, '0') : 'XX'; + return baseCodec + '.' + codec_id_str; +} diff --git a/src/parsing/AVS-utils.js b/src/parsing/AVS-utils.js new file mode 100644 index 00000000..6c6999ea --- /dev/null +++ b/src/parsing/AVS-utils.js @@ -0,0 +1,281 @@ +/* +* Copyright (c) 2024. Paul Higgs +* License: BSD-3-Clause (see LICENSE file) +*/ + +function HexadecimalValue(value, descriptionFn) { + this.value = value; + this.description = (typeof descriptionFn == "function") ? descriptionFn(value) : null; +} +HexadecimalValue.prototype.toString = function() { + return "0x" + this.value.toString(16) + + (this.description ? " (" + this.description + ")" : ""); +} +HexadecimalValue.prototype.get = function() { + return this.value; +} + + +function BinaryValue(value, bits, descriptionFn) { + this.value = value; + this.bits = bits; + this.description = (typeof descriptionFn == "function") ? descriptionFn(value) : null; +} +BinaryValue.prototype.toString = function() { + var i, res = "b"; + for (i=this.bits; i>0; i--) + res += (this.value & (1 << (i-1)) ? "1" : "0"); + return res + (this.description ? " (" + this.description + ")" : ""); +} +BinaryValue.prototype.get = function() { + return this.value; +} + +function DescribedValue(value, descriptionFn) { + this.value = value; + this.description = (typeof descriptionFn == "function") ? descriptionFn(value) : null; +} +DescribedValue.prototype.toString = function() { + return this.value + (this.description ? " (" + this.description + ")" : ""); +} +DescribedValue.prototype.get = function() { + return this.value; +} + +/** + * reads bits and bytes from a buffer that may not contain aligned values + */ +function phBitBuffer(stream) { + var isLocalBigEndian = function () { + var buf = new ArrayBuffer(4); + var u32data = new Uint32Array(buf); + var u8data = new Uint8Array(buf); + u32data[0] = 0xcafebabe; + return u8data[3] === 0xca; + }; + this.OSisLittleEndian = !isLocalBigEndian(); + this._big_endian = true; + this._buffer = []; + this._buffer_size = 0; + + this._state={}; + this._state.rbyte = 0; + this._state.rbit = 0; + this._state.end = this._state.wbyte = this._buffer_size; + this._state.wbit = 0; + + if (stream != undefined) { + var stream_length = stream.getLength(); + var i, buf=[]; + for (i=0; i> (this._big_endian ? (7 - this._state.rbit) : this._state.rbit)) & 0x01; + if (++this._state.rbit > 7) { + this._state.rbyte++; + this._state.rbit = 0; + } + return bit; +}; +phBitBuffer.prototype.peekBit = function() { + //! Read the next bit but don't advance the read pointer. + if (this._read_error || this.endOfRead()) { + this._read_error = true; + return 0; + } + var bit = (this._buffer[this._state.rbyte] >> (this._big_endian ? (7 - this._state.rbit) : this._state.rbit)) & 0x01; + return bit; +}; +phBitBuffer.prototype.endOfRead = function() { + return this._state.rbyte == this._state.wbyte && this._state.rbit == this._state.wbit; +}; +phBitBuffer.prototype.getBool = function() { + return this.getBit() != 0; +}; +phBitBuffer.prototype.rdb = function(bytes) { + var i, res, ff=0xFFFFFFFFFFFFFFFF; + if (this._read_error) + return ff; + if (this._state.rbit==0) { + // Read buffer is byte aligned. Most common case. + if (this._state.rbyte + bytes > this._state.wbyte) { + // Not enough bytes to read. + this._read_error = true; + return ff; + } + else { + for (res=0, i=0; i this.currentWriteBitOffset()) { + // Not enough bytes to read. + this._read_error = true; + return ff; + } + else { + for (res=0, i=0; i> (8 - this._state.rbit))); + else + res = (res << 8) + ((_buffer[_state.rbyte] >> _state.rbit) | (_buffer[_state.rbyte + 1] << (8 - _state.rbit))); + this._state.rbyte++; + } + return res; + } + } +}; +phBitBuffer.prototype.currentReadByteOffset = function() {return this._state.rbyte;}; +phBitBuffer.prototype.currentReadBitOffset = function() {return 8 * this._state.rbyte + this._state.rbit;}; +phBitBuffer.prototype.currentWriteByteOffset = function() {return this._state.wbyte;}; +phBitBuffer.prototype.currentWriteBitOffset = function() {return 8 * this._state.wbyte + this._state.wbit;}; +phBitBuffer.prototype.bitsRemaining = function() {return currentWriteBitOffset() - currentReadBitOffset();}; +phBitBuffer.prototype.getUint8 = function() { return this.rdb(1); }; + +phBitBuffer.prototype.getUint16 = function() { + return this._big_endian ? this.GetUInt16BE(this.rdb(2)) : this.GetUInt16LE(this.rdb(2)); +}; +phBitBuffer.prototype.ByteSwap16 = function(x) { return (x << 8) | (x >> 8); }; +phBitBuffer.prototype.CondByteSwap16BE = function(val) { return this.OSisLittleEndian ? this.ByteSwap16(val) : val; }; +phBitBuffer.prototype.CondByteSwap16LE = function(val) { return this.OSisLittleEndian ? val : this.ByteSwap16(val); }; +phBitBuffer.prototype.GetUInt16BE = function(val) { return this.CondByteSwap16BE(val); }; +phBitBuffer.prototype.GetUInt16LE = function(val) { return this.CondByteSwap16LE(val); }; + + +phBitBuffer.prototype.getUint24 = function() { return this._big_endian ? this.GetUInt24BE(this.rdb(3)) : this.GetUInt24LE(this.rdb(3)); }; +phBitBuffer.prototype.ByteSwap24 = function(x) { return ((x & 0xFF0000) >> 16) | (x & 0xFF00) | (x & 0xFF << 16); }; +phBitBuffer.prototype.CondByteSwap24BE = function(val) { return this.OSisLittleEndian ? this.ByteSwap24(val) : val; }; +phBitBuffer.prototype.CondByteSwap24LE = function(val) { return this.OSisLittleEndian ? val : this.ByteSwap24(val); }; +phBitBuffer.prototype.GetUInt24BE = function(val) { return this.CondByteSwap24BE(val); }; +phBitBuffer.prototype.GetUInt24LE =function(val) { return this.CondByteSwap24LE(val); }; + +phBitBuffer.prototype.getUint32 = function() { return this._big_endian ? this.GetUInt32BE(this.rdb(4)) : this.GetUInt32LE(this.rdb(4)); }; +phBitBuffer.prototype.ByteSwap32 = function(x) { return (x << 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x >> 24); }; +phBitBuffer.prototype.CondByteSwap32BE = function(val) { return this.OSisLittleEndian ? this.ByteSwap32(val) : val; }; +phBitBuffer.prototype.CondByteSwap32LE = function(val) { return this.OSisLittleEndian ? val : this.ByteSwap32(val); }; +phBitBuffer.prototype.GetUInt32BE = function(val) { return this.CondByteSwap32BE(val); }; +phBitBuffer.prototype.GetUInt32LE =function(val) { return this.CondByteSwap32LE(val); }; + +phBitBuffer.prototype.getBits = function(bits) { + // No read if read error is already set or not enough bits to read. + if (this._read_error || this.currentReadBitOffset() + bits > this.currentWriteBitOffset()) { + this._read_error = true; + return 0; + } + var val = 0; + if (this._big_endian) { + // Read leading bits up to byte boundary + while (bits > 0 && this._state.rbit != 0) { + val = (val << 1) | this.getBit(); + --bits; + } + + // Read complete bytes + while (bits > 7) { + val = (val << 8) | this._buffer[this._state.rbyte++]; + bits -= 8; + } + + // Read trailing bits + while (bits > 0) { + val = (val << 1) | this.getBit(); + --bits; + } + } + else { + // Little endian decoding + var shift = 0; + + // Read leading bits up to byte boundary + while (bits > 0 && this._state.rbit != 0) { + val |= (this.getBit() << shift); + --bits; + shift++; + } + + // Read complete bytes + while (bits > 7) { + val |= this._buffer[this._state.rbyte++] << shift; + bits -= 8; + shift += 8; + } + + // Read trailing bits + while (bits > 0) { + val |= (this.getBit() << shift); + --bits; + shift++; + } + } + return (val); +}; +phBitBuffer.prototype.skipBits = function(bits) { + if (this._read_error) { + // Can't skip bits and bytes if read error is already set. + return false; + } + var rpos = 8 * this._state.rbyte + this._state.rbit + bits; + var wpos = 8 * this._state.wbyte + this._state.wbit; + if (rpos > wpos) { + this._state.rbyte = this._state.wbyte; + this._state.rbit = this._state.wbit; + this._read_error = true; + return false; + } + else { + this._state.rbyte = rpos >> 3; + this._state.rbit = rpos & 7; + return true; + } +}; +phBitBuffer.prototype.skipBit = function() { + return this.skipBits(1); +} + +phBitBuffer.prototype.getUE = function() { + // read in an unsigned Exp-Golomb code; + + if (this.getBit() == 1) + return 0; + else { + var zero_count=1; + while (this.peekBit() == 0) { + this.getBit(); + zero_count++; + } + var tmp_value = this.getBits(zero_count+1); + return tmp_value - 1; + } +}; + +phBitBuffer.prototype.byte_alignment = function() { + while ( !this._read_error && this._state.rbit != 0) + this.skipBit(); +} diff --git a/src/parsing/av3a.js b/src/parsing/av3a.js new file mode 100644 index 00000000..a60f3687 --- /dev/null +++ b/src/parsing/av3a.js @@ -0,0 +1,362 @@ +/* +* Copyright (c) 2024. Paul Higgs +* License: BSD-3-Clause (see LICENSE file) +*/ + +function AVS3Acodec(codec_id) { + var codecs = ["General High Rate", "Lossless", "General Full Rate"]; + return codec_id < codecs.length ? codecs[codec_id] : "undefined"; +} + +function AVS3Achannel_number(channel_number_index) { + var configs = ["Mono", "Stereo", "5.1", "7.1", "10.2", "22.2", "4.0/FOA", "5.1.2", "5.1.4", "7.1.2", "7.1.4", "3rd HOA", "2nd HOA"]; + return channel_number_index < configs.length ? configs[channel_number_index] : "undefined"; +} + +function AVS3Asampling_frequency(sampling_frequency_index) { + var frequencies = [192000, 96000, 48000, 44100, 32000, 24000, 22050, 16000, 8000]; + return sampling_frequency_index < frequencies.length ? frequencies[sampling_frequency_index]+"Hz" : "reserved"; +} + +function AVS3Aresolution(resolution) { + switch (resolution) { + case 0: return "8 bits/sample"; + case 1: return "16 bits/sample"; + case 2: return "24 bits/sample"; + } + return "reserved"; +} + +function AVS3Anntype(nn_type) { + switch (nn_type) { + case 0: return "basic neural network"; + case 1: return "low-complexity neural network"; + } + return "reserved"; +} + +function AVS3Acodingprofile(conding_profile) { + switch (conding_profile) { + case 0: return "basic framework"; + case 1: return "object metadata framework"; + case 2: return "HOA data coding framework"; + } + return "reserved"; +} + +function AVS3Atabularize(data) { + var res = ""; + var props = Object.getOwnPropertyNames(data) + if (props) props.forEach(function (val, idx, array) { + var fmt_val = ""; + if (Array.isArray(data[val])) { + for (var i = 0; i < data[val].length; i++) { + var hex = data[val][i].toString(16); + fmt_val += (hex.length === 1 ? "0"+hex : hex) ; + if (i%4 === 3) fmt_val += ' '; + } + } + else + fmt_val = data[val]; + res += "" + val + "" + fmt_val + ""; + }); + return "" + res + "
"; +} + + +/* TODO.AVS3A - activate whem test streams are available +var MakeFourCC = function(val) { + return String.fromCharCode(val >> 24, (val & 0x00ff0000) >> 16, (val & 0x0000ff00) >> 8, val & 0x000000ff); +} + +function parseCA3SpecificBox(stream) { + var BitBuffer = new phBitBuffer(); + BitBuffer.appendUint8(stream.getUint8()); + + this.data = {}; + audio_codec_id = BitBuffer.getBits(4); + this.data.audio_codec_id = new DescribedValue(audio_codec_id, AVS3Acodec); + switch (audio_codec_id) { + case 2: + // Avs3AudioGASpecificConfig() + this.data.sampling_frequency_index = BitBuffer.getBits(4); + BitBuffer.appendUint8(stream.getUint8()); + this.data.nn_type = new DescribedValue(BitBuffer.getBits(3), AVS3Anntype); + BitBuffer.skipBits(1); + this.data.content_type = BitBuffer.getBits(4); + if (this.data.content_type == 0) { + // channel based audio + BitBuffer.appendUint8(stream.getUint8()); + this.data.channel_number_index = BitBuffer.getBits(7); + BitBuffer.skipBits(1); + } + else if (this.data.content_type == 1) { + // object based audio + BitBuffer.appendUint8(stream.getUint8()); + this.data.num_objects = BitBuffer.getBits(7); + BitBuffer.skipBits(1); + } + else if (this.data.content_type == 2) { + // hybrid channel+object based audio + BitBuffer.appendUint8(stream.getUint8()); + this.data.channel_number_index = BitBuffer.getBits(7); + BitBuffer.skipBits(1); + BitBuffer.appendUint8(stream.getUint8()); + this.data.num_objects = BitBuffer.getBits(7); + BitBuffer.skipBits(1); + } + else if (this.data.content_type == 3) { + // high order ambisonics + BitBuffer.appendUint8(stream.getUint8()); + this.data.hoa_order = BitBuffer.getBits(4); + } + BitBuffer.appendUint8(stream.getUint8()); + BitBuffer.appendUint8(stream.getUint8()); + this.data.total_bitrate = BitBuffer.getUint16(); + if (this.data.content_type != 3) + BitBuffer.appendUint8(stream.getUint8()); + this.data.resolution = new DescribedValue(BitBuffer.getBits(2), AVS3resolution); + break; + case 0: + // Avs3AudioGHSpecificConfig() + this.data.sampling_frequency_index = BitBuffer.getBits(4); + BitBuffer.appendUint8(stream.getUint8()); + this.data.anc_data_index = BitBuffer.getBool(); + this.data.coding_profile = new DescribedValue(BitBuffer.getBits(3), AVS3codingprofile); + this.data.bitstream_type = BitBuffer.getBit(); + BitBuffer.appendUint8(stream.getUint8()); + this.data.channel_number_index = BitBuffer.getBits(7); + this.data.bitrate_index = BitBuffer.getBits(4); + BitBuffer.appendUint8(stream.getUint8()); + BitBuffer.appendUint8(stream.getUint8()); + this.data.raw_frame_length = BitBuffer.getUint16(); + BitBuffer.appendUint8(stream.getUint8()); + this.data.resolution = new DescribedValue(BitBuffer.getBits(2), AVS3resolution); + var addition_info_length1 = BitBuffer.getUint16(); + if (addition_info_length1 > 0) { + this.data.addition_info = []; + for (i=0; i 0) { + this.data.addition_info = []; + for (i=0; i 2) { + this.data.supermode_flag = BitBuffer.getBits(2); + this.data.couple_channel_config = BitBuffer.getUint8(); + this.data.PCAGroupmodeHeader = BitBuffer.getUint8(); + } + } + BitBuffer.byte_alignment(); +} +parseAASFHeader.prototype.toHTML = function() { + return AVS3Atabularize(this.data); +}; +*/ + +/* TODO.AVS3A - activate whem test streams are available +BoxParser.createBoxCtor("av3a", function(stream) { + this.config = new parseCA3SpecificBox(stream); +}); + +BoxParser.createBoxCtor("a3as", function(stream) { + this.config = new parseCA3SpecificBox(stream); + this.avs3_as_header = new parseAASFHeader(stream); +}); +*/ + +function parseAvs3AudioGASpecificConfig(BitBuffer) { + this.data = {}; + this.data.sampling_frequency_index = new DescribedValue(BitBuffer.getBits(4), AVS3Asampling_frequency); + this.data.nn_type = new DescribedValue(BitBuffer.getBits(3), AVS3Anntype); + BitBuffer.skipBits(1); + this.data.content_type = BitBuffer.getBits(4); + if (this.data.content_type == 0) { + this.data.channel_number_index = new DescribedValue(BitBuffer.getBits(7), AVS3Achannel_number); + BitBuffer.skipBits(1); + } + else if (this.data.content_type == 1) { + this.data.num_objects = BitBuffer.getBits(7); + BitBuffer.skipBits(1); + } + else if (this.data.content_type == 2) { + this.data.channel_number_index = new DescribedValue(BitBuffer.getBits(7), AVS3Achannel_number); + BitBuffer.skipBits(1); + this.data.num_objects = BitBuffer.getBits(7); + BitBuffer.skipBits(1); + } + else if (this.data.content_type == 3) { + this.data.hoa_order = BitBuffer.getBits(4); + } + this.data.total_bitrate = BitBuffer.getUint16(); + this.data.resolution = new DescribedValue(BitBuffer.getBits(2), AVS3Aresolution); +} +parseAvs3AudioGASpecificConfig.prototype.toHTML = function() { + return AVS3Atabularize(this.data); +}; + + +function parseAvs3AudioGHSpecificConfig(BitBuffer) { + this.data = {}; + this.data.sampling_frequency_index = BitBuffer.getBits(4); + this.data.anc_data_index = BitBuffer.getBit(); + this.data.coding_profile = new DescribedValue(BitBuffer.getBits(3), AVS3Acodingprofile); + this.data.bitstream_type = BitBuffer.getBits(1); + this.data.channel_number_index = BitBuffer.getBits(7); + this.data.bitrate_index = BitBuffer.getBits(4); + this.data.raw_frame_length = BitBuffer.getUint16(); + this.data.resolution = new DescribedValue(BitBuffer.getBits(2), AVS3Aresolution); + var addition_info_length = BitBuffer.getUint16(); + + if (addition_info_length > 0) { + this.data.addition_info=[]; + for (var i=0; i 0) { + this.data.addition_info=[]; + for (var i=0; i 3 ? ", " : "") + str; + }); + ret += "}"; + return ret; +}; + +function ReferencePictureList(list) { + this.list = list; + this.sets = []; +} +ReferencePictureList.prototype.push = function(set) { + this.sets.push(set); +}; +ReferencePictureList.prototype.toString = function() { + if (this.sets.length == 0) + return "(empty)"; + var l = []; + this.sets.forEach( function(set) { + l.push(set.toString()); + }); + return l.join(", "); +}; + +function WeightQuantMatrix( buffer ) { + this.WeightQuantMatrix4x4 = []; + this.WeightQuantMatrix8x8 = []; + + for (var sizeId=0; sizeId < 2; sizeId++) { + var this_size=[]; + var WQMSize = 1<<(sizeId+2); + for (var i=0; i2 ? ",\n" : "") + "8x8: " + JSON.stringify(this.WeightQuantMatrix8x8); + return str; +}; + + +// AVS3 video configuration box +BoxParser.createBoxCtor("av3c", function(stream) { + + var BitBuffer = new phBitBuffer(); + var MAIN_8 = 0x20, MAIN_10 = 0x22, HIGH_8 = 0x30, HIGH_10 = 0x32; + var RESERVED = "Reserved", FORBIDDEN = "Forbidden"; + var AVS3profiles = [ // Table B.1 of T/AI 109.2 + {profile:MAIN_8, description:"Main 8 bit"}, + {profile:MAIN_10, description:"Main 10 bit"}, + {profile:HIGH_8, description:"High 8 bit"}, + {profile:HIGH_10, description:"High 10 bit"}, + {profile:0x00, description:FORBIDDEN}, + ]; + var AVS3levels = [ // Table B.1 of T/AI 109.2 + {level:0x50, description:"8.0.30"}, + {level:0x52, description:"8.2.30"}, + {level:0x51, description:"8.4.30"}, + {level:0x53, description:"8.6.30"}, + {level:0x54, description:"8.0.60"}, + {level:0x56, description:"8.2.60"}, + {level:0x55, description:"8.4.60"}, + {level:0x57, description:"8.6.60"}, + {level:0x58, description:"8.0.120"}, + {level:0x5A, description:"8.2.120"}, + {level:0x59, description:"8.4.120"}, + {level:0x5B, description:"8.6.120"}, + {level:0x60, description:"10.0.30"}, + {level:0x62, description:"10.2.30"}, + {level:0x61, description:"10.4.30"}, + {level:0x63, description:"10.6.30"}, + {level:0x64, description:"10.0.60"}, + {level:0x66, description:"10.2.60"}, + {level:0x65, description:"10.4.60"}, + {level:0x67, description:"10.6.60"}, + {level:0x68, description:"10.0.120"}, + {level:0x6A, description:"10.2.120"}, + {level:0x69, description:"10.4.120"}, + {level:0x6B, description:"10.6.120"}, + {level:0x10, description:"2.0.15"}, + {level:0x12, description:"2.0.30"}, + {level:0x14, description:"2.0.60"}, + {level:0x20, description:"4.0.30"}, + {level:0x22, description:"4.0.60"}, + {level:0x40, description:"6.0.30"}, + {level:0x42, description:"6.2.30"}, + {level:0x41, description:"6.4.30"}, + {level:0x43, description:"6.6.30"}, + {level:0x44, description:"6.0.60"}, + {level:0x46, description:"6.2.60"}, + {level:0x45, description:"6.4.60"}, + {level:0x47, description:"6.6.60"}, + {level:0x48, description:"6.0.120"}, + {level:0x4A, description:"6.2.120"}, + {level:0x49, description:"6.4.120"}, + {level:0x4B, description:"6.6.120"}, + {level:0x00, description:FORBIDDEN}, + ]; + var AVS3precisions = [ // Table 45 of T/AI 109.2 + {precision: 1, description:"8-bit"}, + {precision: 2, description:"10-bit"}, + ]; + var AVS3framerates = [ + "", + "24/1.001", + "24", + "25", + "30/1.001", + "30", + "50", + "60/1.001", + "60", + "100", + "120", + "200", + "240", + "300", + "120/1.001" + ]; + var AVS3ratios = [ + "", + "1.0", + "4:3", + "16:9", + "2.21:1" + ]; + + var AVS3profile = function (profile) { + var t = AVS3profiles.find(function (e) { return e.profile == profile; }); + return t == undefined ? RESERVED : t.description; + }; + var AVS3level = function (level) { + var t = AVS3levels.find(function (e) { return e.level == level; }); + return t == undefined ? RESERVED : t.description; + }; + var se2value = function (codeNum) { + return (Math.pow(-1, codeNum+1) * Math.ceil(codeNum/2)); + }; + var AVS3precision = function (precision) { + var t = AVS3precisions.find(function (e) { return e.precision == precision}); + return t == undefined ? RESERVED : t.description; + } + var AVS3chroma = function (chroma) { + return chroma == 1 ? "4:2:0" : RESERVED; + } + var AVS3aspectratio = function (ratio) { + return (ratio == 0) ? FORBIDDEN : ((ratio >= AVS3ratios.length) ? RESERVED : AVS3ratios[ratio]); + } + var AVS3framerate = function (framerate) { + return (framerate == 0) ? FORBIDDEN : ((framerate >= AVS3framerates.length) ? RESERVED : AVS3framerates[framerate]+" fps"); + } + + this.configurationVersion = stream.readUint8(); + if (this.configurationVersion != 1) { + Log.error("av3c version "+this.configurationVersion+" not supported"); + return; + } + var buf=[], sequence_header_length = stream.readUint16(); + for (var i=0; i 0) + this_pic.sign_delta_doi = BitBuffer.getBit(); + } + this_set.push(this_pic); + } + return this_set; + }; + + this.num_ref_pic_list_set0 = BitBuffer.getUE(); + this.rpl0 = new ReferencePictureList(0); + for (var j=0; j> 5) & 0x07, + (tmp_val1 >> 1) & 0x0f, + (tmp_val2 >> 14) & 0x0003ffff, + (tmp_val2 >> 2) & 0x00000fff) ); + } +}); diff --git a/src/parsing/sampleentries/sampleentry.js b/src/parsing/sampleentries/sampleentry.js index e2c18ac3..f7cf9e0c 100644 --- a/src/parsing/sampleentries/sampleentry.js +++ b/src/parsing/sampleentries/sampleentry.js @@ -105,6 +105,10 @@ BoxParser.createSampleEntryCtor(BoxParser.SAMPLE_ENTRY_TYPE_AUDIO, "mha2"); BoxParser.createSampleEntryCtor(BoxParser.SAMPLE_ENTRY_TYPE_AUDIO, "mhm1"); BoxParser.createSampleEntryCtor(BoxParser.SAMPLE_ENTRY_TYPE_AUDIO, "mhm2"); BoxParser.createSampleEntryCtor(BoxParser.SAMPLE_ENTRY_TYPE_AUDIO, "fLaC"); +BoxParser.createSampleEntryCtor(BoxParser.SAMPLE_ENTRY_TYPE_AUDIO, "av3a"); +/* TODO.AVS3A - activate whem test streams are available +BoxParser.createSampleEntryCtor(BoxParser.SAMPLE_ENTRY_TYPE_AUDIO, "a3as"); +*/ // Encrypted sample entries BoxParser.createEncryptedSampleEntryCtor(BoxParser.SAMPLE_ENTRY_TYPE_VISUAL, "encv"); diff --git a/test/boxHtmlTable.js b/test/boxHtmlTable.js index 78c983c4..df3af873 100644 --- a/test/boxHtmlTable.js +++ b/test/boxHtmlTable.js @@ -42,7 +42,9 @@ function generateBoxTable(box, excluded_fields, additional_props, no_header) { if (i%4 === 3) html += ' '; } } else { - if (box[prop].hasOwnProperty("toString") && typeof box[prop].toString === "function") + if (typeof box[prop].toHTML === "function") + html += box[prop].toHTML(); + else if (box[prop].hasOwnProperty("toString") && typeof box[prop].toString === "function") html += box[prop].toString(); else html += box[prop];