1 // Copyright 2019 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/utils/block_parameters_holder.h"
16 
17 #include <algorithm>
18 
19 #include "src/utils/common.h"
20 #include "src/utils/constants.h"
21 #include "src/utils/logging.h"
22 #include "src/utils/types.h"
23 
24 namespace libgav1 {
25 
Reset(int rows4x4,int columns4x4)26 bool BlockParametersHolder::Reset(int rows4x4, int columns4x4) {
27   rows4x4_ = rows4x4;
28   columns4x4_ = columns4x4;
29   index_ = 0;
30   return block_parameters_cache_.Reset(rows4x4_, columns4x4_) &&
31          block_parameters_.Resize(rows4x4_ * columns4x4_);
32 }
33 
Get(int row4x4,int column4x4,BlockSize block_size)34 BlockParameters* BlockParametersHolder::Get(int row4x4, int column4x4,
35                                             BlockSize block_size) {
36   const size_t index = index_.fetch_add(1, std::memory_order_relaxed);
37   if (index >= block_parameters_.size()) return nullptr;
38   auto& bp = block_parameters_.get()[index];
39   if (bp == nullptr) {
40     bp.reset(new (std::nothrow) BlockParameters);
41     if (bp == nullptr) return nullptr;
42   }
43   FillCache(row4x4, column4x4, block_size, bp.get());
44   return bp.get();
45 }
46 
FillCache(int row4x4,int column4x4,BlockSize block_size,BlockParameters * const bp)47 void BlockParametersHolder::FillCache(int row4x4, int column4x4,
48                                       BlockSize block_size,
49                                       BlockParameters* const bp) {
50   int rows = std::min(static_cast<int>(kNum4x4BlocksHigh[block_size]),
51                       rows4x4_ - row4x4);
52   const int columns = std::min(static_cast<int>(kNum4x4BlocksWide[block_size]),
53                                columns4x4_ - column4x4);
54   auto* bp_dst = &block_parameters_cache_[row4x4][column4x4];
55   // Specialize columns cases (values in kNum4x4BlocksWide[]) for better
56   // performance.
57   if (columns == 1) {
58     SetBlock<BlockParameters*>(rows, 1, bp, bp_dst, columns4x4_);
59   } else if (columns == 2) {
60     SetBlock<BlockParameters*>(rows, 2, bp, bp_dst, columns4x4_);
61   } else if (columns == 4) {
62     SetBlock<BlockParameters*>(rows, 4, bp, bp_dst, columns4x4_);
63   } else if (columns == 8) {
64     SetBlock<BlockParameters*>(rows, 8, bp, bp_dst, columns4x4_);
65   } else if (columns == 16) {
66     SetBlock<BlockParameters*>(rows, 16, bp, bp_dst, columns4x4_);
67   } else if (columns == 32) {
68     SetBlock<BlockParameters*>(rows, 32, bp, bp_dst, columns4x4_);
69   } else {
70     do {
71       // The following loop has better performance than using std::fill().
72       // std::fill() has some overhead in checking zero loop count.
73       int x = columns;
74       auto* d = bp_dst;
75       do {
76         *d++ = bp;
77       } while (--x != 0);
78       bp_dst += columns4x4_;
79     } while (--rows != 0);
80   }
81 }
82 
83 }  // namespace libgav1
84