aboutsummaryrefslogtreecommitdiff
path: root/remuxer/src/codec_param/hevc.rs
blob: 345925873592c3daebde9c9c0a6d6e21dae6ee00 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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")
}