| 1 | // Copyright (c) 2017-2022, 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 | use super::*; |
| 11 | use std::marker::PhantomData; |
| 12 | |
| 13 | pub const CDF_LEN_MAX: usize = 16; |
| 14 | |
| 15 | #[derive (Clone)] |
| 16 | pub struct CDFContextCheckpoint { |
| 17 | small: usize, |
| 18 | large: usize, |
| 19 | } |
| 20 | |
| 21 | #[derive (Clone, Copy)] |
| 22 | #[repr (C)] |
| 23 | pub struct CDFContext { |
| 24 | pub comp_bwd_ref_cdf: [[[u16; 2]; BWD_REFS - 1]; REF_CONTEXTS], |
| 25 | pub comp_mode_cdf: [[u16; 2]; COMP_INTER_CONTEXTS], |
| 26 | pub comp_ref_cdf: [[[u16; 2]; FWD_REFS - 1]; REF_CONTEXTS], |
| 27 | pub comp_ref_type_cdf: [[u16; 2]; COMP_REF_TYPE_CONTEXTS], |
| 28 | pub dc_sign_cdf: [[[u16; 2]; DC_SIGN_CONTEXTS]; PLANE_TYPES], |
| 29 | pub drl_cdfs: [[u16; 2]; DRL_MODE_CONTEXTS], |
| 30 | pub eob_extra_cdf: |
| 31 | [[[[u16; 2]; EOB_COEF_CONTEXTS]; PLANE_TYPES]; TxSize::TX_SIZES], |
| 32 | pub filter_intra_cdfs: [[u16; 2]; BlockSize::BLOCK_SIZES_ALL], |
| 33 | pub intra_inter_cdfs: [[u16; 2]; INTRA_INTER_CONTEXTS], |
| 34 | pub lrf_sgrproj_cdf: [u16; 2], |
| 35 | pub lrf_wiener_cdf: [u16; 2], |
| 36 | pub newmv_cdf: [[u16; 2]; NEWMV_MODE_CONTEXTS], |
| 37 | pub palette_uv_mode_cdfs: [[u16; 2]; PALETTE_UV_MODE_CONTEXTS], |
| 38 | pub palette_y_mode_cdfs: |
| 39 | [[[u16; 2]; PALETTE_Y_MODE_CONTEXTS]; PALETTE_BSIZE_CTXS], |
| 40 | pub refmv_cdf: [[u16; 2]; REFMV_MODE_CONTEXTS], |
| 41 | pub single_ref_cdfs: [[[u16; 2]; SINGLE_REFS - 1]; REF_CONTEXTS], |
| 42 | pub skip_cdfs: [[u16; 2]; SKIP_CONTEXTS], |
| 43 | pub txb_skip_cdf: [[[u16; 2]; TXB_SKIP_CONTEXTS]; TxSize::TX_SIZES], |
| 44 | pub txfm_partition_cdf: [[u16; 2]; TXFM_PARTITION_CONTEXTS], |
| 45 | pub zeromv_cdf: [[u16; 2]; GLOBALMV_MODE_CONTEXTS], |
| 46 | pub tx_size_8x8_cdf: [[u16; MAX_TX_DEPTH]; TX_SIZE_CONTEXTS], |
| 47 | pub inter_tx_3_cdf: [[u16; 2]; TX_SIZE_SQR_CONTEXTS], |
| 48 | |
| 49 | pub coeff_base_eob_cdf: |
| 50 | [[[[u16; 3]; SIG_COEF_CONTEXTS_EOB]; PLANE_TYPES]; TxSize::TX_SIZES], |
| 51 | pub lrf_switchable_cdf: [u16; 3], |
| 52 | pub tx_size_cdf: [[[u16; MAX_TX_DEPTH + 1]; TX_SIZE_CONTEXTS]; BIG_TX_CATS], |
| 53 | |
| 54 | pub coeff_base_cdf: |
| 55 | [[[[u16; 4]; SIG_COEF_CONTEXTS]; PLANE_TYPES]; TxSize::TX_SIZES], |
| 56 | pub coeff_br_cdf: |
| 57 | [[[[u16; BR_CDF_SIZE]; LEVEL_CONTEXTS]; PLANE_TYPES]; TxSize::TX_SIZES], |
| 58 | pub deblock_delta_cdf: [u16; DELTA_LF_PROBS + 1], |
| 59 | pub deblock_delta_multi_cdf: [[u16; DELTA_LF_PROBS + 1]; FRAME_LF_COUNT], |
| 60 | pub partition_w8_cdf: [[u16; 4]; PARTITION_TYPES], |
| 61 | |
| 62 | pub eob_flag_cdf16: [[[u16; 5]; 2]; PLANE_TYPES], |
| 63 | pub intra_tx_2_cdf: [[[u16; 5]; INTRA_MODES]; TX_SIZE_SQR_CONTEXTS], |
| 64 | |
| 65 | pub eob_flag_cdf32: [[[u16; 6]; 2]; PLANE_TYPES], |
| 66 | |
| 67 | pub angle_delta_cdf: [[u16; 2 * MAX_ANGLE_DELTA + 1]; DIRECTIONAL_MODES], |
| 68 | pub eob_flag_cdf64: [[[u16; 7]; 2]; PLANE_TYPES], |
| 69 | pub intra_tx_1_cdf: [[[u16; 7]; INTRA_MODES]; TX_SIZE_SQR_CONTEXTS], |
| 70 | |
| 71 | pub cfl_sign_cdf: [u16; CFL_JOINT_SIGNS], |
| 72 | pub compound_mode_cdf: [[u16; INTER_COMPOUND_MODES]; INTER_MODE_CONTEXTS], |
| 73 | pub eob_flag_cdf128: [[[u16; 8]; 2]; PLANE_TYPES], |
| 74 | pub spatial_segmentation_cdfs: [[u16; 8]; 3], |
| 75 | pub partition_w128_cdf: [[u16; 8]; PARTITION_TYPES], |
| 76 | |
| 77 | pub eob_flag_cdf256: [[[u16; 9]; 2]; PLANE_TYPES], |
| 78 | |
| 79 | pub eob_flag_cdf512: [[[u16; 10]; 2]; PLANE_TYPES], |
| 80 | pub partition_cdf: [[u16; EXT_PARTITION_TYPES]; 3 * PARTITION_TYPES], |
| 81 | |
| 82 | pub eob_flag_cdf1024: [[[u16; 11]; 2]; PLANE_TYPES], |
| 83 | |
| 84 | pub inter_tx_2_cdf: [[u16; 12]; TX_SIZE_SQR_CONTEXTS], |
| 85 | |
| 86 | pub kf_y_cdf: [[[u16; INTRA_MODES]; KF_MODE_CONTEXTS]; KF_MODE_CONTEXTS], |
| 87 | pub y_mode_cdf: [[u16; INTRA_MODES]; BLOCK_SIZE_GROUPS], |
| 88 | pub uv_mode_cdf: [[u16; INTRA_MODES]; INTRA_MODES], |
| 89 | |
| 90 | pub uv_mode_cfl_cdf: [[u16; UV_INTRA_MODES]; INTRA_MODES], |
| 91 | |
| 92 | pub cfl_alpha_cdf: [[u16; CFL_ALPHABET_SIZE]; CFL_ALPHA_CONTEXTS], |
| 93 | pub inter_tx_1_cdf: [[u16; TX_TYPES]; TX_SIZE_SQR_CONTEXTS], |
| 94 | |
| 95 | pub nmv_context: NMVContext, |
| 96 | } |
| 97 | |
| 98 | pub struct CDFOffset<const CDF_LEN: usize> { |
| 99 | offset: usize, |
| 100 | phantom: PhantomData<[u16; CDF_LEN]>, |
| 101 | } |
| 102 | |
| 103 | impl CDFContext { |
| 104 | pub fn new(quantizer: u8) -> CDFContext { |
| 105 | let qctx = match quantizer { |
| 106 | 0..=20 => 0, |
| 107 | 21..=60 => 1, |
| 108 | 61..=120 => 2, |
| 109 | _ => 3, |
| 110 | }; |
| 111 | CDFContext { |
| 112 | partition_w8_cdf: default_partition_w8_cdf, |
| 113 | partition_w128_cdf: default_partition_w128_cdf, |
| 114 | partition_cdf: default_partition_cdf, |
| 115 | kf_y_cdf: default_kf_y_mode_cdf, |
| 116 | y_mode_cdf: default_if_y_mode_cdf, |
| 117 | uv_mode_cdf: default_uv_mode_cdf, |
| 118 | uv_mode_cfl_cdf: default_uv_mode_cfl_cdf, |
| 119 | cfl_sign_cdf: default_cfl_sign_cdf, |
| 120 | cfl_alpha_cdf: default_cfl_alpha_cdf, |
| 121 | newmv_cdf: default_newmv_cdf, |
| 122 | zeromv_cdf: default_zeromv_cdf, |
| 123 | refmv_cdf: default_refmv_cdf, |
| 124 | intra_tx_2_cdf: default_intra_tx_2_cdf, |
| 125 | intra_tx_1_cdf: default_intra_tx_1_cdf, |
| 126 | inter_tx_3_cdf: default_inter_tx_3_cdf, |
| 127 | inter_tx_2_cdf: default_inter_tx_2_cdf, |
| 128 | inter_tx_1_cdf: default_inter_tx_1_cdf, |
| 129 | tx_size_8x8_cdf: default_tx_size_8x8_cdf, |
| 130 | tx_size_cdf: default_tx_size_cdf, |
| 131 | txfm_partition_cdf: default_txfm_partition_cdf, |
| 132 | skip_cdfs: default_skip_cdfs, |
| 133 | intra_inter_cdfs: default_intra_inter_cdf, |
| 134 | angle_delta_cdf: default_angle_delta_cdf, |
| 135 | filter_intra_cdfs: default_filter_intra_cdfs, |
| 136 | palette_y_mode_cdfs: default_palette_y_mode_cdfs, |
| 137 | palette_uv_mode_cdfs: default_palette_uv_mode_cdfs, |
| 138 | comp_mode_cdf: default_comp_mode_cdf, |
| 139 | comp_ref_type_cdf: default_comp_ref_type_cdf, |
| 140 | comp_ref_cdf: default_comp_ref_cdf, |
| 141 | comp_bwd_ref_cdf: default_comp_bwdref_cdf, |
| 142 | single_ref_cdfs: default_single_ref_cdf, |
| 143 | drl_cdfs: default_drl_cdf, |
| 144 | compound_mode_cdf: default_compound_mode_cdf, |
| 145 | nmv_context: default_nmv_context, |
| 146 | deblock_delta_multi_cdf: default_delta_lf_multi_cdf, |
| 147 | deblock_delta_cdf: default_delta_lf_cdf, |
| 148 | spatial_segmentation_cdfs: default_spatial_pred_seg_tree_cdf, |
| 149 | lrf_switchable_cdf: default_switchable_restore_cdf, |
| 150 | lrf_sgrproj_cdf: default_sgrproj_restore_cdf, |
| 151 | lrf_wiener_cdf: default_wiener_restore_cdf, |
| 152 | |
| 153 | // lv_map |
| 154 | txb_skip_cdf: av1_default_txb_skip_cdfs[qctx], |
| 155 | dc_sign_cdf: av1_default_dc_sign_cdfs[qctx], |
| 156 | eob_extra_cdf: av1_default_eob_extra_cdfs[qctx], |
| 157 | |
| 158 | eob_flag_cdf16: av1_default_eob_multi16_cdfs[qctx], |
| 159 | eob_flag_cdf32: av1_default_eob_multi32_cdfs[qctx], |
| 160 | eob_flag_cdf64: av1_default_eob_multi64_cdfs[qctx], |
| 161 | eob_flag_cdf128: av1_default_eob_multi128_cdfs[qctx], |
| 162 | eob_flag_cdf256: av1_default_eob_multi256_cdfs[qctx], |
| 163 | eob_flag_cdf512: av1_default_eob_multi512_cdfs[qctx], |
| 164 | eob_flag_cdf1024: av1_default_eob_multi1024_cdfs[qctx], |
| 165 | |
| 166 | coeff_base_eob_cdf: av1_default_coeff_base_eob_multi_cdfs[qctx], |
| 167 | coeff_base_cdf: av1_default_coeff_base_multi_cdfs[qctx], |
| 168 | coeff_br_cdf: av1_default_coeff_lps_multi_cdfs[qctx], |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | pub fn reset_counts(&mut self) { |
| 173 | macro_rules! reset_1d { |
| 174 | ($field:expr) => { |
| 175 | let r = $field.last_mut().unwrap(); |
| 176 | *r = 0; |
| 177 | }; |
| 178 | } |
| 179 | macro_rules! reset_2d { |
| 180 | ($field:expr) => { |
| 181 | for x in $field.iter_mut() { |
| 182 | reset_1d!(x); |
| 183 | } |
| 184 | }; |
| 185 | } |
| 186 | macro_rules! reset_3d { |
| 187 | ($field:expr) => { |
| 188 | for x in $field.iter_mut() { |
| 189 | reset_2d!(x); |
| 190 | } |
| 191 | }; |
| 192 | } |
| 193 | macro_rules! reset_4d { |
| 194 | ($field:expr) => { |
| 195 | for x in $field.iter_mut() { |
| 196 | reset_3d!(x); |
| 197 | } |
| 198 | }; |
| 199 | } |
| 200 | |
| 201 | reset_2d!(self.partition_w8_cdf); |
| 202 | reset_2d!(self.partition_w128_cdf); |
| 203 | reset_2d!(self.partition_cdf); |
| 204 | |
| 205 | reset_3d!(self.kf_y_cdf); |
| 206 | reset_2d!(self.y_mode_cdf); |
| 207 | |
| 208 | reset_2d!(self.uv_mode_cdf); |
| 209 | reset_2d!(self.uv_mode_cfl_cdf); |
| 210 | reset_1d!(self.cfl_sign_cdf); |
| 211 | reset_2d!(self.cfl_alpha_cdf); |
| 212 | reset_2d!(self.newmv_cdf); |
| 213 | reset_2d!(self.zeromv_cdf); |
| 214 | reset_2d!(self.refmv_cdf); |
| 215 | |
| 216 | reset_3d!(self.intra_tx_2_cdf); |
| 217 | reset_3d!(self.intra_tx_1_cdf); |
| 218 | |
| 219 | reset_2d!(self.inter_tx_3_cdf); |
| 220 | reset_2d!(self.inter_tx_2_cdf); |
| 221 | reset_2d!(self.inter_tx_1_cdf); |
| 222 | |
| 223 | reset_2d!(self.tx_size_8x8_cdf); |
| 224 | reset_3d!(self.tx_size_cdf); |
| 225 | |
| 226 | reset_2d!(self.txfm_partition_cdf); |
| 227 | |
| 228 | reset_2d!(self.skip_cdfs); |
| 229 | reset_2d!(self.intra_inter_cdfs); |
| 230 | reset_2d!(self.angle_delta_cdf); |
| 231 | reset_2d!(self.filter_intra_cdfs); |
| 232 | reset_3d!(self.palette_y_mode_cdfs); |
| 233 | reset_2d!(self.palette_uv_mode_cdfs); |
| 234 | reset_2d!(self.comp_mode_cdf); |
| 235 | reset_2d!(self.comp_ref_type_cdf); |
| 236 | reset_3d!(self.comp_ref_cdf); |
| 237 | reset_3d!(self.comp_bwd_ref_cdf); |
| 238 | reset_3d!(self.single_ref_cdfs); |
| 239 | reset_2d!(self.drl_cdfs); |
| 240 | reset_2d!(self.compound_mode_cdf); |
| 241 | reset_2d!(self.deblock_delta_multi_cdf); |
| 242 | reset_1d!(self.deblock_delta_cdf); |
| 243 | reset_2d!(self.spatial_segmentation_cdfs); |
| 244 | reset_1d!(self.lrf_switchable_cdf); |
| 245 | reset_1d!(self.lrf_sgrproj_cdf); |
| 246 | reset_1d!(self.lrf_wiener_cdf); |
| 247 | |
| 248 | reset_1d!(self.nmv_context.joints_cdf); |
| 249 | for i in 0..2 { |
| 250 | reset_1d!(self.nmv_context.comps[i].classes_cdf); |
| 251 | reset_2d!(self.nmv_context.comps[i].class0_fp_cdf); |
| 252 | reset_1d!(self.nmv_context.comps[i].fp_cdf); |
| 253 | reset_1d!(self.nmv_context.comps[i].sign_cdf); |
| 254 | reset_1d!(self.nmv_context.comps[i].class0_hp_cdf); |
| 255 | reset_1d!(self.nmv_context.comps[i].hp_cdf); |
| 256 | reset_1d!(self.nmv_context.comps[i].class0_cdf); |
| 257 | reset_2d!(self.nmv_context.comps[i].bits_cdf); |
| 258 | } |
| 259 | |
| 260 | // lv_map |
| 261 | reset_3d!(self.txb_skip_cdf); |
| 262 | reset_3d!(self.dc_sign_cdf); |
| 263 | reset_4d!(self.eob_extra_cdf); |
| 264 | |
| 265 | reset_3d!(self.eob_flag_cdf16); |
| 266 | reset_3d!(self.eob_flag_cdf32); |
| 267 | reset_3d!(self.eob_flag_cdf64); |
| 268 | reset_3d!(self.eob_flag_cdf128); |
| 269 | reset_3d!(self.eob_flag_cdf256); |
| 270 | reset_3d!(self.eob_flag_cdf512); |
| 271 | reset_3d!(self.eob_flag_cdf1024); |
| 272 | |
| 273 | reset_4d!(self.coeff_base_eob_cdf); |
| 274 | reset_4d!(self.coeff_base_cdf); |
| 275 | reset_4d!(self.coeff_br_cdf); |
| 276 | } |
| 277 | |
| 278 | /// # Panics |
| 279 | /// |
| 280 | /// - If any of the CDF arrays are uninitialized. |
| 281 | /// This should never happen and indicates a development error. |
| 282 | pub fn build_map(&self) -> Vec<(&'static str, usize, usize)> { |
| 283 | use std::mem::size_of_val; |
| 284 | |
| 285 | let partition_w8_cdf_start = |
| 286 | self.partition_w8_cdf.first().unwrap().as_ptr() as usize; |
| 287 | let partition_w8_cdf_end = |
| 288 | partition_w8_cdf_start + size_of_val(&self.partition_w8_cdf); |
| 289 | let partition_w128_cdf_start = |
| 290 | self.partition_w128_cdf.first().unwrap().as_ptr() as usize; |
| 291 | let partition_w128_cdf_end = |
| 292 | partition_w128_cdf_start + size_of_val(&self.partition_w128_cdf); |
| 293 | let partition_cdf_start = |
| 294 | self.partition_cdf.first().unwrap().as_ptr() as usize; |
| 295 | let partition_cdf_end = |
| 296 | partition_cdf_start + size_of_val(&self.partition_cdf); |
| 297 | let kf_y_cdf_start = self.kf_y_cdf.first().unwrap().as_ptr() as usize; |
| 298 | let kf_y_cdf_end = kf_y_cdf_start + size_of_val(&self.kf_y_cdf); |
| 299 | let y_mode_cdf_start = self.y_mode_cdf.first().unwrap().as_ptr() as usize; |
| 300 | let y_mode_cdf_end = y_mode_cdf_start + size_of_val(&self.y_mode_cdf); |
| 301 | let uv_mode_cdf_start = |
| 302 | self.uv_mode_cdf.first().unwrap().as_ptr() as usize; |
| 303 | let uv_mode_cdf_end = uv_mode_cdf_start + size_of_val(&self.uv_mode_cdf); |
| 304 | let uv_mode_cfl_cdf_start = |
| 305 | self.uv_mode_cfl_cdf.first().unwrap().as_ptr() as usize; |
| 306 | let uv_mode_cfl_cdf_end = |
| 307 | uv_mode_cfl_cdf_start + size_of_val(&self.uv_mode_cfl_cdf); |
| 308 | let cfl_sign_cdf_start = self.cfl_sign_cdf.as_ptr() as usize; |
| 309 | let cfl_sign_cdf_end = |
| 310 | cfl_sign_cdf_start + size_of_val(&self.cfl_sign_cdf); |
| 311 | let cfl_alpha_cdf_start = |
| 312 | self.cfl_alpha_cdf.first().unwrap().as_ptr() as usize; |
| 313 | let cfl_alpha_cdf_end = |
| 314 | cfl_alpha_cdf_start + size_of_val(&self.cfl_alpha_cdf); |
| 315 | let newmv_cdf_start = self.newmv_cdf.first().unwrap().as_ptr() as usize; |
| 316 | let newmv_cdf_end = newmv_cdf_start + size_of_val(&self.newmv_cdf); |
| 317 | let zeromv_cdf_start = self.zeromv_cdf.first().unwrap().as_ptr() as usize; |
| 318 | let zeromv_cdf_end = zeromv_cdf_start + size_of_val(&self.zeromv_cdf); |
| 319 | let refmv_cdf_start = self.refmv_cdf.first().unwrap().as_ptr() as usize; |
| 320 | let refmv_cdf_end = refmv_cdf_start + size_of_val(&self.refmv_cdf); |
| 321 | let intra_tx_2_cdf_start = |
| 322 | self.intra_tx_2_cdf.first().unwrap().as_ptr() as usize; |
| 323 | let intra_tx_2_cdf_end = |
| 324 | intra_tx_2_cdf_start + size_of_val(&self.intra_tx_2_cdf); |
| 325 | let intra_tx_1_cdf_start = |
| 326 | self.intra_tx_1_cdf.first().unwrap().as_ptr() as usize; |
| 327 | let intra_tx_1_cdf_end = |
| 328 | intra_tx_1_cdf_start + size_of_val(&self.intra_tx_1_cdf); |
| 329 | let inter_tx_3_cdf_start = |
| 330 | self.inter_tx_3_cdf.first().unwrap().as_ptr() as usize; |
| 331 | let inter_tx_3_cdf_end = |
| 332 | inter_tx_3_cdf_start + size_of_val(&self.inter_tx_3_cdf); |
| 333 | let inter_tx_2_cdf_start = |
| 334 | self.inter_tx_2_cdf.first().unwrap().as_ptr() as usize; |
| 335 | let inter_tx_2_cdf_end = |
| 336 | inter_tx_2_cdf_start + size_of_val(&self.inter_tx_2_cdf); |
| 337 | let inter_tx_1_cdf_start = |
| 338 | self.inter_tx_1_cdf.first().unwrap().as_ptr() as usize; |
| 339 | let inter_tx_1_cdf_end = |
| 340 | inter_tx_1_cdf_start + size_of_val(&self.inter_tx_1_cdf); |
| 341 | let tx_size_8x8_cdf_start = |
| 342 | self.tx_size_8x8_cdf.first().unwrap().as_ptr() as usize; |
| 343 | let tx_size_8x8_cdf_end = |
| 344 | tx_size_8x8_cdf_start + size_of_val(&self.tx_size_8x8_cdf); |
| 345 | let tx_size_cdf_start = |
| 346 | self.tx_size_cdf.first().unwrap().as_ptr() as usize; |
| 347 | let tx_size_cdf_end = tx_size_cdf_start + size_of_val(&self.tx_size_cdf); |
| 348 | let txfm_partition_cdf_start = |
| 349 | self.txfm_partition_cdf.first().unwrap().as_ptr() as usize; |
| 350 | let txfm_partition_cdf_end = |
| 351 | txfm_partition_cdf_start + size_of_val(&self.txfm_partition_cdf); |
| 352 | let skip_cdfs_start = self.skip_cdfs.first().unwrap().as_ptr() as usize; |
| 353 | let skip_cdfs_end = skip_cdfs_start + size_of_val(&self.skip_cdfs); |
| 354 | let intra_inter_cdfs_start = |
| 355 | self.intra_inter_cdfs.first().unwrap().as_ptr() as usize; |
| 356 | let intra_inter_cdfs_end = |
| 357 | intra_inter_cdfs_start + size_of_val(&self.intra_inter_cdfs); |
| 358 | let angle_delta_cdf_start = |
| 359 | self.angle_delta_cdf.first().unwrap().as_ptr() as usize; |
| 360 | let angle_delta_cdf_end = |
| 361 | angle_delta_cdf_start + size_of_val(&self.angle_delta_cdf); |
| 362 | let filter_intra_cdfs_start = |
| 363 | self.filter_intra_cdfs.first().unwrap().as_ptr() as usize; |
| 364 | let filter_intra_cdfs_end = |
| 365 | filter_intra_cdfs_start + size_of_val(&self.filter_intra_cdfs); |
| 366 | let palette_y_mode_cdfs_start = |
| 367 | self.palette_y_mode_cdfs.first().unwrap().as_ptr() as usize; |
| 368 | let palette_y_mode_cdfs_end = |
| 369 | palette_y_mode_cdfs_start + size_of_val(&self.palette_y_mode_cdfs); |
| 370 | let palette_uv_mode_cdfs_start = |
| 371 | self.palette_uv_mode_cdfs.first().unwrap().as_ptr() as usize; |
| 372 | let palette_uv_mode_cdfs_end = |
| 373 | palette_uv_mode_cdfs_start + size_of_val(&self.palette_uv_mode_cdfs); |
| 374 | let comp_mode_cdf_start = |
| 375 | self.comp_mode_cdf.first().unwrap().as_ptr() as usize; |
| 376 | let comp_mode_cdf_end = |
| 377 | comp_mode_cdf_start + size_of_val(&self.comp_mode_cdf); |
| 378 | let comp_ref_type_cdf_start = |
| 379 | self.comp_ref_type_cdf.first().unwrap().as_ptr() as usize; |
| 380 | let comp_ref_type_cdf_end = |
| 381 | comp_ref_type_cdf_start + size_of_val(&self.comp_ref_type_cdf); |
| 382 | let comp_ref_cdf_start = |
| 383 | self.comp_ref_cdf.first().unwrap().as_ptr() as usize; |
| 384 | let comp_ref_cdf_end = |
| 385 | comp_ref_cdf_start + size_of_val(&self.comp_ref_cdf); |
| 386 | let comp_bwd_ref_cdf_start = |
| 387 | self.comp_bwd_ref_cdf.first().unwrap().as_ptr() as usize; |
| 388 | let comp_bwd_ref_cdf_end = |
| 389 | comp_bwd_ref_cdf_start + size_of_val(&self.comp_bwd_ref_cdf); |
| 390 | let single_ref_cdfs_start = |
| 391 | self.single_ref_cdfs.first().unwrap().as_ptr() as usize; |
| 392 | let single_ref_cdfs_end = |
| 393 | single_ref_cdfs_start + size_of_val(&self.single_ref_cdfs); |
| 394 | let drl_cdfs_start = self.drl_cdfs.first().unwrap().as_ptr() as usize; |
| 395 | let drl_cdfs_end = drl_cdfs_start + size_of_val(&self.drl_cdfs); |
| 396 | let compound_mode_cdf_start = |
| 397 | self.compound_mode_cdf.first().unwrap().as_ptr() as usize; |
| 398 | let compound_mode_cdf_end = |
| 399 | compound_mode_cdf_start + size_of_val(&self.compound_mode_cdf); |
| 400 | let nmv_context_start = &self.nmv_context as *const NMVContext as usize; |
| 401 | let nmv_context_end = nmv_context_start + size_of_val(&self.nmv_context); |
| 402 | let deblock_delta_multi_cdf_start = |
| 403 | self.deblock_delta_multi_cdf.first().unwrap().as_ptr() as usize; |
| 404 | let deblock_delta_multi_cdf_end = deblock_delta_multi_cdf_start |
| 405 | + size_of_val(&self.deblock_delta_multi_cdf); |
| 406 | let deblock_delta_cdf_start = self.deblock_delta_cdf.as_ptr() as usize; |
| 407 | let deblock_delta_cdf_end = |
| 408 | deblock_delta_cdf_start + size_of_val(&self.deblock_delta_cdf); |
| 409 | let spatial_segmentation_cdfs_start = |
| 410 | self.spatial_segmentation_cdfs.first().unwrap().as_ptr() as usize; |
| 411 | let spatial_segmentation_cdfs_end = spatial_segmentation_cdfs_start |
| 412 | + size_of_val(&self.spatial_segmentation_cdfs); |
| 413 | let lrf_switchable_cdf_start = self.lrf_switchable_cdf.as_ptr() as usize; |
| 414 | let lrf_switchable_cdf_end = |
| 415 | lrf_switchable_cdf_start + size_of_val(&self.lrf_switchable_cdf); |
| 416 | let lrf_sgrproj_cdf_start = self.lrf_sgrproj_cdf.as_ptr() as usize; |
| 417 | let lrf_sgrproj_cdf_end = |
| 418 | lrf_sgrproj_cdf_start + size_of_val(&self.lrf_sgrproj_cdf); |
| 419 | let lrf_wiener_cdf_start = self.lrf_wiener_cdf.as_ptr() as usize; |
| 420 | let lrf_wiener_cdf_end = |
| 421 | lrf_wiener_cdf_start + size_of_val(&self.lrf_wiener_cdf); |
| 422 | |
| 423 | let txb_skip_cdf_start = |
| 424 | self.txb_skip_cdf.first().unwrap().as_ptr() as usize; |
| 425 | let txb_skip_cdf_end = |
| 426 | txb_skip_cdf_start + size_of_val(&self.txb_skip_cdf); |
| 427 | let dc_sign_cdf_start = |
| 428 | self.dc_sign_cdf.first().unwrap().as_ptr() as usize; |
| 429 | let dc_sign_cdf_end = dc_sign_cdf_start + size_of_val(&self.dc_sign_cdf); |
| 430 | let eob_extra_cdf_start = |
| 431 | self.eob_extra_cdf.first().unwrap().as_ptr() as usize; |
| 432 | let eob_extra_cdf_end = |
| 433 | eob_extra_cdf_start + size_of_val(&self.eob_extra_cdf); |
| 434 | let eob_flag_cdf16_start = |
| 435 | self.eob_flag_cdf16.first().unwrap().as_ptr() as usize; |
| 436 | let eob_flag_cdf16_end = |
| 437 | eob_flag_cdf16_start + size_of_val(&self.eob_flag_cdf16); |
| 438 | let eob_flag_cdf32_start = |
| 439 | self.eob_flag_cdf32.first().unwrap().as_ptr() as usize; |
| 440 | let eob_flag_cdf32_end = |
| 441 | eob_flag_cdf32_start + size_of_val(&self.eob_flag_cdf32); |
| 442 | let eob_flag_cdf64_start = |
| 443 | self.eob_flag_cdf64.first().unwrap().as_ptr() as usize; |
| 444 | let eob_flag_cdf64_end = |
| 445 | eob_flag_cdf64_start + size_of_val(&self.eob_flag_cdf64); |
| 446 | let eob_flag_cdf128_start = |
| 447 | self.eob_flag_cdf128.first().unwrap().as_ptr() as usize; |
| 448 | let eob_flag_cdf128_end = |
| 449 | eob_flag_cdf128_start + size_of_val(&self.eob_flag_cdf128); |
| 450 | let eob_flag_cdf256_start = |
| 451 | self.eob_flag_cdf256.first().unwrap().as_ptr() as usize; |
| 452 | let eob_flag_cdf256_end = |
| 453 | eob_flag_cdf256_start + size_of_val(&self.eob_flag_cdf256); |
| 454 | let eob_flag_cdf512_start = |
| 455 | self.eob_flag_cdf512.first().unwrap().as_ptr() as usize; |
| 456 | let eob_flag_cdf512_end = |
| 457 | eob_flag_cdf512_start + size_of_val(&self.eob_flag_cdf512); |
| 458 | let eob_flag_cdf1024_start = |
| 459 | self.eob_flag_cdf1024.first().unwrap().as_ptr() as usize; |
| 460 | let eob_flag_cdf1024_end = |
| 461 | eob_flag_cdf1024_start + size_of_val(&self.eob_flag_cdf1024); |
| 462 | let coeff_base_eob_cdf_start = |
| 463 | self.coeff_base_eob_cdf.first().unwrap().as_ptr() as usize; |
| 464 | let coeff_base_eob_cdf_end = |
| 465 | coeff_base_eob_cdf_start + size_of_val(&self.coeff_base_eob_cdf); |
| 466 | let coeff_base_cdf_start = |
| 467 | self.coeff_base_cdf.first().unwrap().as_ptr() as usize; |
| 468 | let coeff_base_cdf_end = |
| 469 | coeff_base_cdf_start + size_of_val(&self.coeff_base_cdf); |
| 470 | let coeff_br_cdf_start = |
| 471 | self.coeff_br_cdf.first().unwrap().as_ptr() as usize; |
| 472 | let coeff_br_cdf_end = |
| 473 | coeff_br_cdf_start + size_of_val(&self.coeff_br_cdf); |
| 474 | |
| 475 | vec![ |
| 476 | ("partition_w8_cdf" , partition_w8_cdf_start, partition_w8_cdf_end), |
| 477 | ("partition_w128_cdf" , partition_w128_cdf_start, partition_w128_cdf_end), |
| 478 | ("partition_cdf" , partition_cdf_start, partition_cdf_end), |
| 479 | ("kf_y_cdf" , kf_y_cdf_start, kf_y_cdf_end), |
| 480 | ("y_mode_cdf" , y_mode_cdf_start, y_mode_cdf_end), |
| 481 | ("uv_mode_cdf" , uv_mode_cdf_start, uv_mode_cdf_end), |
| 482 | ("uv_mode_cfl_cdf" , uv_mode_cfl_cdf_start, uv_mode_cfl_cdf_end), |
| 483 | ("cfl_sign_cdf" , cfl_sign_cdf_start, cfl_sign_cdf_end), |
| 484 | ("cfl_alpha_cdf" , cfl_alpha_cdf_start, cfl_alpha_cdf_end), |
| 485 | ("newmv_cdf" , newmv_cdf_start, newmv_cdf_end), |
| 486 | ("zeromv_cdf" , zeromv_cdf_start, zeromv_cdf_end), |
| 487 | ("refmv_cdf" , refmv_cdf_start, refmv_cdf_end), |
| 488 | ("intra_tx_2_cdf" , intra_tx_2_cdf_start, intra_tx_2_cdf_end), |
| 489 | ("intra_tx_1_cdf" , intra_tx_1_cdf_start, intra_tx_1_cdf_end), |
| 490 | ("inter_tx_3_cdf" , inter_tx_3_cdf_start, inter_tx_3_cdf_end), |
| 491 | ("inter_tx_2_cdf" , inter_tx_2_cdf_start, inter_tx_2_cdf_end), |
| 492 | ("inter_tx_1_cdf" , inter_tx_1_cdf_start, inter_tx_1_cdf_end), |
| 493 | ("tx_size_8x8_cdf" , tx_size_8x8_cdf_start, tx_size_8x8_cdf_end), |
| 494 | ("tx_size_cdf" , tx_size_cdf_start, tx_size_cdf_end), |
| 495 | ("txfm_partition_cdf" , txfm_partition_cdf_start, txfm_partition_cdf_end), |
| 496 | ("skip_cdfs" , skip_cdfs_start, skip_cdfs_end), |
| 497 | ("intra_inter_cdfs" , intra_inter_cdfs_start, intra_inter_cdfs_end), |
| 498 | ("angle_delta_cdf" , angle_delta_cdf_start, angle_delta_cdf_end), |
| 499 | ("filter_intra_cdfs" , filter_intra_cdfs_start, filter_intra_cdfs_end), |
| 500 | ( |
| 501 | "palette_y_mode_cdfs" , |
| 502 | palette_y_mode_cdfs_start, |
| 503 | palette_y_mode_cdfs_end, |
| 504 | ), |
| 505 | ( |
| 506 | "palette_uv_mode_cdfs" , |
| 507 | palette_uv_mode_cdfs_start, |
| 508 | palette_uv_mode_cdfs_end, |
| 509 | ), |
| 510 | ("comp_mode_cdf" , comp_mode_cdf_start, comp_mode_cdf_end), |
| 511 | ("comp_ref_type_cdf" , comp_ref_type_cdf_start, comp_ref_type_cdf_end), |
| 512 | ("comp_ref_cdf" , comp_ref_cdf_start, comp_ref_cdf_end), |
| 513 | ("comp_bwd_ref_cdf" , comp_bwd_ref_cdf_start, comp_bwd_ref_cdf_end), |
| 514 | ("single_ref_cdfs" , single_ref_cdfs_start, single_ref_cdfs_end), |
| 515 | ("drl_cdfs" , drl_cdfs_start, drl_cdfs_end), |
| 516 | ("compound_mode_cdf" , compound_mode_cdf_start, compound_mode_cdf_end), |
| 517 | ("nmv_context" , nmv_context_start, nmv_context_end), |
| 518 | ( |
| 519 | "deblock_delta_multi_cdf" , |
| 520 | deblock_delta_multi_cdf_start, |
| 521 | deblock_delta_multi_cdf_end, |
| 522 | ), |
| 523 | ("deblock_delta_cdf" , deblock_delta_cdf_start, deblock_delta_cdf_end), |
| 524 | ( |
| 525 | "spatial_segmentation_cdfs" , |
| 526 | spatial_segmentation_cdfs_start, |
| 527 | spatial_segmentation_cdfs_end, |
| 528 | ), |
| 529 | ("lrf_switchable_cdf" , lrf_switchable_cdf_start, lrf_switchable_cdf_end), |
| 530 | ("lrf_sgrproj_cdf" , lrf_sgrproj_cdf_start, lrf_sgrproj_cdf_end), |
| 531 | ("lrf_wiener_cdf" , lrf_wiener_cdf_start, lrf_wiener_cdf_end), |
| 532 | ("txb_skip_cdf" , txb_skip_cdf_start, txb_skip_cdf_end), |
| 533 | ("dc_sign_cdf" , dc_sign_cdf_start, dc_sign_cdf_end), |
| 534 | ("eob_extra_cdf" , eob_extra_cdf_start, eob_extra_cdf_end), |
| 535 | ("eob_flag_cdf16" , eob_flag_cdf16_start, eob_flag_cdf16_end), |
| 536 | ("eob_flag_cdf32" , eob_flag_cdf32_start, eob_flag_cdf32_end), |
| 537 | ("eob_flag_cdf64" , eob_flag_cdf64_start, eob_flag_cdf64_end), |
| 538 | ("eob_flag_cdf128" , eob_flag_cdf128_start, eob_flag_cdf128_end), |
| 539 | ("eob_flag_cdf256" , eob_flag_cdf256_start, eob_flag_cdf256_end), |
| 540 | ("eob_flag_cdf512" , eob_flag_cdf512_start, eob_flag_cdf512_end), |
| 541 | ("eob_flag_cdf1024" , eob_flag_cdf1024_start, eob_flag_cdf1024_end), |
| 542 | ("coeff_base_eob_cdf" , coeff_base_eob_cdf_start, coeff_base_eob_cdf_end), |
| 543 | ("coeff_base_cdf" , coeff_base_cdf_start, coeff_base_cdf_end), |
| 544 | ("coeff_br_cdf" , coeff_br_cdf_start, coeff_br_cdf_end), |
| 545 | ] |
| 546 | } |
| 547 | |
| 548 | pub fn offset<const CDF_LEN: usize>( |
| 549 | &self, cdf: *const [u16; CDF_LEN], |
| 550 | ) -> CDFOffset<CDF_LEN> { |
| 551 | CDFOffset { |
| 552 | offset: cdf as usize - self as *const _ as usize, |
| 553 | phantom: PhantomData, |
| 554 | } |
| 555 | } |
| 556 | } |
| 557 | |
| 558 | impl fmt::Debug for CDFContext { |
| 559 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 560 | write!(f, "CDFContext contains too many numbers to print :-(" ) |
| 561 | } |
| 562 | } |
| 563 | |
| 564 | macro_rules! symbol_with_update { |
| 565 | ($self:ident, $w:ident, $s:expr, $cdf:expr) => { |
| 566 | let cdf = $self.fc.offset($cdf); |
| 567 | $w.symbol_with_update($s, cdf, &mut $self.fc_log, &mut $self.fc); |
| 568 | symbol_with_update!($self, $cdf); |
| 569 | }; |
| 570 | ($self:ident, $cdf:expr) => { |
| 571 | #[cfg(feature = "desync_finder" )] |
| 572 | { |
| 573 | let cdf: &[_] = $cdf; |
| 574 | if let Some(map) = $self.fc_map.as_ref() { |
| 575 | map.lookup(cdf.as_ptr() as usize); |
| 576 | } |
| 577 | } |
| 578 | }; |
| 579 | } |
| 580 | |
| 581 | #[derive (Clone)] |
| 582 | pub struct ContextWriterCheckpoint { |
| 583 | pub fc: CDFContextCheckpoint, |
| 584 | pub bc: BlockContextCheckpoint, |
| 585 | } |
| 586 | |
| 587 | struct CDFContextLogPartition<const CDF_LEN_MAX_PLUS_1: usize> { |
| 588 | pub data: Vec<[u16; CDF_LEN_MAX_PLUS_1]>, |
| 589 | } |
| 590 | |
| 591 | impl<const CDF_LEN_MAX_PLUS_1: usize> |
| 592 | CDFContextLogPartition<CDF_LEN_MAX_PLUS_1> |
| 593 | { |
| 594 | fn new(capacity: usize) -> Self { |
| 595 | Self { data: Vec::with_capacity(capacity) } |
| 596 | } |
| 597 | #[inline (always)] |
| 598 | fn push<const CDF_LEN: usize>( |
| 599 | &mut self, fc: &mut CDFContext, cdf: CDFOffset<CDF_LEN>, |
| 600 | ) -> &mut [u16; CDF_LEN] { |
| 601 | debug_assert!(CDF_LEN < CDF_LEN_MAX_PLUS_1); |
| 602 | debug_assert!(cdf.offset <= u16::MAX.into()); |
| 603 | // SAFETY: Maintain an invariant of non-zero spare capacity, so that |
| 604 | // branching may be deferred until writes are issued. Benchmarks indicate |
| 605 | // this is faster than first testing capacity and possibly reallocating. |
| 606 | unsafe { |
| 607 | let len = self.data.len(); |
| 608 | let new_len = len + 1; |
| 609 | let capacity = self.data.capacity(); |
| 610 | debug_assert!(new_len <= capacity); |
| 611 | let dst = self.data.as_mut_ptr().add(len) as *mut u16; |
| 612 | let base = fc as *mut _ as *mut u8; |
| 613 | let src = base.add(cdf.offset) as *const u16; |
| 614 | dst.copy_from_nonoverlapping(src, CDF_LEN_MAX_PLUS_1 - 1); |
| 615 | *dst.add(CDF_LEN_MAX_PLUS_1 - 1) = cdf.offset as u16; |
| 616 | self.data.set_len(new_len); |
| 617 | if CDF_LEN_MAX_PLUS_1 > capacity.wrapping_sub(new_len) { |
| 618 | self.data.reserve(CDF_LEN_MAX_PLUS_1); |
| 619 | } |
| 620 | let cdf = base.add(cdf.offset) as *mut [u16; CDF_LEN]; |
| 621 | &mut *cdf |
| 622 | } |
| 623 | } |
| 624 | #[inline (always)] |
| 625 | fn rollback(&mut self, fc: &mut CDFContext, checkpoint: usize) { |
| 626 | let base = fc as *mut _ as *mut u8; |
| 627 | let mut len = self.data.len(); |
| 628 | // SAFETY: We use unchecked pointers here for performance. |
| 629 | // Since we know the length, we can ensure not to go OOB. |
| 630 | unsafe { |
| 631 | let mut src = self.data.as_mut_ptr().add(len); |
| 632 | while len > checkpoint { |
| 633 | len -= 1; |
| 634 | src = src.sub(1); |
| 635 | let src = src as *mut u16; |
| 636 | let offset = *src.add(CDF_LEN_MAX_PLUS_1 - 1) as usize; |
| 637 | let dst = base.add(offset) as *mut u16; |
| 638 | dst.copy_from_nonoverlapping(src, CDF_LEN_MAX_PLUS_1 - 1); |
| 639 | } |
| 640 | self.data.set_len(len); |
| 641 | } |
| 642 | } |
| 643 | } |
| 644 | |
| 645 | const CDF_LEN_SMALL: usize = 4; |
| 646 | |
| 647 | pub struct CDFContextLog { |
| 648 | small: CDFContextLogPartition<{ CDF_LEN_SMALL + 1 }>, |
| 649 | large: CDFContextLogPartition<{ CDF_LEN_MAX + 1 }>, |
| 650 | } |
| 651 | |
| 652 | impl Default for CDFContextLog { |
| 653 | fn default() -> Self { |
| 654 | Self { |
| 655 | small: CDFContextLogPartition::new(capacity:1 << 16), |
| 656 | large: CDFContextLogPartition::new(capacity:1 << 9), |
| 657 | } |
| 658 | } |
| 659 | } |
| 660 | |
| 661 | impl CDFContextLog { |
| 662 | fn checkpoint(&self) -> CDFContextCheckpoint { |
| 663 | CDFContextCheckpoint { |
| 664 | small: self.small.data.len(), |
| 665 | large: self.large.data.len(), |
| 666 | } |
| 667 | } |
| 668 | #[inline (always)] |
| 669 | pub fn push<const CDF_LEN: usize>( |
| 670 | &mut self, fc: &mut CDFContext, cdf: CDFOffset<CDF_LEN>, |
| 671 | ) -> &mut [u16; CDF_LEN] { |
| 672 | if CDF_LEN <= CDF_LEN_SMALL { |
| 673 | self.small.push(fc, cdf) |
| 674 | } else { |
| 675 | self.large.push(fc, cdf) |
| 676 | } |
| 677 | } |
| 678 | #[inline (always)] |
| 679 | pub fn rollback( |
| 680 | &mut self, fc: &mut CDFContext, checkpoint: &CDFContextCheckpoint, |
| 681 | ) { |
| 682 | self.small.rollback(fc, checkpoint.small); |
| 683 | self.large.rollback(fc, checkpoint.large); |
| 684 | } |
| 685 | pub fn clear(&mut self) { |
| 686 | self.small.data.clear(); |
| 687 | self.large.data.clear(); |
| 688 | } |
| 689 | } |
| 690 | |
| 691 | pub struct ContextWriter<'a> { |
| 692 | pub bc: BlockContext<'a>, |
| 693 | pub fc: &'a mut CDFContext, |
| 694 | pub fc_log: CDFContextLog, |
| 695 | #[cfg (feature = "desync_finder" )] |
| 696 | pub fc_map: Option<FieldMap>, // For debugging purposes |
| 697 | } |
| 698 | |
| 699 | impl<'a> ContextWriter<'a> { |
| 700 | #[allow (clippy::let_and_return)] |
| 701 | pub fn new(fc: &'a mut CDFContext, bc: BlockContext<'a>) -> Self { |
| 702 | let fc_log = CDFContextLog::default(); |
| 703 | #[allow (unused_mut)] |
| 704 | let mut cw = ContextWriter { |
| 705 | bc, |
| 706 | fc, |
| 707 | fc_log, |
| 708 | #[cfg (feature = "desync_finder" )] |
| 709 | fc_map: Default::default(), |
| 710 | }; |
| 711 | #[cfg (feature = "desync_finder" )] |
| 712 | { |
| 713 | if std::env::var_os("RAV1E_DEBUG" ).is_some() { |
| 714 | cw.fc_map = Some(FieldMap { map: cw.fc.build_map() }); |
| 715 | } |
| 716 | } |
| 717 | |
| 718 | cw |
| 719 | } |
| 720 | |
| 721 | pub const fn cdf_element_prob(cdf: &[u16], element: usize) -> u16 { |
| 722 | (if element > 0 { cdf[element - 1] } else { 32768 }) |
| 723 | - (if element + 1 < cdf.len() { cdf[element] } else { 0 }) |
| 724 | } |
| 725 | |
| 726 | pub fn checkpoint( |
| 727 | &self, tile_bo: &TileBlockOffset, chroma_sampling: ChromaSampling, |
| 728 | ) -> ContextWriterCheckpoint { |
| 729 | ContextWriterCheckpoint { |
| 730 | fc: self.fc_log.checkpoint(), |
| 731 | bc: self.bc.checkpoint(tile_bo, chroma_sampling), |
| 732 | } |
| 733 | } |
| 734 | |
| 735 | pub fn rollback(&mut self, checkpoint: &ContextWriterCheckpoint) { |
| 736 | self.fc_log.rollback(self.fc, &checkpoint.fc); |
| 737 | self.bc.rollback(&checkpoint.bc); |
| 738 | #[cfg (feature = "desync_finder" )] |
| 739 | { |
| 740 | if self.fc_map.is_some() { |
| 741 | self.fc_map = Some(FieldMap { map: self.fc.build_map() }); |
| 742 | } |
| 743 | } |
| 744 | } |
| 745 | } |
| 746 | |