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
14use crate::color::ChromaSampling;
15use crate::ec::{Writer, OD_BITRES};
16use crate::encoder::FrameInvariants;
17use crate::entropymode::*;
18use crate::frame::*;
19use crate::header::ReferenceMode;
20use crate::lrf::*;
21use crate::mc::MotionVector;
22use crate::partition::BlockSize::*;
23use crate::partition::RefType::*;
24use crate::partition::*;
25use crate::scan_order::*;
26use crate::tiling::*;
27use crate::token_cdfs::*;
28use crate::transform::TxSize::*;
29
30use crate::transform::*;
31use crate::util::*;
32
33use arrayvec::*;
34use std::default::Default;
35use std::ops::{Add, Index, IndexMut};
36use std::*;
37
38const MAX_REF_MV_STACK_SIZE: usize = 8;
39pub const REF_CAT_LEVEL: u32 = 640;
40
41pub const FRAME_LF_COUNT: usize = 4;
42pub const MAX_LOOP_FILTER: usize = 63;
43const DELTA_LF_SMALL: u32 = 3;
44pub const DELTA_LF_PROBS: usize = DELTA_LF_SMALL as usize;
45
46const DELTA_Q_SMALL: u32 = 3;
47pub const DELTA_Q_PROBS: usize = DELTA_Q_SMALL as usize;
48
49static 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
52static 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]
56mod cdf_context;
57pub use cdf_context::*;
58
59mod partition_unit;
60pub use partition_unit::*;
61
62mod superblock_unit;
63pub use superblock_unit::*;
64
65mod transform_unit;
66pub use transform_unit::TxClass::*;
67pub use transform_unit::*;
68
69mod block_unit;
70pub use block_unit::*;
71
72mod frame_header;
73
74#[derive(Debug, Default)]
75pub struct FieldMap {
76 map: Vec<(&'static str, usize, usize)>,
77}
78
79impl 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]
95pub 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 */
105const MV_CLASSES: usize = 11;
106
107// MV Class Types
108const MV_CLASS_0: usize = 0; /* (0, 2] integer pel */
109const MV_CLASS_1: usize = 1; /* (2, 4] integer pel */
110const MV_CLASS_2: usize = 2; /* (4, 8] integer pel */
111const MV_CLASS_3: usize = 3; /* (8, 16] integer pel */
112const MV_CLASS_4: usize = 4; /* (16, 32] integer pel */
113const MV_CLASS_5: usize = 5; /* (32, 64] integer pel */
114const MV_CLASS_6: usize = 6; /* (64, 128] integer pel */
115const MV_CLASS_7: usize = 7; /* (128, 256] integer pel */
116const MV_CLASS_8: usize = 8; /* (256, 512] integer pel */
117const MV_CLASS_9: usize = 9; /* (512, 1024] integer pel */
118const MV_CLASS_10: usize = 10; /* (1024,2048] integer pel */
119
120const CLASS0_BITS: usize = 1; /* bits at integer precision for class 0 */
121const CLASS0_SIZE: usize = 1 << CLASS0_BITS;
122const MV_OFFSET_BITS: usize = MV_CLASSES + CLASS0_BITS - 2;
123const MV_BITS_CONTEXTS: usize = 6;
124const MV_FP_SIZE: usize = 4;
125
126const MV_MAX_BITS: usize = MV_CLASSES + CLASS0_BITS + 2;
127const MV_MAX: usize = (1 << MV_MAX_BITS) - 1;
128const MV_VALS: usize = (MV_MAX << 1) + 1;
129
130const MV_IN_USE_BITS: usize = 14;
131pub const MV_UPP: i32 = 1 << MV_IN_USE_BITS;
132pub const MV_LOW: i32 = -(1 << MV_IN_USE_BITS);
133
134#[inline(always)]
135pub 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)]
144pub 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)]
149pub 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)]
154pub 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.
163pub 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)]
169pub 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
180impl<'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