• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The libgav1 Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/symbol_decoder_context.h"
16 
17 #include <cstdint>
18 #include <cstring>
19 
20 #include "gtest/gtest.h"
21 #include "src/utils/constants.h"
22 
23 namespace libgav1 {
24 namespace {
25 
TEST(SymbolDecoderContextTest,ResetIntraFrameYModeCdf)26 TEST(SymbolDecoderContextTest, ResetIntraFrameYModeCdf) {
27   // Note these are zero-initialized separately to avoid differences in padding
28   // values added to tables for alignment purposes when comparing the contexts
29   // with memcmp().
30   libgav1::SymbolDecoderContext gold_context = {};
31   libgav1::SymbolDecoderContext context = {};
32   gold_context.Initialize(0);
33   context.Initialize(0);
34   EXPECT_EQ(memcmp(&gold_context, &context, sizeof(gold_context)), 0);
35   EXPECT_EQ(context.intra_frame_y_mode_cdf[0][0][0], 32768 - 15588);
36   EXPECT_EQ(context.intra_frame_y_mode_cdf[0][0][1], 32768 - 17027);
37   ++context.intra_frame_y_mode_cdf[0][0][0];
38   --context.intra_frame_y_mode_cdf[0][0][1];
39   EXPECT_NE(memcmp(&gold_context, &context, sizeof(gold_context)), 0);
40   context.ResetIntraFrameYModeCdf();
41   EXPECT_EQ(memcmp(&gold_context, &context, sizeof(gold_context)), 0);
42 }
43 
ResetAndVerifyCounters(libgav1::SymbolDecoderContext * const context)44 void ResetAndVerifyCounters(libgav1::SymbolDecoderContext* const context) {
45   libgav1::SymbolDecoderContext gold_context = {};
46   gold_context.Initialize(0);
47   EXPECT_NE(memcmp(&gold_context, context, sizeof(gold_context)), 0);
48   context->ResetCounters();
49   EXPECT_EQ(memcmp(&gold_context, context, sizeof(gold_context)), 0);
50 }
51 
TEST(SymbolDecoderContextTest,ResetCounters1d)52 TEST(SymbolDecoderContextTest, ResetCounters1d) {
53   libgav1::SymbolDecoderContext context = {};
54   context.Initialize(0);
55   int value = 0;
56   context.delta_q_cdf[libgav1::kDeltaSymbolCount] = ++value;
57   context.delta_lf_cdf[libgav1::kDeltaSymbolCount] = ++value;
58   context.intra_block_copy_cdf[libgav1::kBooleanSymbolCount] = ++value;
59   context.cfl_alpha_signs_cdf[libgav1::kCflAlphaSignsSymbolCount] = ++value;
60   context.filter_intra_mode_cdf[libgav1::kNumFilterIntraPredictors] = ++value;
61   context.restoration_type_cdf[libgav1::kRestorationTypeSymbolCount] = ++value;
62   context.use_wiener_cdf[libgav1::kBooleanSymbolCount] = ++value;
63   context.use_sgrproj_cdf[libgav1::kBooleanSymbolCount] = ++value;
64   ResetAndVerifyCounters(&context);
65 }
66 
IncreasePartitionCounters(SymbolDecoderContext * symbol_context,int value)67 void IncreasePartitionCounters(SymbolDecoderContext* symbol_context,
68                                int value) {
69   const int min_bsize_log2 = k4x4WidthLog2[kBlock8x8];
70   const int max_bsize_log2 = k4x4WidthLog2[kBlock128x128];
71   for (int block_size_log2 = min_bsize_log2; block_size_log2 <= max_bsize_log2;
72        ++block_size_log2) {
73     for (int context = 0; context < kPartitionContexts; ++context) {
74       const int cdf_size =
75           SymbolDecoderContext::PartitionCdfSize(block_size_log2);
76       symbol_context->partition_cdf[block_size_log2 - min_bsize_log2][context]
77                                    [cdf_size] += value;
78     }
79   }
80 }
81 
IncreasePaletteColorIndexCounters(SymbolDecoderContext * symbol_context,int value)82 void IncreasePaletteColorIndexCounters(SymbolDecoderContext* symbol_context,
83                                        int value) {
84   for (auto& palette_color_index_cdf_plane :
85        symbol_context->palette_color_index_cdf) {
86     for (int symbol_count = 0; symbol_count < kPaletteSizeSymbolCount;
87          ++symbol_count) {
88       const int cdf_size = symbol_count + kMinPaletteSize;
89       for (int context = 0; context < kPaletteColorIndexContexts; ++context) {
90         palette_color_index_cdf_plane[symbol_count][context][cdf_size] += value;
91       }
92     }
93   }
94 }
95 
IncreaseTxTypeCounters(SymbolDecoderContext * context,int value)96 void IncreaseTxTypeCounters(SymbolDecoderContext* context, int value) {
97   for (int set_idx = kTransformSetIntra1; set_idx <= kTransformSetIntra2;
98        ++set_idx) {
99     auto tx_set = static_cast<TransformSet>(set_idx);
100     for (int tx_size = 0; tx_size < kNumExtendedTransformSizes; ++tx_size) {
101       for (int mode = 0; mode < kIntraPredictionModesY; ++mode) {
102         context->intra_tx_type_cdf[SymbolDecoderContext::TxTypeIndex(
103             tx_set)][tx_size][mode][kNumTransformTypesInSet[tx_set]] += value;
104       }
105     }
106   }
107 
108   for (int set_idx = kTransformSetInter1; set_idx <= kTransformSetInter3;
109        ++set_idx) {
110     auto tx_set = static_cast<TransformSet>(set_idx);
111     for (int tx_size = 0; tx_size < kNumExtendedTransformSizes; ++tx_size) {
112       context->inter_tx_type_cdf[SymbolDecoderContext::TxTypeIndex(tx_set)]
113                                 [tx_size][kNumTransformTypesInSet[tx_set]] +=
114           value;
115     }
116   }
117 }
118 
IncreaseTxDepthCounters(SymbolDecoderContext * symbol_context,int value)119 void IncreaseTxDepthCounters(SymbolDecoderContext* symbol_context, int value) {
120   for (int context = 0; context < kTxDepthContexts; ++context) {
121     symbol_context->tx_depth_cdf[0][context][kMaxTxDepthSymbolCount - 1] +=
122         value;
123   }
124 
125   for (int plane_category = 1; plane_category < 4; ++plane_category) {
126     for (int context = 0; context < kTxDepthContexts; ++context) {
127       symbol_context
128           ->tx_depth_cdf[plane_category][context][kMaxTxDepthSymbolCount] +=
129           value;
130     }
131   }
132 }
133 
IncreaseUVModeCounters(SymbolDecoderContext * symbol_context,int value)134 void IncreaseUVModeCounters(SymbolDecoderContext* symbol_context, int value) {
135   for (int cfl_allowed = 0; cfl_allowed < kBooleanSymbolCount; ++cfl_allowed) {
136     for (int mode = 0; mode < kIntraPredictionModesY; ++mode) {
137       symbol_context->uv_mode_cdf[cfl_allowed][mode][kIntraPredictionModesUV -
138                                                      (1 - cfl_allowed)] +=
139           value;
140     }
141   }
142 }
143 
144 #define ASSIGN_COUNTER_2D(array, offset) \
145   do {                                   \
146     for (auto& d1 : context.array) {     \
147       d1[libgav1::offset] = ++value;     \
148     }                                    \
149   } while (false)
150 
TEST(SymbolDecoderContextTest,ResetCounters2d)151 TEST(SymbolDecoderContextTest, ResetCounters2d) {
152   libgav1::SymbolDecoderContext context = {};
153   context.Initialize(0);
154   int value = 0;
155   ASSIGN_COUNTER_2D(segment_id_cdf, kMaxSegments);
156   ASSIGN_COUNTER_2D(use_predicted_segment_id_cdf, kBooleanSymbolCount);
157   ASSIGN_COUNTER_2D(skip_cdf, kBooleanSymbolCount);
158   ASSIGN_COUNTER_2D(skip_mode_cdf, kBooleanSymbolCount);
159   ASSIGN_COUNTER_2D(delta_lf_multi_cdf, kDeltaSymbolCount);
160   ASSIGN_COUNTER_2D(y_mode_cdf, kIntraPredictionModesY);
161   ASSIGN_COUNTER_2D(angle_delta_cdf, kAngleDeltaSymbolCount);
162   ASSIGN_COUNTER_2D(cfl_alpha_cdf, kCflAlphaSymbolCount);
163   ASSIGN_COUNTER_2D(use_filter_intra_cdf, kBooleanSymbolCount);
164   ASSIGN_COUNTER_2D(tx_split_cdf, kBooleanSymbolCount);
165   ASSIGN_COUNTER_2D(eob_pt_512_cdf, kEobPt512SymbolCount);
166   ASSIGN_COUNTER_2D(eob_pt_1024_cdf, kEobPt1024SymbolCount);
167   ASSIGN_COUNTER_2D(palette_y_size_cdf, kPaletteSizeSymbolCount);
168   ASSIGN_COUNTER_2D(has_palette_uv_cdf, kBooleanSymbolCount);
169   ASSIGN_COUNTER_2D(palette_uv_size_cdf, kPaletteSizeSymbolCount);
170   ASSIGN_COUNTER_2D(is_inter_cdf, kBooleanSymbolCount);
171   ASSIGN_COUNTER_2D(use_compound_reference_cdf, kBooleanSymbolCount);
172   ASSIGN_COUNTER_2D(compound_reference_type_cdf, kBooleanSymbolCount);
173   ASSIGN_COUNTER_2D(compound_prediction_mode_cdf,
174                     kNumCompoundInterPredictionModes);
175   ASSIGN_COUNTER_2D(new_mv_cdf, kBooleanSymbolCount);
176   ASSIGN_COUNTER_2D(zero_mv_cdf, kBooleanSymbolCount);
177   ASSIGN_COUNTER_2D(reference_mv_cdf, kBooleanSymbolCount);
178   ASSIGN_COUNTER_2D(ref_mv_index_cdf, kBooleanSymbolCount);
179   ASSIGN_COUNTER_2D(is_inter_intra_cdf, kBooleanSymbolCount);
180   ASSIGN_COUNTER_2D(inter_intra_mode_cdf, kNumInterIntraModes);
181   ASSIGN_COUNTER_2D(is_wedge_inter_intra_cdf, kBooleanSymbolCount);
182   ASSIGN_COUNTER_2D(wedge_index_cdf, kWedgeIndexSymbolCount);
183   ASSIGN_COUNTER_2D(use_obmc_cdf, kBooleanSymbolCount);
184   ASSIGN_COUNTER_2D(motion_mode_cdf, kNumMotionModes);
185   ASSIGN_COUNTER_2D(is_explicit_compound_type_cdf, kBooleanSymbolCount);
186   ASSIGN_COUNTER_2D(is_compound_type_average_cdf, kBooleanSymbolCount);
187   ASSIGN_COUNTER_2D(compound_type_cdf, kNumExplicitCompoundPredictionTypes);
188   ASSIGN_COUNTER_2D(interpolation_filter_cdf, kNumExplicitInterpolationFilters);
189   ASSIGN_COUNTER_2D(mv_joint_cdf, kNumMvJointTypes);
190   ResetAndVerifyCounters(&context);
191 }
192 
193 #undef ASSIGN_COUNTER_2D
194 
195 #define ASSIGN_COUNTER_3D(array, offset) \
196   do {                                   \
197     for (auto& d1 : context.array) {     \
198       for (auto& d2 : d1) {              \
199         d2[libgav1::offset] = ++value;   \
200       }                                  \
201     }                                    \
202   } while (false)
203 
TEST(SymbolDecoderContextTest,ResetCounters3d)204 TEST(SymbolDecoderContextTest, ResetCounters3d) {
205   libgav1::SymbolDecoderContext context = {};
206   context.Initialize(0);
207   int value = 0;
208   ASSIGN_COUNTER_3D(intra_frame_y_mode_cdf, kIntraPredictionModesY);
209   ASSIGN_COUNTER_3D(all_zero_cdf, kBooleanSymbolCount);
210   ASSIGN_COUNTER_3D(eob_pt_16_cdf, kEobPt16SymbolCount);
211   ASSIGN_COUNTER_3D(eob_pt_32_cdf, kEobPt32SymbolCount);
212   ASSIGN_COUNTER_3D(eob_pt_64_cdf, kEobPt64SymbolCount);
213   ASSIGN_COUNTER_3D(eob_pt_128_cdf, kEobPt128SymbolCount);
214   ASSIGN_COUNTER_3D(eob_pt_256_cdf, kEobPt256SymbolCount);
215   ASSIGN_COUNTER_3D(dc_sign_cdf, kBooleanSymbolCount);
216   ASSIGN_COUNTER_3D(has_palette_y_cdf, kBooleanSymbolCount);
217   ASSIGN_COUNTER_3D(compound_backward_reference_cdf, kBooleanSymbolCount);
218   ASSIGN_COUNTER_3D(single_reference_cdf, kBooleanSymbolCount);
219   ASSIGN_COUNTER_3D(mv_sign_cdf, kBooleanSymbolCount);
220   ASSIGN_COUNTER_3D(mv_class_cdf, kMvClassSymbolCount);
221   ASSIGN_COUNTER_3D(mv_class0_bit_cdf, kBooleanSymbolCount);
222   ASSIGN_COUNTER_3D(mv_class0_high_precision_cdf, kBooleanSymbolCount);
223   ASSIGN_COUNTER_3D(mv_fraction_cdf, kMvFractionSymbolCount);
224   ASSIGN_COUNTER_3D(mv_high_precision_cdf, kBooleanSymbolCount);
225   IncreasePartitionCounters(&context, value);
226   IncreaseTxTypeCounters(&context, value);
227   IncreaseTxDepthCounters(&context, value);
228   IncreaseUVModeCounters(&context, value);
229   ResetAndVerifyCounters(&context);
230 }
231 
232 #undef ASSIGN_COUNTER_3D
233 
234 #define ASSIGN_COUNTER_4D(array, offset) \
235   do {                                   \
236     for (auto& d1 : context.array) {     \
237       for (auto& d2 : d1) {              \
238         for (auto& d3 : d2) {            \
239           d3[libgav1::offset] = ++value; \
240         }                                \
241       }                                  \
242     }                                    \
243   } while (false)
244 
TEST(SymbolDecoderContextTest,ResetCounters4d)245 TEST(SymbolDecoderContextTest, ResetCounters4d) {
246   libgav1::SymbolDecoderContext context = {};
247   context.Initialize(0);
248   int value = 0;
249   ASSIGN_COUNTER_4D(eob_extra_cdf, kBooleanSymbolCount);
250   ASSIGN_COUNTER_4D(coeff_base_eob_cdf, kCoeffBaseEobSymbolCount);
251   ASSIGN_COUNTER_4D(coeff_base_cdf, kCoeffBaseSymbolCount);
252   ASSIGN_COUNTER_4D(coeff_base_range_cdf, kCoeffBaseRangeSymbolCount);
253   ASSIGN_COUNTER_4D(compound_reference_cdf, kBooleanSymbolCount);
254   ASSIGN_COUNTER_4D(mv_class0_fraction_cdf, kMvFractionSymbolCount);
255   ASSIGN_COUNTER_4D(mv_bit_cdf, kBooleanSymbolCount);
256   IncreasePaletteColorIndexCounters(&context, value);
257   IncreaseTxTypeCounters(&context, value);
258   ResetAndVerifyCounters(&context);
259 }
260 
261 #undef ASSIGN_COUNTER_4D
262 
263 }  // namespace
264 }  // namespace libgav1
265