From fd6867bc57081ae89429162ab9ee12b24c94898f Mon Sep 17 00:00:00 2001 From: Muaz Ahmad Date: Thu, 12 Oct 2023 14:21:20 +0500 Subject: [PATCH] av01 parsing --- mp4-tree.js | 55 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/mp4-tree.js b/mp4-tree.js index 185e227..065d4b4 100644 --- a/mp4-tree.js +++ b/mp4-tree.js @@ -49,19 +49,21 @@ class MP4Tree { if (!this.parse_until('trak')) { // if no more tracks in file break; } - const curr_track_end = this.idx + this.read_next_head().len; + let curr_track_end = this.idx + this.read_next_head().len; this.idx += 8 this.parse_into('mdia', 8); this.parse_into('minf', 8); - const track_type_head = this.read_next_head().name; + let track_type_head = this.read_next_head().name; if (track_type_head == 'smhd' || track_type_head == 'vmhd') { this.parse_into('stbl', 8); this.parse_into('stsd', 16); - const media_sample = this.read_next_head().name; + let media_sample = this.read_next_head().name; if (media_sample == 'avc1') { this.parse_avc1(); } else if (media_sample == 'vp09') { this.parse_vp09(); + } else if (media_sample == 'av01') { + this.parse_av01(); } else if (media_sample == 'mp4a') { this.parse_mp4a(); } else if (media_sample == 'Opus') { @@ -80,27 +82,62 @@ class MP4Tree { // ex, 01 64 00 1f // 01 is avc version (always 1, bit-and it off) // rest is video codec profile, rep as hex - const avc_profile = (this.data.getUint32(this.idx) & 0xffffff).toString(16); + let avc_profile = (this.data.getUint32(this.idx) & 0xffffff).toString(16); this.codecs.push('avc1.' + avc_profile); } parse_vp09() { this.parse_into('vp09', 86); this.parse_into('vpcC', 12); - const profile = this.data.getUint8(this.idx).toString().padStart(2, "0"); - const level = this.data.getUint8(this.idx + 1).toString(); - const depth = (this.data.getUint8(this.idx + 2) >> 4).toString().padStart(2, "0"); + let profile = this.data.getUint8(this.idx).toString().padStart(2, "0"); + let level = this.data.getUint8(this.idx + 1).toString(); + let depth = (this.data.getUint8(this.idx + 2) >> 4).toString().padStart(2, "0"); this.codecs.push(["vp09", profile, level, depth].join('.')); } + parse_av01() { + this.parse_into('av01', 101); + this.parse_into('av1C', 8); + let tmp = this.data.getUint8(this.idx + 1); + let profile = tmp >> 5; + let level = tmp & 0x1f; + let tmp = this.data.getUint8(this.idx + 2); + switch (tmp >> 7) { + case 0: + let level_profile = "M"; + break; + case 1: + let level_profile = "H"; + break; + default: + let level_profile = ""; + } + let depth_bits = (tmp >> 5) & 0x3; + switch (depth_bits) { + case 0: + let bit_depth = "8"; + break; + case 1: + let bit_depth = "12"; + break; + case 2: + let bit_depth = "10"; + break; + default: + let bit_depth = "0"; + break; + } + this.codecs.push(["av01", profile, level.toString().padStart(2, "0") + level_profile, bit_depth].join('.')) + } + parse_mp4a() { this.parse_into('mp4a', 36); // 28 bytes of subboxes with unclear offsets this.parse_into('esds', 12); // mp4a is as mp4a.40.2 // oti has defined position, rep as hex // aot as a subtype is defined as 5 bits of the fetched byte, rep as dec - const oti = this.data.getUint8(this.idx + 13).toString(16); - const aot = (this.data.getUint8(this.idx + 31) >> 3).toString(10); + let oti = this.data.getUint8(this.idx + 13).toString(16); + let aot = (this.data.getUint8(this.idx + 31) >> 3).toString(10); this.codecs.push(["mp4a", oti, aot].join('.')); }