diff options
Diffstat (limited to 'remuxer/src')
| -rw-r--r-- | remuxer/src/codec_param/av1.rs | 38 | ||||
| -rw-r--r-- | remuxer/src/codec_param/hevc.rs | 55 | ||||
| -rw-r--r-- | remuxer/src/codec_param/mod.rs | 27 | ||||
| -rw-r--r-- | remuxer/src/lib.rs | 2 |
4 files changed, 122 insertions, 0 deletions
diff --git a/remuxer/src/codec_param/av1.rs b/remuxer/src/codec_param/av1.rs new file mode 100644 index 0000000..5641e77 --- /dev/null +++ b/remuxer/src/codec_param/av1.rs @@ -0,0 +1,38 @@ +/* + This file is part of jellything (https://codeberg.org/metamuffin/jellything) + which is licensed under the GNU Affero General Public License (version 3); see /COPYING. + Copyright (C) 2026 metamuffin <metamuffin.org> +*/ + +pub fn av1_codec_param(cp: &[u8]) -> String { + let profile = (cp[1] >> 5) & 0b111; + let level = cp[1] & 0b11111; + let tier = (cp[2] >> 7) & 0b1; + let high_bitdepth = (cp[2] >> 6) & 0b1; + let twelve_bit = (cp[2] >> 5) & 0b1; + let _monochrome = (cp[2] >> 4) & 0b1; + let _css_x = (cp[2] >> 3) & 0b1; + let _css_y = (cp[2] >> 2) & 0b1; + let _css_pos = cp[2] & 0b11; + + let tier_char = if tier == 1 { 'H' } else { 'M' }; + let bit_depth = if twelve_bit == 1 { + 12 + } else if high_bitdepth == 1 { + 10 + } else { + 0 + }; + format!( + "av01.{profile}.{level:02}{tier_char}.{bit_depth:02}" // .{monochrome}.{css_x}{css_y}{css_pos} + ) +} + +#[test] +fn sample1() { + assert_eq!(av1_codec_param(&[0x81, 0x04, 0x4E]), "av01.0.04M.10"); +} +#[test] +fn sample2() { + assert_eq!(av1_codec_param(&[0x81, 0x35, 0xF4]), "av01.1.21H.12"); +} diff --git a/remuxer/src/codec_param/hevc.rs b/remuxer/src/codec_param/hevc.rs new file mode 100644 index 0000000..3459258 --- /dev/null +++ b/remuxer/src/codec_param/hevc.rs @@ -0,0 +1,55 @@ +/* + This file is part of jellything (https://codeberg.org/metamuffin/jellything) + which is licensed under the GNU Affero General Public License (version 3); see /COPYING. + Copyright (C) 2026 metamuffin <metamuffin.org> +*/ + +use std::fmt::Write; + +pub(super) fn hevc_codec_param(cp: &[u8]) -> String { + let general_profile_space = cp[1] >> 6; + let general_tier_flag = (cp[1] >> 5) & 0b1; + let general_profile_idc = cp[1] & 0b11111; + let general_level_idc = cp[12]; + let general_profile_compatibility_flag = + u32::from_be_bytes([cp[2], cp[3], cp[4], cp[5]]).reverse_bits(); + let mut d = String::new(); + let trailing_zeroes = cp[6..12].iter().rev().take_while(|x| **x == 0).count(); + for &flag in &cp[6..12 - trailing_zeroes] { + write!(d, ".{flag:02x}").unwrap(); + } + format!( + "hvc1.{}{}.{:x}.{}{}{d}", + match general_profile_space { + 0 => "", + 1 => "A", + 2 => "B", + 3 => "C", + _ => unreachable!(), + }, + general_profile_idc, + general_profile_compatibility_flag, + match general_tier_flag { + 0 => 'L', + 1 => 'H', + _ => unreachable!(), + }, + general_level_idc, + ) +} + +#[test] +fn sample1() { + let cp = [ + 0x01, 0x02, 0x20, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, + ]; + assert_eq!(hevc_codec_param(&cp), "hvc1.2.4.L63.90") +} + +#[test] +fn sample2() { + let cp = [ + 0x01, 0x01, 0x60, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, + ]; + assert_eq!(hevc_codec_param(&cp), "hvc1.1.6.L120.b0") +} diff --git a/remuxer/src/codec_param/mod.rs b/remuxer/src/codec_param/mod.rs new file mode 100644 index 0000000..8c0b6b7 --- /dev/null +++ b/remuxer/src/codec_param/mod.rs @@ -0,0 +1,27 @@ +/* + This file is part of jellything (https://codeberg.org/metamuffin/jellything) + which is licensed under the GNU Affero General Public License (version 3); see /COPYING. + Copyright (C) 2026 metamuffin <metamuffin.org> +*/ + +use crate::codec_param::{av1::av1_codec_param, hevc::hevc_codec_param}; +use winter_matroska::TrackEntry; + +mod av1; +mod hevc; + +pub fn codec_param(te: &TrackEntry) -> String { + let cp = te.codec_private.as_ref().unwrap(); + match te.codec_id.as_str() { + "A_AAC" => format!("mp4a.40.2"), // TODO + "A_FLAC" => "flac".to_string(), + "A_OPUS" => "opus".to_string(), + "A_VORBIS" => "vorbis".to_string(), + + "V_AV1" => av1_codec_param(cp), + "V_MPEG4/ISO/AVC" => format!("avc1.{:02x}{:02x}{:02x}", cp[1], cp[2], cp[3]), + "V_MPEGH/ISO/HEVC" => hevc_codec_param(cp), + + x => todo!("{x:?}"), + } +} diff --git a/remuxer/src/lib.rs b/remuxer/src/lib.rs index e4b0fdc..ad5de53 100644 --- a/remuxer/src/lib.rs +++ b/remuxer/src/lib.rs @@ -7,7 +7,9 @@ pub mod demuxers; pub mod magic; pub mod muxers; +mod codec_param; +pub use codec_param::codec_param; pub use winter_matroska as matroska; #[derive(Debug, Clone, Copy, PartialEq)] |