xref: /aosp_15_r20/external/libgav1/src/tile/bitstream/partition.cc (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1*09537850SAkhilesh Sanikop // Copyright 2019 The libgav1 Authors
2*09537850SAkhilesh Sanikop //
3*09537850SAkhilesh Sanikop // Licensed under the Apache License, Version 2.0 (the "License");
4*09537850SAkhilesh Sanikop // you may not use this file except in compliance with the License.
5*09537850SAkhilesh Sanikop // You may obtain a copy of the License at
6*09537850SAkhilesh Sanikop //
7*09537850SAkhilesh Sanikop //      http://www.apache.org/licenses/LICENSE-2.0
8*09537850SAkhilesh Sanikop //
9*09537850SAkhilesh Sanikop // Unless required by applicable law or agreed to in writing, software
10*09537850SAkhilesh Sanikop // distributed under the License is distributed on an "AS IS" BASIS,
11*09537850SAkhilesh Sanikop // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*09537850SAkhilesh Sanikop // See the License for the specific language governing permissions and
13*09537850SAkhilesh Sanikop // limitations under the License.
14*09537850SAkhilesh Sanikop 
15*09537850SAkhilesh Sanikop #include <cassert>
16*09537850SAkhilesh Sanikop #include <cstdint>
17*09537850SAkhilesh Sanikop 
18*09537850SAkhilesh Sanikop #include "src/symbol_decoder_context.h"
19*09537850SAkhilesh Sanikop #include "src/tile.h"
20*09537850SAkhilesh Sanikop #include "src/utils/block_parameters_holder.h"
21*09537850SAkhilesh Sanikop #include "src/utils/common.h"
22*09537850SAkhilesh Sanikop #include "src/utils/constants.h"
23*09537850SAkhilesh Sanikop #include "src/utils/entropy_decoder.h"
24*09537850SAkhilesh Sanikop #include "src/utils/types.h"
25*09537850SAkhilesh Sanikop 
26*09537850SAkhilesh Sanikop namespace libgav1 {
27*09537850SAkhilesh Sanikop namespace {
28*09537850SAkhilesh Sanikop 
PartitionCdfGatherHorizontalAlike(const uint16_t * const partition_cdf,BlockSize block_size)29*09537850SAkhilesh Sanikop uint16_t PartitionCdfGatherHorizontalAlike(const uint16_t* const partition_cdf,
30*09537850SAkhilesh Sanikop                                            BlockSize block_size) {
31*09537850SAkhilesh Sanikop   // The spec computes the cdf value using the following formula (not writing
32*09537850SAkhilesh Sanikop   // partition_cdf[] and using short forms for partition names for clarity):
33*09537850SAkhilesh Sanikop   //   cdf = None - H + V - S + S - HTS + HTS - HBS + HBS - VLS;
34*09537850SAkhilesh Sanikop   //   if (block_size != 128x128) {
35*09537850SAkhilesh Sanikop   //     cdf += VRS - H4;
36*09537850SAkhilesh Sanikop   //   }
37*09537850SAkhilesh Sanikop   // After canceling out the repeated terms with opposite signs, we have:
38*09537850SAkhilesh Sanikop   //   cdf = None - H + V - VLS;
39*09537850SAkhilesh Sanikop   //   if (block_size != 128x128) {
40*09537850SAkhilesh Sanikop   //     cdf += VRS - H4;
41*09537850SAkhilesh Sanikop   //   }
42*09537850SAkhilesh Sanikop   uint16_t cdf = partition_cdf[kPartitionNone] -
43*09537850SAkhilesh Sanikop                  partition_cdf[kPartitionHorizontal] +
44*09537850SAkhilesh Sanikop                  partition_cdf[kPartitionVertical] -
45*09537850SAkhilesh Sanikop                  partition_cdf[kPartitionVerticalWithLeftSplit];
46*09537850SAkhilesh Sanikop   if (block_size != kBlock128x128) {
47*09537850SAkhilesh Sanikop     cdf += partition_cdf[kPartitionVerticalWithRightSplit] -
48*09537850SAkhilesh Sanikop            partition_cdf[kPartitionHorizontal4];
49*09537850SAkhilesh Sanikop   }
50*09537850SAkhilesh Sanikop   return cdf;
51*09537850SAkhilesh Sanikop }
52*09537850SAkhilesh Sanikop 
PartitionCdfGatherVerticalAlike(const uint16_t * const partition_cdf,BlockSize block_size)53*09537850SAkhilesh Sanikop uint16_t PartitionCdfGatherVerticalAlike(const uint16_t* const partition_cdf,
54*09537850SAkhilesh Sanikop                                          BlockSize block_size) {
55*09537850SAkhilesh Sanikop   // The spec computes the cdf value using the following formula (not writing
56*09537850SAkhilesh Sanikop   // partition_cdf[] and using short forms for partition names for clarity):
57*09537850SAkhilesh Sanikop   //   cdf = H - V + V - S + HBS - VLS + VLS - VRS + S - HTS;
58*09537850SAkhilesh Sanikop   //   if (block_size != 128x128) {
59*09537850SAkhilesh Sanikop   //     cdf += H4 - V4;
60*09537850SAkhilesh Sanikop   //   }
61*09537850SAkhilesh Sanikop   // V4 is always zero. So, after canceling out the repeated terms with opposite
62*09537850SAkhilesh Sanikop   // signs, we have:
63*09537850SAkhilesh Sanikop   //   cdf = H + HBS - VRS - HTS;
64*09537850SAkhilesh Sanikop   //   if (block_size != 128x128) {
65*09537850SAkhilesh Sanikop   //     cdf += H4;
66*09537850SAkhilesh Sanikop   //   }
67*09537850SAkhilesh Sanikop   // VRS is zero for 128x128 blocks. So, further simplifying we have:
68*09537850SAkhilesh Sanikop   //   cdf = H + HBS - HTS;
69*09537850SAkhilesh Sanikop   //   if (block_size != 128x128) {
70*09537850SAkhilesh Sanikop   //     cdf += H4 - VRS;
71*09537850SAkhilesh Sanikop   //   }
72*09537850SAkhilesh Sanikop   uint16_t cdf = partition_cdf[kPartitionHorizontal] +
73*09537850SAkhilesh Sanikop                  partition_cdf[kPartitionHorizontalWithBottomSplit] -
74*09537850SAkhilesh Sanikop                  partition_cdf[kPartitionHorizontalWithTopSplit];
75*09537850SAkhilesh Sanikop   if (block_size != kBlock128x128) {
76*09537850SAkhilesh Sanikop     cdf += partition_cdf[kPartitionHorizontal4] -
77*09537850SAkhilesh Sanikop            partition_cdf[kPartitionVerticalWithRightSplit];
78*09537850SAkhilesh Sanikop   }
79*09537850SAkhilesh Sanikop   return cdf;
80*09537850SAkhilesh Sanikop }
81*09537850SAkhilesh Sanikop 
82*09537850SAkhilesh Sanikop }  // namespace
83*09537850SAkhilesh Sanikop 
GetPartitionCdf(int row4x4,int column4x4,BlockSize block_size)84*09537850SAkhilesh Sanikop uint16_t* Tile::GetPartitionCdf(int row4x4, int column4x4,
85*09537850SAkhilesh Sanikop                                 BlockSize block_size) {
86*09537850SAkhilesh Sanikop   const int block_size_log2 = k4x4WidthLog2[block_size];
87*09537850SAkhilesh Sanikop   int top = 0;
88*09537850SAkhilesh Sanikop   if (IsTopInside(row4x4)) {
89*09537850SAkhilesh Sanikop     top = static_cast<int>(
90*09537850SAkhilesh Sanikop         k4x4WidthLog2[block_parameters_holder_.Find(row4x4 - 1, column4x4)
91*09537850SAkhilesh Sanikop                           ->size] < block_size_log2);
92*09537850SAkhilesh Sanikop   }
93*09537850SAkhilesh Sanikop   int left = 0;
94*09537850SAkhilesh Sanikop   if (IsLeftInside(column4x4)) {
95*09537850SAkhilesh Sanikop     left = static_cast<int>(
96*09537850SAkhilesh Sanikop         k4x4HeightLog2[block_parameters_holder_.Find(row4x4, column4x4 - 1)
97*09537850SAkhilesh Sanikop                            ->size] < block_size_log2);
98*09537850SAkhilesh Sanikop   }
99*09537850SAkhilesh Sanikop   const int context = left * 2 + top;
100*09537850SAkhilesh Sanikop   return symbol_decoder_context_.partition_cdf[block_size_log2 - 1][context];
101*09537850SAkhilesh Sanikop }
102*09537850SAkhilesh Sanikop 
ReadPartition(int row4x4,int column4x4,BlockSize block_size,bool has_rows,bool has_columns,Partition * const partition)103*09537850SAkhilesh Sanikop bool Tile::ReadPartition(int row4x4, int column4x4, BlockSize block_size,
104*09537850SAkhilesh Sanikop                          bool has_rows, bool has_columns,
105*09537850SAkhilesh Sanikop                          Partition* const partition) {
106*09537850SAkhilesh Sanikop   if (IsBlockSmallerThan8x8(block_size)) {
107*09537850SAkhilesh Sanikop     *partition = kPartitionNone;
108*09537850SAkhilesh Sanikop     return true;
109*09537850SAkhilesh Sanikop   }
110*09537850SAkhilesh Sanikop   if (!has_rows && !has_columns) {
111*09537850SAkhilesh Sanikop     *partition = kPartitionSplit;
112*09537850SAkhilesh Sanikop     return true;
113*09537850SAkhilesh Sanikop   }
114*09537850SAkhilesh Sanikop   uint16_t* const partition_cdf =
115*09537850SAkhilesh Sanikop       GetPartitionCdf(row4x4, column4x4, block_size);
116*09537850SAkhilesh Sanikop   if (partition_cdf == nullptr) {
117*09537850SAkhilesh Sanikop     return false;
118*09537850SAkhilesh Sanikop   }
119*09537850SAkhilesh Sanikop   if (has_rows && has_columns) {
120*09537850SAkhilesh Sanikop     const int bsize_log2 = k4x4WidthLog2[block_size];
121*09537850SAkhilesh Sanikop     // The partition block size should be 8x8 or above.
122*09537850SAkhilesh Sanikop     assert(bsize_log2 > 0);
123*09537850SAkhilesh Sanikop     if (bsize_log2 == 1) {
124*09537850SAkhilesh Sanikop       *partition = static_cast<Partition>(
125*09537850SAkhilesh Sanikop           reader_.ReadSymbol<kPartitionSplit + 1>(partition_cdf));
126*09537850SAkhilesh Sanikop     } else if (bsize_log2 == 5) {
127*09537850SAkhilesh Sanikop       *partition = static_cast<Partition>(
128*09537850SAkhilesh Sanikop           reader_.ReadSymbol<kPartitionVerticalWithRightSplit + 1>(
129*09537850SAkhilesh Sanikop               partition_cdf));
130*09537850SAkhilesh Sanikop     } else {
131*09537850SAkhilesh Sanikop       *partition = static_cast<Partition>(
132*09537850SAkhilesh Sanikop           reader_.ReadSymbol<kMaxPartitionTypes>(partition_cdf));
133*09537850SAkhilesh Sanikop     }
134*09537850SAkhilesh Sanikop   } else if (has_columns) {
135*09537850SAkhilesh Sanikop     const uint16_t cdf =
136*09537850SAkhilesh Sanikop         PartitionCdfGatherVerticalAlike(partition_cdf, block_size);
137*09537850SAkhilesh Sanikop     *partition = reader_.ReadSymbolWithoutCdfUpdate(cdf) ? kPartitionSplit
138*09537850SAkhilesh Sanikop                                                          : kPartitionHorizontal;
139*09537850SAkhilesh Sanikop   } else {
140*09537850SAkhilesh Sanikop     const uint16_t cdf =
141*09537850SAkhilesh Sanikop         PartitionCdfGatherHorizontalAlike(partition_cdf, block_size);
142*09537850SAkhilesh Sanikop     *partition = reader_.ReadSymbolWithoutCdfUpdate(cdf) ? kPartitionSplit
143*09537850SAkhilesh Sanikop                                                          : kPartitionVertical;
144*09537850SAkhilesh Sanikop   }
145*09537850SAkhilesh Sanikop   return true;
146*09537850SAkhilesh Sanikop }
147*09537850SAkhilesh Sanikop 
148*09537850SAkhilesh Sanikop }  // namespace libgav1
149