Upload upstream chromium 108.0.5359.1
[platform/framework/web/chromium-efl.git] / media / filters / vp9_compressed_header_parser.cc
1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/filters/vp9_compressed_header_parser.h"
6
7 #include "base/logging.h"
8
9 namespace media {
10
11 namespace {
12
13 // 6.3.6 Inv recenter noneg syntax, inv_recenter_nonneg().
14 int InvRecenterNonneg(int v, int m) {
15   DCHECK_LE(m, kVp9MaxProb / 2);
16   if (v > 2 * m)
17     return v;
18
19   if (v & 1)
20     return m - ((v + 1) >> 1);
21   return m + (v >> 1);
22 }
23
24 // 6.3.5 Inv remap prob syntax, inv_remap_prob().
25 Vp9Prob InvRemapProb(uint8_t delta_prob, uint8_t prob, bool have_context) {
26   static const uint8_t inv_map_table[kVp9MaxProb] = {
27       7,   20,  33,  46,  59,  72,  85,  98,  111, 124, 137, 150, 163, 176,
28       189, 202, 215, 228, 241, 254, 1,   2,   3,   4,   5,   6,   8,   9,
29       10,  11,  12,  13,  14,  15,  16,  17,  18,  19,  21,  22,  23,  24,
30       25,  26,  27,  28,  29,  30,  31,  32,  34,  35,  36,  37,  38,  39,
31       40,  41,  42,  43,  44,  45,  47,  48,  49,  50,  51,  52,  53,  54,
32       55,  56,  57,  58,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,
33       70,  71,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
34       86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  99,  100,
35       101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 112, 113, 114, 115,
36       116, 117, 118, 119, 120, 121, 122, 123, 125, 126, 127, 128, 129, 130,
37       131, 132, 133, 134, 135, 136, 138, 139, 140, 141, 142, 143, 144, 145,
38       146, 147, 148, 149, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
39       161, 162, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
40       177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 190, 191,
41       192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 203, 204, 205, 206,
42       207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 220, 221,
43       222, 223, 224, 225, 226, 227, 229, 230, 231, 232, 233, 234, 235, 236,
44       237, 238, 239, 240, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
45       252, 253, 253};
46   uint8_t v = delta_prob;
47   DCHECK_LT(v, std::size(inv_map_table));
48   v = inv_map_table[v];
49   if (!have_context)
50     return v;
51
52   uint8_t m = prob;
53   DCHECK_LE(m, kVp9MaxProb);
54   DCHECK_GE(m, 1);
55   m--;
56   if ((m << 1) <= kVp9MaxProb) {
57     return 1 + InvRecenterNonneg(v, m);
58   }
59   return kVp9MaxProb - InvRecenterNonneg(v, kVp9MaxProb - 1 - m);
60 }
61
62 }  // namespace
63
64 Vp9CompressedHeaderParser::Vp9CompressedHeaderParser() = default;
65
66 // 6.3 Compressed header syntax
67 bool Vp9CompressedHeaderParser::Parse(const uint8_t* stream,
68                                       off_t frame_size,
69                                       Vp9FrameHeader* fhdr) {
70   have_frame_context_ = true;
71   return ParseInternal(stream, frame_size, fhdr);
72 }
73
74 bool Vp9CompressedHeaderParser::ParseNoContext(const uint8_t* stream,
75                                                off_t frame_size,
76                                                Vp9FrameHeader* fhdr) {
77   have_frame_context_ = false;
78   memset(&fhdr->frame_context, 0, sizeof(fhdr->frame_context));
79   return ParseInternal(stream, frame_size, fhdr);
80 }
81
82 // 6.3.1 Tx mode syntax
83 void Vp9CompressedHeaderParser::ReadTxMode(Vp9FrameHeader* fhdr) {
84   int tx_mode;
85   if (fhdr->quant_params.IsLossless()) {
86     tx_mode = Vp9CompressedHeader::ONLY_4X4;
87   } else {
88     tx_mode = reader_.ReadLiteral(2);
89     if (tx_mode == Vp9CompressedHeader::ALLOW_32X32)
90       tx_mode += reader_.ReadLiteral(1);
91   }
92   fhdr->compressed_header.tx_mode =
93       static_cast<Vp9CompressedHeader::Vp9TxMode>(tx_mode);
94 }
95
96 // 6.3.4 Decode term subexp syntax
97 uint8_t Vp9CompressedHeaderParser::DecodeTermSubexp() {
98   if (reader_.ReadLiteral(1) == 0)
99     return reader_.ReadLiteral(4);
100   if (reader_.ReadLiteral(1) == 0)
101     return reader_.ReadLiteral(4) + 16;
102   if (reader_.ReadLiteral(1) == 0)
103     return reader_.ReadLiteral(5) + 32;
104   uint8_t v = reader_.ReadLiteral(7);
105   if (v < 65)
106     return v + 64;
107   return (v << 1) - 1 + reader_.ReadLiteral(1);
108 }
109
110 // 6.3.3 Diff update prob syntax
111 void Vp9CompressedHeaderParser::DiffUpdateProb(Vp9Prob* prob) {
112   const Vp9Prob kUpdateProb = 252;
113   const bool must_update_probabilities = reader_.ReadBool(kUpdateProb);
114
115   if (!must_update_probabilities)
116     return;
117
118   uint8_t delta_prob = DecodeTermSubexp();
119   *prob = InvRemapProb(delta_prob, *prob, have_frame_context_);
120 }
121
122 // Helper function to DiffUpdateProb an array of probs.
123 template <int N>
124 void Vp9CompressedHeaderParser::DiffUpdateProbArray(Vp9Prob (&prob_array)[N]) {
125   for (auto& x : prob_array) {
126     DiffUpdateProb(&x);
127   }
128 }
129
130 // 6.3.2 Tx mode probs syntax
131 void Vp9CompressedHeaderParser::ReadTxModeProbs(
132     Vp9FrameContext* frame_context) {
133   for (auto& a : frame_context->tx_probs_8x8) {
134     DiffUpdateProbArray(a);
135   }
136   for (auto& a : frame_context->tx_probs_16x16) {
137     DiffUpdateProbArray(a);
138   }
139   for (auto& a : frame_context->tx_probs_32x32) {
140     DiffUpdateProbArray(a);
141   }
142 }
143
144 // 6.3.7 Coef probs syntax
145 void Vp9CompressedHeaderParser::ReadCoefProbs(Vp9FrameHeader* fhdr) {
146   const int tx_mode_to_biggest_tx_size[Vp9CompressedHeader::TX_MODES] = {
147       0, 1, 2, 3, 3,
148   };
149   const int max_tx_size =
150       tx_mode_to_biggest_tx_size[fhdr->compressed_header.tx_mode];
151   for (int tx_size = 0; tx_size <= max_tx_size; tx_size++) {
152     if (reader_.ReadLiteral(1) == 0)
153       continue;
154
155     for (auto& ai : fhdr->frame_context.coef_probs[tx_size]) {
156       for (auto& aj : ai) {
157         for (auto& ak : aj) {
158           int max_l = (+ak == +aj[0]) ? 3 : 6;
159           for (int l = 0; l < max_l; l++) {
160             DiffUpdateProbArray(ak[l]);
161           }
162         }
163       }
164     }
165   }
166 }
167
168 // 6.3.8 Skip probs syntax
169 void Vp9CompressedHeaderParser::ReadSkipProb(Vp9FrameContext* frame_context) {
170   DiffUpdateProbArray(frame_context->skip_prob);
171 }
172
173 // 6.3.9 Inter mode probs syntax
174 void Vp9CompressedHeaderParser::ReadInterModeProbs(
175     Vp9FrameContext* frame_context) {
176   for (auto& a : frame_context->inter_mode_probs)
177     DiffUpdateProbArray(a);
178 }
179
180 // 6.3.10 Interp filter probs syntax
181 void Vp9CompressedHeaderParser::ReadInterpFilterProbs(
182     Vp9FrameContext* frame_context) {
183   for (auto& a : frame_context->interp_filter_probs)
184     DiffUpdateProbArray(a);
185 }
186
187 // 6.3.11 Intra inter probs syntax
188 void Vp9CompressedHeaderParser::ReadIsInterProbs(
189     Vp9FrameContext* frame_context) {
190   DiffUpdateProbArray(frame_context->is_inter_prob);
191 }
192
193 // 6.3.12 Frame reference mode syntax
194 void Vp9CompressedHeaderParser::ReadFrameReferenceMode(Vp9FrameHeader* fhdr) {
195   bool compound_reference_allowed = false;
196   for (int i = VP9_FRAME_LAST + 1; i < VP9_FRAME_MAX; i++)
197     if (fhdr->ref_frame_sign_bias[i] != fhdr->ref_frame_sign_bias[1])
198       compound_reference_allowed = true;
199
200   if (compound_reference_allowed && reader_.ReadLiteral(1)) {
201     fhdr->compressed_header.reference_mode =
202         reader_.ReadLiteral(1) ? REFERENCE_MODE_SELECT : COMPOUND_REFERENCE;
203   } else {
204     fhdr->compressed_header.reference_mode = SINGLE_REFERENCE;
205   }
206 }
207
208 // 6.3.13 Frame reference mode probs syntax
209 void Vp9CompressedHeaderParser::ReadFrameReferenceModeProbs(
210     Vp9FrameHeader* fhdr) {
211   Vp9FrameContext* frame_context = &fhdr->frame_context;
212   if (fhdr->compressed_header.reference_mode == REFERENCE_MODE_SELECT)
213     DiffUpdateProbArray(frame_context->comp_mode_prob);
214
215   if (fhdr->compressed_header.reference_mode != COMPOUND_REFERENCE)
216     for (auto& a : frame_context->single_ref_prob)
217       DiffUpdateProbArray(a);
218
219   if (fhdr->compressed_header.reference_mode != SINGLE_REFERENCE)
220     DiffUpdateProbArray(frame_context->comp_ref_prob);
221 }
222
223 // 6.3.14 Y mode probs syntax
224 void Vp9CompressedHeaderParser::ReadYModeProbs(Vp9FrameContext* frame_context) {
225   for (auto& a : frame_context->y_mode_probs)
226     DiffUpdateProbArray(a);
227 }
228
229 // 6.3.15 Partition probs syntax
230 void Vp9CompressedHeaderParser::ReadPartitionProbs(
231     Vp9FrameContext* frame_context) {
232   for (auto& a : frame_context->partition_probs)
233     DiffUpdateProbArray(a);
234 }
235
236 // 6.3.16 MV probs syntax
237 void Vp9CompressedHeaderParser::ReadMvProbs(bool allow_high_precision_mv,
238                                             Vp9FrameContext* frame_context) {
239   UpdateMvProbArray(frame_context->mv_joint_probs);
240
241   for (int i = 0; i < 2; i++) {
242     UpdateMvProb(&frame_context->mv_sign_prob[i]);
243     UpdateMvProbArray(frame_context->mv_class_probs[i]);
244     UpdateMvProb(&frame_context->mv_class0_bit_prob[i]);
245     UpdateMvProbArray(frame_context->mv_bits_prob[i]);
246   }
247
248   for (int i = 0; i < 2; i++) {
249     for (auto& a : frame_context->mv_class0_fr_probs[i])
250       UpdateMvProbArray(a);
251     UpdateMvProbArray(frame_context->mv_fr_probs[i]);
252   }
253
254   if (allow_high_precision_mv) {
255     for (int i = 0; i < 2; i++) {
256       UpdateMvProb(&frame_context->mv_class0_hp_prob[i]);
257       UpdateMvProb(&frame_context->mv_hp_prob[i]);
258     }
259   }
260 }
261
262 // 6.3.17 Update mv prob syntax
263 void Vp9CompressedHeaderParser::UpdateMvProb(Vp9Prob* prob) {
264   if (reader_.ReadBool(252))
265     *prob = reader_.ReadLiteral(7) << 1 | 1;
266 }
267
268 // Helper function to UpdateMvProb an array of probs.
269 template <int N>
270 void Vp9CompressedHeaderParser::UpdateMvProbArray(Vp9Prob (&prob_array)[N]) {
271   for (auto& x : prob_array) {
272     UpdateMvProb(&x);
273   }
274 }
275
276 // 6.3 Compressed header syntax
277 bool Vp9CompressedHeaderParser::ParseInternal(const uint8_t* stream,
278                                               off_t frame_size,
279                                               Vp9FrameHeader* fhdr) {
280   DVLOG(2) << "Vp9CompressedHeaderParser::Parse";
281   if (!reader_.Initialize(stream, frame_size))
282     return false;
283
284   ReadTxMode(fhdr);
285   if (fhdr->compressed_header.tx_mode == Vp9CompressedHeader::TX_MODE_SELECT)
286     ReadTxModeProbs(&fhdr->frame_context);
287
288   ReadCoefProbs(fhdr);
289   ReadSkipProb(&fhdr->frame_context);
290
291   if (!fhdr->IsIntra()) {
292     ReadInterModeProbs(&fhdr->frame_context);
293     if (fhdr->interpolation_filter == SWITCHABLE)
294       ReadInterpFilterProbs(&fhdr->frame_context);
295     ReadIsInterProbs(&fhdr->frame_context);
296     ReadFrameReferenceMode(fhdr);
297     ReadFrameReferenceModeProbs(fhdr);
298     ReadYModeProbs(&fhdr->frame_context);
299     ReadPartitionProbs(&fhdr->frame_context);
300     ReadMvProbs(fhdr->allow_high_precision_mv, &fhdr->frame_context);
301   }
302
303   if (!reader_.IsValid()) {
304     DVLOG(1) << "parser reads beyond the end of buffer";
305     return false;
306   }
307   if (!reader_.ConsumePaddingBits()) {
308     DVLOG(1) << "padding bits are not zero";
309     return false;
310   }
311   return true;
312 }
313
314 }  // namespace media