Commit 4365c8d6 authored by Raphaël Zumer's avatar Raphaël Zumer Committed by Luca Barbato

Support color description (#805)

* Handle color description in the header
* Allow setting color description via CLI
parent 5e965c4d
......@@ -41,6 +41,7 @@ pub struct EncoderConfig {
pub low_latency: bool,
pub quantizer: usize,
pub tune: Tune,
pub color_description: Option<ColorDescription>,
pub speed_settings: SpeedSettings,
pub show_psnr: bool,
}
......@@ -60,6 +61,7 @@ impl EncoderConfig {
low_latency: true,
quantizer: 100,
tune: Tune::Psnr,
color_description: None,
speed_settings: SpeedSettings::from_preset(speed),
show_psnr: false,
}
......@@ -154,45 +156,24 @@ pub enum PredictionModesSetting {
ComplexAll,
}
#[derive(Debug,Clone,Copy,PartialEq)]
pub enum MatrixCoefficients {
Identity = 0,
BT709,
Unspecified,
Reserved,
BT470M,
BT470BG,
ST170M,
ST240M,
YCgCo,
BT2020NonConstantLuminance,
BT2020ConstantLuminance,
ST2085,
ChromaticityDerivedNonConstantLuminance,
ChromaticityDerivedConstantLuminance,
ICtCp,
}
impl fmt::Display for MatrixCoefficients {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
MatrixCoefficients::Identity => write!(f, "Identity"),
MatrixCoefficients::BT709 => write!(f, "ITU BT.709"),
MatrixCoefficients::Unspecified => write!(f, "Unspecified"),
MatrixCoefficients::Reserved => write!(f, "Reserved"),
MatrixCoefficients::BT470M => write!(f, "ITU BT.470M"),
MatrixCoefficients::BT470BG => write!(f, "ITU BT.470BG"),
MatrixCoefficients::ST170M => write!(f, "SMPTE ST-170M"),
MatrixCoefficients::ST240M => write!(f, "SMPTE ST-240M"),
MatrixCoefficients::YCgCo => write!(f, "YCgCo"),
MatrixCoefficients::BT2020NonConstantLuminance => write!(f, "ITU BT.2020 (Non Constant Luminance)"),
MatrixCoefficients::BT2020ConstantLuminance => write!(f, "ITU BT.2020 (Constant Luminance)"),
MatrixCoefficients::ST2085 => write!(f, "SMPTE ST-2085"),
MatrixCoefficients::ChromaticityDerivedNonConstantLuminance => write!(f, "Chromaticity Derived (Non Constant Luminance)"),
MatrixCoefficients::ChromaticityDerivedConstantLuminance => write!(f, "Chromaticity Derived (Constant Luminance)"),
MatrixCoefficients::ICtCp => write!(f, "ICtCp"),
}
}
arg_enum!{
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum MatrixCoefficients {
Identity = 0,
BT709,
Unspecified,
BT470M = 4,
BT470BG,
ST170M,
ST240M,
YCgCo,
BT2020NonConstantLuminance,
BT2020ConstantLuminance,
ST2085,
ChromaticityDerivedNonConstantLuminance,
ChromaticityDerivedConstantLuminance,
ICtCp,
}
}
impl Default for MatrixCoefficients {
......@@ -201,43 +182,22 @@ impl Default for MatrixCoefficients {
}
}
#[derive(Debug,Clone,Copy,PartialEq)]
pub enum ColorPrimaries {
Reserved0 = 0,
BT709,
Unspecified,
Reserved,
BT470M,
BT470BG,
ST170M,
ST240M,
Film,
BT2020,
ST428,
P3DCI,
P3Display,
Tech3213 = 22,
}
impl fmt::Display for ColorPrimaries {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
ColorPrimaries::Reserved0 => write!(f, "Identity"),
ColorPrimaries::BT709 => write!(f, "ITU BT.709"),
ColorPrimaries::Unspecified => write!(f, "Unspecified"),
ColorPrimaries::Reserved => write!(f, "Reserved"),
ColorPrimaries::BT470M => write!(f, "ITU BT.470M"),
ColorPrimaries::BT470BG => write!(f, "ITU BT.470BG"),
ColorPrimaries::ST170M => write!(f, "SMPTE ST-170M"),
ColorPrimaries::ST240M => write!(f, "SMPTE ST-240M"),
ColorPrimaries::Film => write!(f, "Film"),
ColorPrimaries::BT2020 => write!(f, "ITU BT.2020"),
ColorPrimaries::ST428 => write!(f, "SMPTE ST-428"),
ColorPrimaries::P3DCI => write!(f, "DCI P3"),
ColorPrimaries::P3Display => write!(f, "Display P3"),
ColorPrimaries::Tech3213 => write!(f, "EBU Tech3213"),
}
}
arg_enum!{
#[derive(Debug,Clone,Copy,PartialEq)]
pub enum ColorPrimaries {
BT709 = 1,
Unspecified,
BT470M = 4,
BT470BG,
ST170M,
ST240M,
Film,
BT2020,
ST428,
P3DCI,
P3Display,
Tech3213 = 22,
}
}
impl Default for ColorPrimaries {
......@@ -246,53 +206,27 @@ impl Default for ColorPrimaries {
}
}
#[derive(Debug,Clone,Copy,PartialEq)]
pub enum TransferCharacteristics {
Reserved0 = 0,
BT1886,
Unspecified,
Reserved,
BT470M,
BT470BG,
ST170M,
ST240M,
Linear,
Logarithmic100,
Logarithmic316,
XVYCC,
BT1361E,
SRGB,
BT2020Ten,
BT2020Twelve,
PerceptualQuantizer,
ST428,
HybridLogGamma,
}
impl fmt::Display for TransferCharacteristics {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
TransferCharacteristics::Reserved0 => write!(f, "Identity"),
TransferCharacteristics::BT1886 => write!(f, "ITU BT.1886"),
TransferCharacteristics::Unspecified => write!(f, "Unspecified"),
TransferCharacteristics::Reserved => write!(f, "Reserved"),
TransferCharacteristics::BT470M => write!(f, "ITU BT.470M"),
TransferCharacteristics::BT470BG => write!(f, "ITU BT.470BG"),
TransferCharacteristics::ST170M => write!(f, "SMPTE ST-170M"),
TransferCharacteristics::ST240M => write!(f, "SMPTE ST-240M"),
TransferCharacteristics::Linear => write!(f, "Linear"),
TransferCharacteristics::Logarithmic100 => write!(f, "Logarithmic 100:1 range"),
TransferCharacteristics::Logarithmic316 => write!(f, "Logarithmic 316:1 range"),
TransferCharacteristics::XVYCC => write!(f, "XVYCC"),
TransferCharacteristics::BT1361E => write!(f, "ITU BT.1361 Extended Color Gamut"),
TransferCharacteristics::SRGB => write!(f, "sRGB"),
TransferCharacteristics::BT2020Ten => write!(f, "ITU BT.2020 for 10bit systems"),
TransferCharacteristics::BT2020Twelve => write!(f, "ITU BT.2020 for 12bit systems"),
TransferCharacteristics::PerceptualQuantizer => write!(f, "Perceptual Quantizer"),
TransferCharacteristics::ST428 => write!(f, "SMPTE ST-428"),
TransferCharacteristics::HybridLogGamma => write!(f, "Hybrid Log-Gamma"),
}
}
arg_enum!{
#[derive(Debug,Clone,Copy,PartialEq)]
pub enum TransferCharacteristics {
BT1886 = 1,
Unspecified,
BT470M = 4,
BT470BG,
ST170M,
ST240M,
Linear,
Logarithmic100,
Logarithmic316,
XVYCC,
BT1361E,
SRGB,
BT2020Ten,
BT2020Twelve,
PerceptualQuantizer,
ST428,
HybridLogGamma,
}
}
impl Default for TransferCharacteristics {
......@@ -301,6 +235,13 @@ impl Default for TransferCharacteristics {
}
}
#[derive(Copy, Clone, Debug)]
pub struct ColorDescription {
pub color_primaries: ColorPrimaries,
pub transfer_characteristics: TransferCharacteristics,
pub matrix_coefficients: MatrixCoefficients
}
/// Frame-specific information
#[derive(Clone, Copy, Debug, Default)]
pub struct FrameInfo {
......
......@@ -8,6 +8,7 @@
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.
use clap::{App, Arg, ArgMatches};
use {ColorPrimaries, TransferCharacteristics, MatrixCoefficients};
use rav1e::*;
use std::{fmt, io, slice};
......@@ -97,6 +98,27 @@ pub fn parse_cli() -> CliOptions {
.possible_values(&Tune::variants())
.default_value("psnr")
.case_insensitive(true)
).arg(
Arg::with_name("COLOR_PRIMARIES")
.help("Color primaries used to describe color parameters.")
.long("primaries")
.possible_values(&ColorPrimaries::variants())
.default_value("unspecified")
.case_insensitive(true)
).arg(
Arg::with_name("TRANSFER_CHARACTERISTICS")
.help("Transfer characteristics used to describe color parameters.")
.long("transfer")
.possible_values(&TransferCharacteristics::variants())
.default_value("unspecified")
.case_insensitive(true)
).arg(
Arg::with_name("MATRIX_COEFFICIENTS")
.help("Color primaries used to describe color parameters.")
.long("matrix")
.possible_values(&MatrixCoefficients::variants())
.default_value("unspecified")
.case_insensitive(true)
).arg(
Arg::with_name("VERBOSE")
.help("verbose logging, output info for every frame")
......@@ -145,11 +167,27 @@ fn parse_config(matches: &ArgMatches) -> EncoderConfig {
panic!("Maximum keyframe interval must be greater than or equal to minimum keyframe interval");
}
let color_primaries = matches.value_of("COLOR_PRIMARIES").unwrap().parse().unwrap_or_default();
let transfer_characteristics = matches.value_of("TRANSFER_CHARACTERISTICS").unwrap().parse().unwrap_or_default();
let matrix_coefficients = matches.value_of("MATRIX_COEFFICIENTS").unwrap().parse().unwrap_or_default();
let mut cfg = EncoderConfig::with_speed_preset(speed);
cfg.max_key_frame_interval = min_interval;
cfg.max_key_frame_interval = max_interval;
cfg.low_latency = matches.value_of("LOW_LATENCY").unwrap().parse().unwrap();
cfg.tune = matches.value_of("TUNE").unwrap().parse().unwrap();
cfg.color_description = if color_primaries == ColorPrimaries::Unspecified &&
transfer_characteristics == TransferCharacteristics::Unspecified &&
matrix_coefficients == MatrixCoefficients::Unspecified {
// No need to set a color description with all parameters unspecified.
None
} else {
Some(ColorDescription {
color_primaries,
transfer_characteristics,
matrix_coefficients
})
};
cfg.quantizer = quantizer;
cfg.show_psnr = matches.is_present("PSNR");
......
......@@ -216,13 +216,14 @@ impl Default for ChromaSamplePosition {
#[derive(Copy, Clone)]
pub struct Sequence {
// OBU Sequence header of AV1
// OBU Sequence header of AV1
pub profile: u8,
pub num_bits_width: u32,
pub num_bits_height: u32,
pub bit_depth: usize,
pub chroma_sampling: ChromaSampling,
pub chroma_sample_position: ChromaSamplePosition,
pub color_description: Option<ColorDescription>,
pub max_frame_width: u32,
pub max_frame_height: u32,
pub frame_id_numbers_present_flag: bool,
......@@ -305,6 +306,7 @@ impl Sequence {
bit_depth: info.bit_depth,
chroma_sampling: info.chroma_sampling,
chroma_sample_position: info.chroma_sample_position,
color_description: None,
max_frame_width: info.width as u32,
max_frame_height: info.height as u32,
frame_id_numbers_present_flag: false,
......@@ -940,7 +942,7 @@ impl<W: io::Write> UncompressedHeader for BitWriter<W, BigEndian> {
self.write_bit(seq.film_grain_params_present)?;
self.write_bit(true)?; // add_trailing_bits
self.write_bit(true)?; // trailing bit
Ok(())
}
......@@ -1021,12 +1023,19 @@ impl<W: io::Write> UncompressedHeader for BitWriter<W, BigEndian> {
self.write_bit(seq.monochrome)?;
}
self.write_bit(false)?; // color description present flag
if seq.monochrome {
unimplemented!();
}
if let Some(color_description) = seq.color_description {
self.write_bit(true)?; // color description present
self.write(8, color_description.color_primaries as u8)?;
self.write(8, color_description.transfer_characteristics as u8)?;
self.write(8, color_description.matrix_coefficients as u8)?;
} else {
self.write_bit(false)?; // no color description present
}
self.write_bit(false)?; // full color range
let subsampling_x = seq.chroma_sampling != ChromaSampling::Cs444;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment