use crate::pixel_format::Av1SequenceHeader;
pub fn av1_codec_string(h: &Av1SequenceHeader) -> String {
let tier_char = if h.seq_tier_0 == 0 { 'M' } else { 'H' };
let at_defaults = !h.monochrome
&& h.color_primaries == 1
&& h.transfer_characteristics == 1
&& h.matrix_coefficients == 1
&& !h.color_range;
if at_defaults {
format!(
"av01.{}.{:02}{}.{:02}",
h.seq_profile, h.seq_level_idx_0, tier_char, h.bit_depth,
)
} else {
format!(
"av01.{}.{:02}{}.{:02}.{}.{:03}.{:03}.{:03}.{}",
h.seq_profile,
h.seq_level_idx_0,
tier_char,
h.bit_depth,
u8::from(h.monochrome),
h.color_primaries,
h.transfer_characteristics,
h.matrix_coefficients,
u8::from(h.color_range),
)
}
}
pub const AAC_LC_CODEC_STRING: &str = "mp4a.40.2";
pub fn hls_codecs_attribute(video: &str, audio: &str) -> String {
format!("{video},{audio}")
}
#[cfg(test)]
mod tests {
use super::*;
fn synth_seq_header(
seq_profile: u8,
seq_level_idx_0: u8,
seq_tier_0: u8,
bit_depth: u8,
monochrome: bool,
color_primaries: u8,
transfer_characteristics: u8,
matrix_coefficients: u8,
color_range: bool,
) -> Av1SequenceHeader {
Av1SequenceHeader {
seq_profile,
still_picture: false,
reduced_still_picture_header: false,
max_frame_width_minus1: 0,
max_frame_height_minus1: 0,
seq_level_idx_0,
seq_tier_0,
bit_depth,
monochrome,
color_primaries,
transfer_characteristics,
matrix_coefficients,
color_range,
chroma_subsampling_x: true,
chroma_subsampling_y: true,
film_grain_params_present: false,
enable_filter_intra: false,
enable_intra_edge_filter: false,
enable_interintra_compound: false,
enable_masked_compound: false,
enable_warped_motion: false,
enable_dual_filter: false,
enable_order_hint: false,
enable_jnt_comp: false,
enable_ref_frame_mvs: false,
enable_superres: false,
enable_cdef: false,
enable_restoration: false,
order_hint_bits: 0,
seq_force_screen_content_tools: 0,
seq_force_integer_mv: 0,
frame_width_bits_minus_1: 0,
frame_height_bits_minus_1: 0,
use_128x128_superblock: false,
separate_uv_delta_q: false,
}
}
#[test]
fn av1_string_short_form_at_bt709_defaults() {
let h = synth_seq_header(0, 8, 0, 8, false, 1, 1, 1, false);
assert_eq!(av1_codec_string(&h), "av01.0.08M.08");
}
#[test]
fn av1_string_high_tier_renders_h_character() {
let h = synth_seq_header(0, 16, 1, 10, false, 9, 16, 9, false);
assert_eq!(av1_codec_string(&h), "av01.0.16H.10.0.009.016.009.0");
}
#[test]
fn av1_string_hdr10_bt2020_pq_full_range() {
let h = synth_seq_header(0, 12, 0, 10, false, 9, 16, 9, true);
assert_eq!(av1_codec_string(&h), "av01.0.12M.10.0.009.016.009.1");
}
#[test]
fn av1_string_monochrome_uses_long_form() {
let h = synth_seq_header(0, 8, 0, 8, true, 1, 1, 1, false);
assert_eq!(av1_codec_string(&h), "av01.0.08M.08.1.001.001.001.0");
}
#[test]
fn av1_string_full_range_at_8bit_bt709_uses_long_form() {
let h = synth_seq_header(0, 8, 0, 8, false, 1, 1, 1, true);
assert_eq!(av1_codec_string(&h), "av01.0.08M.08.0.001.001.001.1");
}
#[test]
fn av1_string_two_digit_level_padding() {
let h = synth_seq_header(0, 0, 0, 8, false, 1, 1, 1, false);
let s = av1_codec_string(&h);
assert!(s.starts_with("av01.0.00M."), "got: {s}");
}
#[test]
fn av1_string_two_digit_bit_depth_padding() {
let h_8 = synth_seq_header(0, 8, 0, 8, false, 1, 1, 1, false);
let h_10 = synth_seq_header(0, 8, 0, 10, false, 1, 1, 1, false);
let h_12 = synth_seq_header(2, 8, 0, 12, false, 1, 1, 1, false);
assert_eq!(av1_codec_string(&h_8), "av01.0.08M.08");
assert_eq!(av1_codec_string(&h_10), "av01.0.08M.10");
assert_eq!(av1_codec_string(&h_12), "av01.2.08M.12");
}
#[test]
fn aac_lc_constant_is_canonical() {
assert_eq!(AAC_LC_CODEC_STRING, "mp4a.40.2");
}
#[test]
fn hls_codecs_attribute_concatenates_video_then_audio() {
let s = hls_codecs_attribute("av01.0.08M.08.0.001.001.001.0", AAC_LC_CODEC_STRING);
assert_eq!(s, "av01.0.08M.08.0.001.001.001.0,mp4a.40.2");
}
}