X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-core%2Fsrc%2Fscale%2Fcolorcvt.rs;h=00ae2a56203b38e2c9ac315be0e1696edd341226;hp=056c0504dc5f8db4e50772f3f47ebc68b996fb5b;hb=25e0bf9a974b1bb5a8f8b38e23b4a7e91db3eab0;hpb=575c0b27ffcb7440620222e6e78c9ecb4006cf99 diff --git a/nihav-core/src/scale/colorcvt.rs b/nihav-core/src/scale/colorcvt.rs index 056c050..00ae2a5 100644 --- a/nihav-core/src/scale/colorcvt.rs +++ b/nihav-core/src/scale/colorcvt.rs @@ -1,6 +1,8 @@ use super::*; use super::kernel::Kernel; +const DEFAULT_YUV: usize = 4; + const YUV_PARAMS: &[[f32; 2]] = &[ [ 0.333, 0.333 ], // RGB [ 0.2126, 0.0722 ], // ITU-R BT709 @@ -15,6 +17,33 @@ const YUV_PARAMS: &[[f32; 2]] = &[ [ 0.2627, 0.0593 ], // ITU-R BT2020 ]; +fn parse_yuv_mat(name: &str) -> usize { + match name { + "rgb" => 0, + "bt709" => 1, + "bt601" => 4, + "bt470" => 5, + "smpte170m" => 6, + "smpte240m" => 7, + "ycocg" => 8, + "bt2020" => 9, + _ => 2, + } +} + +/*fn get_yuv_mat(id: usize) -> &'static str { + match id { + 1 => "bt709", + 4 => "bt601", + 5 => "bt470", + 6 => "smpte170m", + 7 => "smpte240m", + 8 => "ycocg", + 9 => "bt2020", + _ => "rgb", + } +}*/ + const BT_PAL_COEFFS: [f32; 2] = [ 0.493, 0.877 ]; const SMPTE_NTSC_COEFFS: &[f32; 4] = &[ -0.268, 0.7358, 0.4127, 0.4778 ]; @@ -161,6 +190,7 @@ fn matrix_mul(mat: &[[f32; 3]; 3], a: f32, b: f32, c: f32) -> (f32, f32, f32) { #[derive(Default)] struct RgbToYuv { matrix: [[f32; 3]; 3], + mode: usize, } impl RgbToYuv { @@ -169,10 +199,23 @@ impl RgbToYuv { #[allow(clippy::many_single_char_names)] impl Kernel for RgbToYuv { - fn init(&mut self, in_fmt: &ScaleInfo, dest_fmt: &ScaleInfo) -> ScaleResult { + fn init(&mut self, in_fmt: &ScaleInfo, dest_fmt: &ScaleInfo, options: &[(String, String)]) -> ScaleResult { + let mut debug = false; + let mut mode = DEFAULT_YUV; + for (name, value) in options.iter() { + match (name.as_str(), value.as_str()) { + ("debug", "") => { debug = true; }, + ("debug", "true") => { debug = true; }, + ("rgb2yuv.mode", ymode) => { + mode = parse_yuv_mat(ymode); + }, + _ => {}, + } + } + self.mode = mode; + let mut df = dest_fmt.fmt; -//todo coeff selection - make_rgb2yuv(YUV_PARAMS[2][0], YUV_PARAMS[2][1], &mut self.matrix); + make_rgb2yuv(YUV_PARAMS[mode][0], YUV_PARAMS[mode][1], &mut self.matrix); if let ColorModel::YUV(yuvsm) = df.get_model() { match yuvsm { YUVSubmodel::YCbCr => {}, @@ -190,7 +233,9 @@ impl Kernel for RgbToYuv { chr.v_ss = 0; } } -println!(" [intermediate format {}]", df); + if debug { + println!(" [intermediate format {}]", df); + } let res = alloc_video_buffer(NAVideoInfo::new(in_fmt.width, in_fmt.height, false, df), 3); if res.is_err() { return Err(ScaleError::AllocError); } Ok(res.unwrap()) @@ -270,6 +315,7 @@ pub fn create_rgb2yuv() -> Box { #[derive(Default)] struct YuvToRgb { matrix: [[f32; 3]; 3], + mode: usize, yscale: Vec, r_chr: Vec, g_u: Vec, @@ -283,7 +329,21 @@ impl YuvToRgb { #[allow(clippy::many_single_char_names)] impl Kernel for YuvToRgb { - fn init(&mut self, in_fmt: &ScaleInfo, dest_fmt: &ScaleInfo) -> ScaleResult { + fn init(&mut self, in_fmt: &ScaleInfo, dest_fmt: &ScaleInfo, options: &[(String, String)]) -> ScaleResult { + let mut debug = false; + let mut mode = DEFAULT_YUV; + for (name, value) in options.iter() { + match (name.as_str(), value.as_str()) { + ("debug", "") => { debug = true; }, + ("debug", "true") => { debug = true; }, + ("yuv2rgb.mode", ymode) => { + mode = parse_yuv_mat(ymode); + }, + _ => {}, + } + } + self.mode = mode; + let mut df = dest_fmt.fmt; df.palette = false; if !df.is_unpacked() || df.get_max_depth() != 8 || df.get_total_depth() != df.get_num_comp() as u8 * 8 { @@ -301,13 +361,12 @@ impl Kernel for YuvToRgb { df.comp_info[3] = Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: false, depth: 8, shift: 0, comp_offs: 3, next_elem: 1 }); } } -//todo coeff selection - make_yuv2rgb(YUV_PARAMS[2][0], YUV_PARAMS[2][1], &mut self.matrix); + make_yuv2rgb(YUV_PARAMS[mode][0], YUV_PARAMS[mode][1], &mut self.matrix); if let ColorModel::YUV(yuvsm) = in_fmt.fmt.get_model() { match yuvsm { YUVSubmodel::YCbCr => {}, YUVSubmodel::YIQ => { - make_rgb2yuv(YUV_PARAMS[2][0], YUV_PARAMS[2][1], &mut self.matrix); + make_rgb2yuv(YUV_PARAMS[DEFAULT_YUV][0], YUV_PARAMS[DEFAULT_YUV][1], &mut self.matrix); apply_ntsc_rgb2yiq(SMPTE_NTSC_COEFFS, &mut self.matrix); invert_matrix(&mut self.matrix); }, @@ -343,7 +402,9 @@ impl Kernel for YuvToRgb { chr.comp_offs = i as u8; } } -println!(" [intermediate format {}]", df); + if debug { + println!(" [intermediate format {}]", df); + } let res = alloc_video_buffer(NAVideoInfo::new(in_fmt.width, in_fmt.height, false, df), 3); if res.is_err() { return Err(ScaleError::AllocError); } Ok(res.unwrap()) @@ -369,7 +430,7 @@ println!(" [intermediate format {}]", df); let mut voff = sbuf.get_offset(2); let src = sbuf.get_data(); let dst = dbuf.get_data_mut().unwrap(); - if self.yscale.len() > 0 { + if !self.yscale.is_empty() { for y in 0..h { for x in 0..w { let y = self.yscale[src[yoff + x] as usize]; @@ -432,7 +493,7 @@ impl YuvToRgb { let mut yoff = sbuf.get_offset(0); let src = sbuf.get_data(); let dst = dbuf.get_data_mut().unwrap(); - if self.yscale.len() > 0 { + if !self.yscale.is_empty() { for _y in 0..h { for x in 0..w { let y = self.yscale[src[yoff + x] as usize];