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