xref: /aosp_15_r20/external/libgav1/src/buffer_pool.cc (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1*09537850SAkhilesh Sanikop // Copyright 2019 The libgav1 Authors
2*09537850SAkhilesh Sanikop //
3*09537850SAkhilesh Sanikop // Licensed under the Apache License, Version 2.0 (the "License");
4*09537850SAkhilesh Sanikop // you may not use this file except in compliance with the License.
5*09537850SAkhilesh Sanikop // You may obtain a copy of the License at
6*09537850SAkhilesh Sanikop //
7*09537850SAkhilesh Sanikop //      http://www.apache.org/licenses/LICENSE-2.0
8*09537850SAkhilesh Sanikop //
9*09537850SAkhilesh Sanikop // Unless required by applicable law or agreed to in writing, software
10*09537850SAkhilesh Sanikop // distributed under the License is distributed on an "AS IS" BASIS,
11*09537850SAkhilesh Sanikop // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*09537850SAkhilesh Sanikop // See the License for the specific language governing permissions and
13*09537850SAkhilesh Sanikop // limitations under the License.
14*09537850SAkhilesh Sanikop 
15*09537850SAkhilesh Sanikop #include "src/buffer_pool.h"
16*09537850SAkhilesh Sanikop 
17*09537850SAkhilesh Sanikop #include <cassert>
18*09537850SAkhilesh Sanikop #include <cstring>
19*09537850SAkhilesh Sanikop 
20*09537850SAkhilesh Sanikop #include "src/utils/common.h"
21*09537850SAkhilesh Sanikop #include "src/utils/constants.h"
22*09537850SAkhilesh Sanikop #include "src/utils/logging.h"
23*09537850SAkhilesh Sanikop 
24*09537850SAkhilesh Sanikop namespace libgav1 {
25*09537850SAkhilesh Sanikop 
26*09537850SAkhilesh Sanikop namespace {
27*09537850SAkhilesh Sanikop 
28*09537850SAkhilesh Sanikop // Copies the feature_enabled, feature_data, segment_id_pre_skip, and
29*09537850SAkhilesh Sanikop // last_active_segment_id fields of Segmentation.
CopySegmentationParameters(const Segmentation & from,Segmentation * to)30*09537850SAkhilesh Sanikop void CopySegmentationParameters(const Segmentation& from, Segmentation* to) {
31*09537850SAkhilesh Sanikop   memcpy(to->feature_enabled, from.feature_enabled,
32*09537850SAkhilesh Sanikop          sizeof(to->feature_enabled));
33*09537850SAkhilesh Sanikop   memcpy(to->feature_data, from.feature_data, sizeof(to->feature_data));
34*09537850SAkhilesh Sanikop   to->segment_id_pre_skip = from.segment_id_pre_skip;
35*09537850SAkhilesh Sanikop   to->last_active_segment_id = from.last_active_segment_id;
36*09537850SAkhilesh Sanikop }
37*09537850SAkhilesh Sanikop 
38*09537850SAkhilesh Sanikop }  // namespace
39*09537850SAkhilesh Sanikop 
40*09537850SAkhilesh Sanikop RefCountedBuffer::RefCountedBuffer() = default;
41*09537850SAkhilesh Sanikop 
42*09537850SAkhilesh Sanikop RefCountedBuffer::~RefCountedBuffer() = default;
43*09537850SAkhilesh Sanikop 
Realloc(int bitdepth,bool is_monochrome,int width,int height,int subsampling_x,int subsampling_y,int left_border,int right_border,int top_border,int bottom_border)44*09537850SAkhilesh Sanikop bool RefCountedBuffer::Realloc(int bitdepth, bool is_monochrome, int width,
45*09537850SAkhilesh Sanikop                                int height, int subsampling_x, int subsampling_y,
46*09537850SAkhilesh Sanikop                                int left_border, int right_border,
47*09537850SAkhilesh Sanikop                                int top_border, int bottom_border) {
48*09537850SAkhilesh Sanikop   // The YuvBuffer::Realloc() could call the get frame buffer callback which
49*09537850SAkhilesh Sanikop   // will need to be thread safe. So we ensure that we only call Realloc() once
50*09537850SAkhilesh Sanikop   // at any given time.
51*09537850SAkhilesh Sanikop   std::lock_guard<std::mutex> lock(pool_->mutex_);
52*09537850SAkhilesh Sanikop   assert(!buffer_private_data_valid_);
53*09537850SAkhilesh Sanikop   if (!yuv_buffer_.Realloc(
54*09537850SAkhilesh Sanikop           bitdepth, is_monochrome, width, height, subsampling_x, subsampling_y,
55*09537850SAkhilesh Sanikop           left_border, right_border, top_border, bottom_border,
56*09537850SAkhilesh Sanikop           pool_->get_frame_buffer_, pool_->callback_private_data_,
57*09537850SAkhilesh Sanikop           &buffer_private_data_)) {
58*09537850SAkhilesh Sanikop     return false;
59*09537850SAkhilesh Sanikop   }
60*09537850SAkhilesh Sanikop   buffer_private_data_valid_ = true;
61*09537850SAkhilesh Sanikop   return true;
62*09537850SAkhilesh Sanikop }
63*09537850SAkhilesh Sanikop 
SetFrameDimensions(const ObuFrameHeader & frame_header)64*09537850SAkhilesh Sanikop bool RefCountedBuffer::SetFrameDimensions(const ObuFrameHeader& frame_header) {
65*09537850SAkhilesh Sanikop   upscaled_width_ = frame_header.upscaled_width;
66*09537850SAkhilesh Sanikop   frame_width_ = frame_header.width;
67*09537850SAkhilesh Sanikop   frame_height_ = frame_header.height;
68*09537850SAkhilesh Sanikop   render_width_ = frame_header.render_width;
69*09537850SAkhilesh Sanikop   render_height_ = frame_header.render_height;
70*09537850SAkhilesh Sanikop   rows4x4_ = frame_header.rows4x4;
71*09537850SAkhilesh Sanikop   columns4x4_ = frame_header.columns4x4;
72*09537850SAkhilesh Sanikop   if (frame_header.refresh_frame_flags != 0 &&
73*09537850SAkhilesh Sanikop       !IsIntraFrame(frame_header.frame_type)) {
74*09537850SAkhilesh Sanikop     const int rows4x4_half = DivideBy2(rows4x4_);
75*09537850SAkhilesh Sanikop     const int columns4x4_half = DivideBy2(columns4x4_);
76*09537850SAkhilesh Sanikop     if (!reference_info_.Reset(rows4x4_half, columns4x4_half)) {
77*09537850SAkhilesh Sanikop       return false;
78*09537850SAkhilesh Sanikop     }
79*09537850SAkhilesh Sanikop   }
80*09537850SAkhilesh Sanikop   return segmentation_map_.Allocate(rows4x4_, columns4x4_);
81*09537850SAkhilesh Sanikop }
82*09537850SAkhilesh Sanikop 
SetGlobalMotions(const std::array<GlobalMotion,kNumReferenceFrameTypes> & global_motions)83*09537850SAkhilesh Sanikop void RefCountedBuffer::SetGlobalMotions(
84*09537850SAkhilesh Sanikop     const std::array<GlobalMotion, kNumReferenceFrameTypes>& global_motions) {
85*09537850SAkhilesh Sanikop   for (int ref = kReferenceFrameLast; ref <= kReferenceFrameAlternate; ++ref) {
86*09537850SAkhilesh Sanikop     static_assert(sizeof(global_motion_[ref].params) ==
87*09537850SAkhilesh Sanikop                       sizeof(global_motions[ref].params),
88*09537850SAkhilesh Sanikop                   "");
89*09537850SAkhilesh Sanikop     memcpy(global_motion_[ref].params, global_motions[ref].params,
90*09537850SAkhilesh Sanikop            sizeof(global_motion_[ref].params));
91*09537850SAkhilesh Sanikop   }
92*09537850SAkhilesh Sanikop }
93*09537850SAkhilesh Sanikop 
SetFrameContext(const SymbolDecoderContext & context)94*09537850SAkhilesh Sanikop void RefCountedBuffer::SetFrameContext(const SymbolDecoderContext& context) {
95*09537850SAkhilesh Sanikop   frame_context_ = context;
96*09537850SAkhilesh Sanikop   frame_context_.ResetIntraFrameYModeCdf();
97*09537850SAkhilesh Sanikop   frame_context_.ResetCounters();
98*09537850SAkhilesh Sanikop }
99*09537850SAkhilesh Sanikop 
GetSegmentationParameters(Segmentation * segmentation) const100*09537850SAkhilesh Sanikop void RefCountedBuffer::GetSegmentationParameters(
101*09537850SAkhilesh Sanikop     Segmentation* segmentation) const {
102*09537850SAkhilesh Sanikop   CopySegmentationParameters(/*from=*/segmentation_, /*to=*/segmentation);
103*09537850SAkhilesh Sanikop }
104*09537850SAkhilesh Sanikop 
SetSegmentationParameters(const Segmentation & segmentation)105*09537850SAkhilesh Sanikop void RefCountedBuffer::SetSegmentationParameters(
106*09537850SAkhilesh Sanikop     const Segmentation& segmentation) {
107*09537850SAkhilesh Sanikop   CopySegmentationParameters(/*from=*/segmentation, /*to=*/&segmentation_);
108*09537850SAkhilesh Sanikop }
109*09537850SAkhilesh Sanikop 
SetBufferPool(BufferPool * pool)110*09537850SAkhilesh Sanikop void RefCountedBuffer::SetBufferPool(BufferPool* pool) { pool_ = pool; }
111*09537850SAkhilesh Sanikop 
ReturnToBufferPool(RefCountedBuffer * ptr)112*09537850SAkhilesh Sanikop void RefCountedBuffer::ReturnToBufferPool(RefCountedBuffer* ptr) {
113*09537850SAkhilesh Sanikop   ptr->pool_->ReturnUnusedBuffer(ptr);
114*09537850SAkhilesh Sanikop }
115*09537850SAkhilesh Sanikop 
BufferPool(FrameBufferSizeChangedCallback on_frame_buffer_size_changed,GetFrameBufferCallback get_frame_buffer,ReleaseFrameBufferCallback release_frame_buffer,void * callback_private_data)116*09537850SAkhilesh Sanikop BufferPool::BufferPool(
117*09537850SAkhilesh Sanikop     FrameBufferSizeChangedCallback on_frame_buffer_size_changed,
118*09537850SAkhilesh Sanikop     GetFrameBufferCallback get_frame_buffer,
119*09537850SAkhilesh Sanikop     ReleaseFrameBufferCallback release_frame_buffer,
120*09537850SAkhilesh Sanikop     void* callback_private_data) {
121*09537850SAkhilesh Sanikop   if (get_frame_buffer != nullptr) {
122*09537850SAkhilesh Sanikop     // on_frame_buffer_size_changed may be null.
123*09537850SAkhilesh Sanikop     assert(release_frame_buffer != nullptr);
124*09537850SAkhilesh Sanikop     on_frame_buffer_size_changed_ = on_frame_buffer_size_changed;
125*09537850SAkhilesh Sanikop     get_frame_buffer_ = get_frame_buffer;
126*09537850SAkhilesh Sanikop     release_frame_buffer_ = release_frame_buffer;
127*09537850SAkhilesh Sanikop     callback_private_data_ = callback_private_data;
128*09537850SAkhilesh Sanikop   } else {
129*09537850SAkhilesh Sanikop     on_frame_buffer_size_changed_ = OnInternalFrameBufferSizeChanged;
130*09537850SAkhilesh Sanikop     get_frame_buffer_ = GetInternalFrameBuffer;
131*09537850SAkhilesh Sanikop     release_frame_buffer_ = ReleaseInternalFrameBuffer;
132*09537850SAkhilesh Sanikop     callback_private_data_ = &internal_frame_buffers_;
133*09537850SAkhilesh Sanikop   }
134*09537850SAkhilesh Sanikop }
135*09537850SAkhilesh Sanikop 
~BufferPool()136*09537850SAkhilesh Sanikop BufferPool::~BufferPool() {
137*09537850SAkhilesh Sanikop   for (const auto* buffer : buffers_) {
138*09537850SAkhilesh Sanikop     if (buffer->in_use_) {
139*09537850SAkhilesh Sanikop       assert(false && "RefCountedBuffer still in use at destruction time.");
140*09537850SAkhilesh Sanikop       LIBGAV1_DLOG(ERROR, "RefCountedBuffer still in use at destruction time.");
141*09537850SAkhilesh Sanikop     }
142*09537850SAkhilesh Sanikop     delete buffer;
143*09537850SAkhilesh Sanikop   }
144*09537850SAkhilesh Sanikop }
145*09537850SAkhilesh Sanikop 
OnFrameBufferSizeChanged(int bitdepth,Libgav1ImageFormat image_format,int width,int height,int left_border,int right_border,int top_border,int bottom_border)146*09537850SAkhilesh Sanikop bool BufferPool::OnFrameBufferSizeChanged(int bitdepth,
147*09537850SAkhilesh Sanikop                                           Libgav1ImageFormat image_format,
148*09537850SAkhilesh Sanikop                                           int width, int height,
149*09537850SAkhilesh Sanikop                                           int left_border, int right_border,
150*09537850SAkhilesh Sanikop                                           int top_border, int bottom_border) {
151*09537850SAkhilesh Sanikop   if (on_frame_buffer_size_changed_ == nullptr) return true;
152*09537850SAkhilesh Sanikop   return on_frame_buffer_size_changed_(callback_private_data_, bitdepth,
153*09537850SAkhilesh Sanikop                                        image_format, width, height, left_border,
154*09537850SAkhilesh Sanikop                                        right_border, top_border, bottom_border,
155*09537850SAkhilesh Sanikop                                        /*stride_alignment=*/16) == kStatusOk;
156*09537850SAkhilesh Sanikop }
157*09537850SAkhilesh Sanikop 
GetFreeBuffer()158*09537850SAkhilesh Sanikop RefCountedBufferPtr BufferPool::GetFreeBuffer() {
159*09537850SAkhilesh Sanikop   std::unique_lock<std::mutex> lock(mutex_);
160*09537850SAkhilesh Sanikop   for (auto buffer : buffers_) {
161*09537850SAkhilesh Sanikop     if (!buffer->in_use_) {
162*09537850SAkhilesh Sanikop       buffer->in_use_ = true;
163*09537850SAkhilesh Sanikop       buffer->progress_row_ = -1;
164*09537850SAkhilesh Sanikop       buffer->frame_state_ = kFrameStateUnknown;
165*09537850SAkhilesh Sanikop       buffer->hdr_cll_set_ = false;
166*09537850SAkhilesh Sanikop       buffer->hdr_mdcv_set_ = false;
167*09537850SAkhilesh Sanikop       buffer->itut_t35_set_ = false;
168*09537850SAkhilesh Sanikop       lock.unlock();
169*09537850SAkhilesh Sanikop       return RefCountedBufferPtr(buffer, RefCountedBuffer::ReturnToBufferPool);
170*09537850SAkhilesh Sanikop     }
171*09537850SAkhilesh Sanikop   }
172*09537850SAkhilesh Sanikop   lock.unlock();
173*09537850SAkhilesh Sanikop   auto* const buffer = new (std::nothrow) RefCountedBuffer();
174*09537850SAkhilesh Sanikop   if (buffer == nullptr) {
175*09537850SAkhilesh Sanikop     LIBGAV1_DLOG(ERROR, "Failed to allocate a new reference counted buffer.");
176*09537850SAkhilesh Sanikop     return RefCountedBufferPtr();
177*09537850SAkhilesh Sanikop   }
178*09537850SAkhilesh Sanikop   buffer->SetBufferPool(this);
179*09537850SAkhilesh Sanikop   buffer->in_use_ = true;
180*09537850SAkhilesh Sanikop   buffer->progress_row_ = -1;
181*09537850SAkhilesh Sanikop   buffer->frame_state_ = kFrameStateUnknown;
182*09537850SAkhilesh Sanikop   lock.lock();
183*09537850SAkhilesh Sanikop   const bool ok = buffers_.push_back(buffer);
184*09537850SAkhilesh Sanikop   lock.unlock();
185*09537850SAkhilesh Sanikop   if (!ok) {
186*09537850SAkhilesh Sanikop     LIBGAV1_DLOG(
187*09537850SAkhilesh Sanikop         ERROR,
188*09537850SAkhilesh Sanikop         "Failed to push the new reference counted buffer into the vector.");
189*09537850SAkhilesh Sanikop     delete buffer;
190*09537850SAkhilesh Sanikop     return RefCountedBufferPtr();
191*09537850SAkhilesh Sanikop   }
192*09537850SAkhilesh Sanikop   return RefCountedBufferPtr(buffer, RefCountedBuffer::ReturnToBufferPool);
193*09537850SAkhilesh Sanikop }
194*09537850SAkhilesh Sanikop 
Abort()195*09537850SAkhilesh Sanikop void BufferPool::Abort() {
196*09537850SAkhilesh Sanikop   std::unique_lock<std::mutex> lock(mutex_);
197*09537850SAkhilesh Sanikop   for (auto buffer : buffers_) {
198*09537850SAkhilesh Sanikop     if (buffer->in_use_) {
199*09537850SAkhilesh Sanikop       buffer->Abort();
200*09537850SAkhilesh Sanikop     }
201*09537850SAkhilesh Sanikop   }
202*09537850SAkhilesh Sanikop }
203*09537850SAkhilesh Sanikop 
ReturnUnusedBuffer(RefCountedBuffer * buffer)204*09537850SAkhilesh Sanikop void BufferPool::ReturnUnusedBuffer(RefCountedBuffer* buffer) {
205*09537850SAkhilesh Sanikop   std::lock_guard<std::mutex> lock(mutex_);
206*09537850SAkhilesh Sanikop   assert(buffer->in_use_);
207*09537850SAkhilesh Sanikop   buffer->in_use_ = false;
208*09537850SAkhilesh Sanikop   if (buffer->buffer_private_data_valid_) {
209*09537850SAkhilesh Sanikop     release_frame_buffer_(callback_private_data_, buffer->buffer_private_data_);
210*09537850SAkhilesh Sanikop     buffer->buffer_private_data_valid_ = false;
211*09537850SAkhilesh Sanikop   }
212*09537850SAkhilesh Sanikop }
213*09537850SAkhilesh Sanikop 
214*09537850SAkhilesh Sanikop }  // namespace libgav1
215