aboutsummaryrefslogtreecommitdiff
path: root/remuxer/src
diff options
context:
space:
mode:
Diffstat (limited to 'remuxer/src')
-rw-r--r--remuxer/src/codec_param/av1.rs38
-rw-r--r--remuxer/src/codec_param/hevc.rs55
-rw-r--r--remuxer/src/codec_param/mod.rs27
-rw-r--r--remuxer/src/lib.rs2
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)]