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