1*09537850SAkhilesh Sanikop /* 2*09537850SAkhilesh Sanikop * Copyright 2019 The libgav1 Authors 3*09537850SAkhilesh Sanikop * 4*09537850SAkhilesh Sanikop * Licensed under the Apache License, Version 2.0 (the "License"); 5*09537850SAkhilesh Sanikop * you may not use this file except in compliance with the License. 6*09537850SAkhilesh Sanikop * You may obtain a copy of the License at 7*09537850SAkhilesh Sanikop * 8*09537850SAkhilesh Sanikop * http://www.apache.org/licenses/LICENSE-2.0 9*09537850SAkhilesh Sanikop * 10*09537850SAkhilesh Sanikop * Unless required by applicable law or agreed to in writing, software 11*09537850SAkhilesh Sanikop * distributed under the License is distributed on an "AS IS" BASIS, 12*09537850SAkhilesh Sanikop * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*09537850SAkhilesh Sanikop * See the License for the specific language governing permissions and 14*09537850SAkhilesh Sanikop * limitations under the License. 15*09537850SAkhilesh Sanikop */ 16*09537850SAkhilesh Sanikop 17*09537850SAkhilesh Sanikop #ifndef LIBGAV1_SRC_RESIDUAL_BUFFER_POOL_H_ 18*09537850SAkhilesh Sanikop #define LIBGAV1_SRC_RESIDUAL_BUFFER_POOL_H_ 19*09537850SAkhilesh Sanikop 20*09537850SAkhilesh Sanikop #include <cstddef> 21*09537850SAkhilesh Sanikop #include <cstdint> 22*09537850SAkhilesh Sanikop #include <memory> 23*09537850SAkhilesh Sanikop #include <mutex> // NOLINT (unapproved c++11 header) 24*09537850SAkhilesh Sanikop #include <new> 25*09537850SAkhilesh Sanikop 26*09537850SAkhilesh Sanikop #include "src/utils/common.h" 27*09537850SAkhilesh Sanikop #include "src/utils/compiler_attributes.h" 28*09537850SAkhilesh Sanikop #include "src/utils/constants.h" 29*09537850SAkhilesh Sanikop #include "src/utils/memory.h" 30*09537850SAkhilesh Sanikop #include "src/utils/queue.h" 31*09537850SAkhilesh Sanikop #include "src/utils/types.h" 32*09537850SAkhilesh Sanikop 33*09537850SAkhilesh Sanikop namespace libgav1 { 34*09537850SAkhilesh Sanikop 35*09537850SAkhilesh Sanikop // This class is used for parsing and decoding a superblock. Members of this 36*09537850SAkhilesh Sanikop // class are populated in the "parse" step and consumed in the "decode" step. 37*09537850SAkhilesh Sanikop class ResidualBuffer : public Allocable { 38*09537850SAkhilesh Sanikop public: Create(size_t buffer_size,int queue_size)39*09537850SAkhilesh Sanikop static std::unique_ptr<ResidualBuffer> Create(size_t buffer_size, 40*09537850SAkhilesh Sanikop int queue_size) { 41*09537850SAkhilesh Sanikop std::unique_ptr<ResidualBuffer> buffer(new (std::nothrow) ResidualBuffer); 42*09537850SAkhilesh Sanikop if (buffer != nullptr) { 43*09537850SAkhilesh Sanikop buffer->buffer_ = MakeAlignedUniquePtr<uint8_t>(32, buffer_size); 44*09537850SAkhilesh Sanikop if (buffer->buffer_ == nullptr || 45*09537850SAkhilesh Sanikop !buffer->transform_parameters_.Init(queue_size) || 46*09537850SAkhilesh Sanikop !buffer->partition_tree_order_.Init(queue_size)) { 47*09537850SAkhilesh Sanikop buffer = nullptr; 48*09537850SAkhilesh Sanikop } 49*09537850SAkhilesh Sanikop } 50*09537850SAkhilesh Sanikop return buffer; 51*09537850SAkhilesh Sanikop } 52*09537850SAkhilesh Sanikop 53*09537850SAkhilesh Sanikop // Move only. 54*09537850SAkhilesh Sanikop ResidualBuffer(ResidualBuffer&& other) = default; 55*09537850SAkhilesh Sanikop ResidualBuffer& operator=(ResidualBuffer&& other) = default; 56*09537850SAkhilesh Sanikop 57*09537850SAkhilesh Sanikop // Buffer used to store the residual values. buffer()58*09537850SAkhilesh Sanikop uint8_t* buffer() { return buffer_.get(); } 59*09537850SAkhilesh Sanikop // Queue used to store the transform parameters. transform_parameters()60*09537850SAkhilesh Sanikop Queue<TransformParameters>* transform_parameters() { 61*09537850SAkhilesh Sanikop return &transform_parameters_; 62*09537850SAkhilesh Sanikop } 63*09537850SAkhilesh Sanikop // Queue used to store the block ordering in the partition tree of the 64*09537850SAkhilesh Sanikop // superblocks. partition_tree_order()65*09537850SAkhilesh Sanikop Queue<PartitionTreeNode>* partition_tree_order() { 66*09537850SAkhilesh Sanikop return &partition_tree_order_; 67*09537850SAkhilesh Sanikop } 68*09537850SAkhilesh Sanikop 69*09537850SAkhilesh Sanikop private: 70*09537850SAkhilesh Sanikop friend class ResidualBufferStack; 71*09537850SAkhilesh Sanikop 72*09537850SAkhilesh Sanikop ResidualBuffer() = default; 73*09537850SAkhilesh Sanikop 74*09537850SAkhilesh Sanikop AlignedUniquePtr<uint8_t> buffer_; 75*09537850SAkhilesh Sanikop Queue<TransformParameters> transform_parameters_; 76*09537850SAkhilesh Sanikop Queue<PartitionTreeNode> partition_tree_order_; 77*09537850SAkhilesh Sanikop // Used by ResidualBufferStack to form a chain of ResidualBuffers. 78*09537850SAkhilesh Sanikop ResidualBuffer* next_ = nullptr; 79*09537850SAkhilesh Sanikop }; 80*09537850SAkhilesh Sanikop 81*09537850SAkhilesh Sanikop // A LIFO stack of ResidualBuffers. Owns the buffers in the stack. 82*09537850SAkhilesh Sanikop class ResidualBufferStack { 83*09537850SAkhilesh Sanikop public: 84*09537850SAkhilesh Sanikop ResidualBufferStack() = default; 85*09537850SAkhilesh Sanikop 86*09537850SAkhilesh Sanikop // Not copyable or movable 87*09537850SAkhilesh Sanikop ResidualBufferStack(const ResidualBufferStack&) = delete; 88*09537850SAkhilesh Sanikop ResidualBufferStack& operator=(const ResidualBufferStack&) = delete; 89*09537850SAkhilesh Sanikop 90*09537850SAkhilesh Sanikop ~ResidualBufferStack(); 91*09537850SAkhilesh Sanikop 92*09537850SAkhilesh Sanikop // Pushes |buffer| to the top of the stack. 93*09537850SAkhilesh Sanikop void Push(std::unique_ptr<ResidualBuffer> buffer); 94*09537850SAkhilesh Sanikop 95*09537850SAkhilesh Sanikop // If the stack is non-empty, returns the buffer at the top of the stack and 96*09537850SAkhilesh Sanikop // removes it from the stack. If the stack is empty, returns nullptr. 97*09537850SAkhilesh Sanikop std::unique_ptr<ResidualBuffer> Pop(); 98*09537850SAkhilesh Sanikop 99*09537850SAkhilesh Sanikop // Swaps the contents of this stack and |other|. 100*09537850SAkhilesh Sanikop void Swap(ResidualBufferStack* other); 101*09537850SAkhilesh Sanikop 102*09537850SAkhilesh Sanikop // Returns the number of buffers in the stack. Size()103*09537850SAkhilesh Sanikop size_t Size() const { return num_buffers_; } 104*09537850SAkhilesh Sanikop 105*09537850SAkhilesh Sanikop private: 106*09537850SAkhilesh Sanikop // A singly-linked list of ResidualBuffers, chained together using the next_ 107*09537850SAkhilesh Sanikop // field of ResidualBuffer. 108*09537850SAkhilesh Sanikop ResidualBuffer* top_ = nullptr; 109*09537850SAkhilesh Sanikop size_t num_buffers_ = 0; 110*09537850SAkhilesh Sanikop }; 111*09537850SAkhilesh Sanikop 112*09537850SAkhilesh Sanikop // Utility class used to manage the residual buffers (and the transform 113*09537850SAkhilesh Sanikop // parameters) used for multi-threaded decoding. This class uses a stack to 114*09537850SAkhilesh Sanikop // store the buffers for better cache locality. Since buffers used more recently 115*09537850SAkhilesh Sanikop // are more likely to be in the cache. All functions in this class are 116*09537850SAkhilesh Sanikop // thread-safe. 117*09537850SAkhilesh Sanikop class ResidualBufferPool : public Allocable { 118*09537850SAkhilesh Sanikop public: 119*09537850SAkhilesh Sanikop ResidualBufferPool(bool use_128x128_superblock, int subsampling_x, 120*09537850SAkhilesh Sanikop int subsampling_y, size_t residual_size); 121*09537850SAkhilesh Sanikop 122*09537850SAkhilesh Sanikop // Recomputes |buffer_size_| and invalidates the existing buffers if 123*09537850SAkhilesh Sanikop // necessary. 124*09537850SAkhilesh Sanikop void Reset(bool use_128x128_superblock, int subsampling_x, int subsampling_y, 125*09537850SAkhilesh Sanikop size_t residual_size); 126*09537850SAkhilesh Sanikop // Gets a residual buffer. The buffer is guaranteed to be large enough to 127*09537850SAkhilesh Sanikop // store the residual values for one superblock whose parameters are the same 128*09537850SAkhilesh Sanikop // as the constructor or the last call to Reset(). If there are free buffers 129*09537850SAkhilesh Sanikop // in the stack, it returns one from the stack, otherwise a new buffer is 130*09537850SAkhilesh Sanikop // allocated. 131*09537850SAkhilesh Sanikop std::unique_ptr<ResidualBuffer> Get(); 132*09537850SAkhilesh Sanikop // Returns the |buffer| back to the pool (by appending it to the stack). 133*09537850SAkhilesh Sanikop // Subsequent calls to Get() may re-use this buffer. 134*09537850SAkhilesh Sanikop void Release(std::unique_ptr<ResidualBuffer> buffer); 135*09537850SAkhilesh Sanikop 136*09537850SAkhilesh Sanikop // Used only in the tests. Returns the number of buffers in the stack. 137*09537850SAkhilesh Sanikop size_t Size() const; 138*09537850SAkhilesh Sanikop 139*09537850SAkhilesh Sanikop private: 140*09537850SAkhilesh Sanikop mutable std::mutex mutex_; 141*09537850SAkhilesh Sanikop ResidualBufferStack buffers_ LIBGAV1_GUARDED_BY(mutex_); 142*09537850SAkhilesh Sanikop size_t buffer_size_; 143*09537850SAkhilesh Sanikop int queue_size_; 144*09537850SAkhilesh Sanikop }; 145*09537850SAkhilesh Sanikop 146*09537850SAkhilesh Sanikop } // namespace libgav1 147*09537850SAkhilesh Sanikop 148*09537850SAkhilesh Sanikop #endif // LIBGAV1_SRC_RESIDUAL_BUFFER_POOL_H_ 149