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