// Copyright 2019 The libgav1 Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "src/utils/block_parameters_holder.h" #include #include "src/utils/common.h" #include "src/utils/constants.h" #include "src/utils/logging.h" #include "src/utils/types.h" namespace libgav1 { bool BlockParametersHolder::Reset(int rows4x4, int columns4x4) { rows4x4_ = rows4x4; columns4x4_ = columns4x4; index_ = 0; return block_parameters_cache_.Reset(rows4x4_, columns4x4_) && block_parameters_.Resize(rows4x4_ * columns4x4_); } BlockParameters* BlockParametersHolder::Get(int row4x4, int column4x4, BlockSize block_size) { const size_t index = index_.fetch_add(1, std::memory_order_relaxed); if (index >= block_parameters_.size()) return nullptr; auto& bp = block_parameters_.get()[index]; if (bp == nullptr) { bp.reset(new (std::nothrow) BlockParameters); if (bp == nullptr) return nullptr; } FillCache(row4x4, column4x4, block_size, bp.get()); return bp.get(); } void BlockParametersHolder::FillCache(int row4x4, int column4x4, BlockSize block_size, BlockParameters* const bp) { int rows = std::min(static_cast(kNum4x4BlocksHigh[block_size]), rows4x4_ - row4x4); const int columns = std::min(static_cast(kNum4x4BlocksWide[block_size]), columns4x4_ - column4x4); auto* bp_dst = &block_parameters_cache_[row4x4][column4x4]; // Specialize columns cases (values in kNum4x4BlocksWide[]) for better // performance. if (columns == 1) { SetBlock(rows, 1, bp, bp_dst, columns4x4_); } else if (columns == 2) { SetBlock(rows, 2, bp, bp_dst, columns4x4_); } else if (columns == 4) { SetBlock(rows, 4, bp, bp_dst, columns4x4_); } else if (columns == 8) { SetBlock(rows, 8, bp, bp_dst, columns4x4_); } else if (columns == 16) { SetBlock(rows, 16, bp, bp_dst, columns4x4_); } else if (columns == 32) { SetBlock(rows, 32, bp, bp_dst, columns4x4_); } else { do { // The following loop has better performance than using std::fill(). // std::fill() has some overhead in checking zero loop count. int x = columns; auto* d = bp_dst; do { *d++ = bp; } while (--x != 0); bp_dst += columns4x4_; } while (--rows != 0); } } } // namespace libgav1