| 1 | // Copyright (c) 2017-2023, The rav1e contributors. All rights reserved |
| 2 | // |
| 3 | // This source code is subject to the terms of the BSD 2 Clause License and |
| 4 | // the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| 5 | // was not distributed with this source code in the LICENSE file, you can |
| 6 | // obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| 7 | // Media Patent License 1.0 was not distributed with this source code in the |
| 8 | // PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
| 9 | |
| 10 | #![allow (non_upper_case_globals)] |
| 11 | #![allow (dead_code)] |
| 12 | #![allow (non_camel_case_types)] |
| 13 | |
| 14 | use crate::color::ChromaSampling; |
| 15 | use crate::ec::{Writer, OD_BITRES}; |
| 16 | use crate::encoder::FrameInvariants; |
| 17 | use crate::entropymode::*; |
| 18 | use crate::frame::*; |
| 19 | use crate::header::ReferenceMode; |
| 20 | use crate::lrf::*; |
| 21 | use crate::mc::MotionVector; |
| 22 | use crate::partition::BlockSize::*; |
| 23 | use crate::partition::RefType::*; |
| 24 | use crate::partition::*; |
| 25 | use crate::scan_order::*; |
| 26 | use crate::tiling::*; |
| 27 | use crate::token_cdfs::*; |
| 28 | use crate::transform::TxSize::*; |
| 29 | |
| 30 | use crate::transform::*; |
| 31 | use crate::util::*; |
| 32 | |
| 33 | use arrayvec::*; |
| 34 | use std::default::Default; |
| 35 | use std::ops::{Add, Index, IndexMut}; |
| 36 | use std::*; |
| 37 | |
| 38 | const MAX_REF_MV_STACK_SIZE: usize = 8; |
| 39 | pub const REF_CAT_LEVEL: u32 = 640; |
| 40 | |
| 41 | pub const FRAME_LF_COUNT: usize = 4; |
| 42 | pub const MAX_LOOP_FILTER: usize = 63; |
| 43 | const DELTA_LF_SMALL: u32 = 3; |
| 44 | pub const DELTA_LF_PROBS: usize = DELTA_LF_SMALL as usize; |
| 45 | |
| 46 | const DELTA_Q_SMALL: u32 = 3; |
| 47 | pub const DELTA_Q_PROBS: usize = DELTA_Q_SMALL as usize; |
| 48 | |
| 49 | static size_group_lookup: [u8; BlockSize::BLOCK_SIZES_ALL] = |
| 50 | [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 0, 0, 1, 1, 2, 2]; |
| 51 | |
| 52 | static num_pels_log2_lookup: [u8; BlockSize::BLOCK_SIZES_ALL] = |
| 53 | [4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13, 13, 14, 6, 6, 8, 8, 10, 10]; |
| 54 | |
| 55 | #[macro_use ] |
| 56 | mod cdf_context; |
| 57 | pub use cdf_context::*; |
| 58 | |
| 59 | mod partition_unit; |
| 60 | pub use partition_unit::*; |
| 61 | |
| 62 | mod superblock_unit; |
| 63 | pub use superblock_unit::*; |
| 64 | |
| 65 | mod transform_unit; |
| 66 | pub use transform_unit::TxClass::*; |
| 67 | pub use transform_unit::*; |
| 68 | |
| 69 | mod block_unit; |
| 70 | pub use block_unit::*; |
| 71 | |
| 72 | mod frame_header; |
| 73 | |
| 74 | #[derive (Debug, Default)] |
| 75 | pub struct FieldMap { |
| 76 | map: Vec<(&'static str, usize, usize)>, |
| 77 | } |
| 78 | |
| 79 | impl FieldMap { |
| 80 | /// Print the field the address belong to |
| 81 | fn lookup(&self, addr: usize) { |
| 82 | for (name: &&str, start: &usize, end: &usize) in &self.map { |
| 83 | if addr >= *start && addr < *end { |
| 84 | println!(" CDF {name}" ); |
| 85 | println!(); |
| 86 | return; |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | println!(" CDF address not found: {addr}" ); |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | #[inline ] |
| 95 | pub const fn av1_get_coded_tx_size(tx_size: TxSize) -> TxSize { |
| 96 | match tx_size { |
| 97 | TX_64X64 | TX_64X32 | TX_32X64 => TX_32X32, |
| 98 | TX_16X64 => TX_16X32, |
| 99 | TX_64X16 => TX_32X16, |
| 100 | _ => tx_size, |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | /* Symbols for coding magnitude class of nonzero components */ |
| 105 | const MV_CLASSES: usize = 11; |
| 106 | |
| 107 | // MV Class Types |
| 108 | const MV_CLASS_0: usize = 0; /* (0, 2] integer pel */ |
| 109 | const MV_CLASS_1: usize = 1; /* (2, 4] integer pel */ |
| 110 | const MV_CLASS_2: usize = 2; /* (4, 8] integer pel */ |
| 111 | const MV_CLASS_3: usize = 3; /* (8, 16] integer pel */ |
| 112 | const MV_CLASS_4: usize = 4; /* (16, 32] integer pel */ |
| 113 | const MV_CLASS_5: usize = 5; /* (32, 64] integer pel */ |
| 114 | const MV_CLASS_6: usize = 6; /* (64, 128] integer pel */ |
| 115 | const MV_CLASS_7: usize = 7; /* (128, 256] integer pel */ |
| 116 | const MV_CLASS_8: usize = 8; /* (256, 512] integer pel */ |
| 117 | const MV_CLASS_9: usize = 9; /* (512, 1024] integer pel */ |
| 118 | const MV_CLASS_10: usize = 10; /* (1024,2048] integer pel */ |
| 119 | |
| 120 | const CLASS0_BITS: usize = 1; /* bits at integer precision for class 0 */ |
| 121 | const CLASS0_SIZE: usize = 1 << CLASS0_BITS; |
| 122 | const MV_OFFSET_BITS: usize = MV_CLASSES + CLASS0_BITS - 2; |
| 123 | const MV_BITS_CONTEXTS: usize = 6; |
| 124 | const MV_FP_SIZE: usize = 4; |
| 125 | |
| 126 | const MV_MAX_BITS: usize = MV_CLASSES + CLASS0_BITS + 2; |
| 127 | const MV_MAX: usize = (1 << MV_MAX_BITS) - 1; |
| 128 | const MV_VALS: usize = (MV_MAX << 1) + 1; |
| 129 | |
| 130 | const MV_IN_USE_BITS: usize = 14; |
| 131 | pub const MV_UPP: i32 = 1 << MV_IN_USE_BITS; |
| 132 | pub const MV_LOW: i32 = -(1 << MV_IN_USE_BITS); |
| 133 | |
| 134 | #[inline (always)] |
| 135 | pub const fn av1_get_mv_joint(mv: MotionVector) -> MvJointType { |
| 136 | match (mv.row, mv.col) { |
| 137 | (0, 0) => MvJointType::MV_JOINT_ZERO, |
| 138 | (0, _) => MvJointType::MV_JOINT_HNZVZ, |
| 139 | (_, 0) => MvJointType::MV_JOINT_HZVNZ, |
| 140 | (_, _) => MvJointType::MV_JOINT_HNZVNZ, |
| 141 | } |
| 142 | } |
| 143 | #[inline (always)] |
| 144 | pub fn mv_joint_vertical(joint_type: MvJointType) -> bool { |
| 145 | joint_type == MvJointType::MV_JOINT_HZVNZ |
| 146 | || joint_type == MvJointType::MV_JOINT_HNZVNZ |
| 147 | } |
| 148 | #[inline (always)] |
| 149 | pub fn mv_joint_horizontal(joint_type: MvJointType) -> bool { |
| 150 | joint_type == MvJointType::MV_JOINT_HNZVZ |
| 151 | || joint_type == MvJointType::MV_JOINT_HNZVNZ |
| 152 | } |
| 153 | #[inline (always)] |
| 154 | pub const fn mv_class_base(mv_class: usize) -> u32 { |
| 155 | if mv_class != MV_CLASS_0 { |
| 156 | (CLASS0_SIZE << (mv_class + 2)) as u32 |
| 157 | } else { |
| 158 | 0 |
| 159 | } |
| 160 | } |
| 161 | #[inline (always)] |
| 162 | // If n != 0, returns the floor of log base 2 of n. If n == 0, returns 0. |
| 163 | pub fn log_in_base_2(n: u32) -> u8 { |
| 164 | 31 - cmp::min(v1:31, v2:n.leading_zeros() as u8) |
| 165 | } |
| 166 | |
| 167 | /// Returns `(mv_class, offset)` |
| 168 | #[inline (always)] |
| 169 | pub fn get_mv_class(z: u32) -> (usize, u32) { |
| 170 | let c: usize = if z >= CLASS0_SIZE as u32 * 4096 { |
| 171 | MV_CLASS_10 |
| 172 | } else { |
| 173 | log_in_base_2(z >> 3) as usize |
| 174 | }; |
| 175 | |
| 176 | let offset: u32 = z - mv_class_base(mv_class:c); |
| 177 | (c, offset) |
| 178 | } |
| 179 | |
| 180 | impl<'a> ContextWriter<'a> { |
| 181 | /// # Panics |
| 182 | /// |
| 183 | /// - If the `comp` is 0 |
| 184 | /// - If the `comp` is outside the bounds of `MV_LOW` and `MV_UPP` |
| 185 | pub fn encode_mv_component<W: Writer>( |
| 186 | &mut self, w: &mut W, comp: i32, axis: usize, precision: MvSubpelPrecision, |
| 187 | ) { |
| 188 | assert!(comp != 0); |
| 189 | assert!((MV_LOW..=MV_UPP).contains(&comp)); |
| 190 | let sign: u32 = u32::from(comp < 0); |
| 191 | let mag: u32 = if sign == 1 { -comp as u32 } else { comp as u32 }; |
| 192 | let (mv_class, offset) = get_mv_class(mag - 1); |
| 193 | let d = offset >> 3; // int mv data |
| 194 | let fr = (offset >> 1) & 3; // fractional mv data |
| 195 | let hp = offset & 1; // high precision mv data |
| 196 | |
| 197 | // Sign |
| 198 | { |
| 199 | let mvcomp = &self.fc.nmv_context.comps[axis]; |
| 200 | let cdf = &mvcomp.sign_cdf; |
| 201 | symbol_with_update!(self, w, sign, cdf); |
| 202 | } |
| 203 | |
| 204 | // Class |
| 205 | { |
| 206 | let mvcomp = &self.fc.nmv_context.comps[axis]; |
| 207 | let cdf = &mvcomp.classes_cdf; |
| 208 | symbol_with_update!(self, w, mv_class as u32, cdf); |
| 209 | } |
| 210 | |
| 211 | // Integer bits |
| 212 | if mv_class == MV_CLASS_0 { |
| 213 | let mvcomp = &self.fc.nmv_context.comps[axis]; |
| 214 | let cdf = &mvcomp.class0_cdf; |
| 215 | symbol_with_update!(self, w, d, cdf); |
| 216 | } else { |
| 217 | let n = mv_class + CLASS0_BITS - 1; // number of bits |
| 218 | for i in 0..n { |
| 219 | let mvcomp = &self.fc.nmv_context.comps[axis]; |
| 220 | let cdf = &mvcomp.bits_cdf[i]; |
| 221 | symbol_with_update!(self, w, (d >> i) & 1, cdf); |
| 222 | } |
| 223 | } |
| 224 | // Fractional bits |
| 225 | if precision > MvSubpelPrecision::MV_SUBPEL_NONE { |
| 226 | let mvcomp = &self.fc.nmv_context.comps[axis]; |
| 227 | let cdf = if mv_class == MV_CLASS_0 { |
| 228 | &mvcomp.class0_fp_cdf[d as usize] |
| 229 | } else { |
| 230 | &mvcomp.fp_cdf |
| 231 | }; |
| 232 | symbol_with_update!(self, w, fr, cdf); |
| 233 | } |
| 234 | |
| 235 | // High precision bit |
| 236 | if precision > MvSubpelPrecision::MV_SUBPEL_LOW_PRECISION { |
| 237 | let mvcomp = &self.fc.nmv_context.comps[axis]; |
| 238 | let cdf = if mv_class == MV_CLASS_0 { |
| 239 | &mvcomp.class0_hp_cdf |
| 240 | } else { |
| 241 | &mvcomp.hp_cdf |
| 242 | }; |
| 243 | symbol_with_update!(self, w, hp, cdf); |
| 244 | } |
| 245 | } |
| 246 | } |
| 247 | |