xref: /aosp_15_r20/external/libgav1/src/buffer_pool.h (revision 095378508e87ed692bf8dfeb34008b65b3735891)
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_BUFFER_POOL_H_
18*09537850SAkhilesh Sanikop #define LIBGAV1_SRC_BUFFER_POOL_H_
19*09537850SAkhilesh Sanikop 
20*09537850SAkhilesh Sanikop #include <algorithm>
21*09537850SAkhilesh Sanikop #include <array>
22*09537850SAkhilesh Sanikop #include <cassert>
23*09537850SAkhilesh Sanikop #include <climits>
24*09537850SAkhilesh Sanikop #include <condition_variable>  // NOLINT (unapproved c++11 header)
25*09537850SAkhilesh Sanikop #include <cstdint>
26*09537850SAkhilesh Sanikop #include <memory>
27*09537850SAkhilesh Sanikop #include <mutex>  // NOLINT (unapproved c++11 header)
28*09537850SAkhilesh Sanikop 
29*09537850SAkhilesh Sanikop #include "src/dsp/common.h"
30*09537850SAkhilesh Sanikop #include "src/gav1/decoder_buffer.h"
31*09537850SAkhilesh Sanikop #include "src/gav1/frame_buffer.h"
32*09537850SAkhilesh Sanikop #include "src/internal_frame_buffer_list.h"
33*09537850SAkhilesh Sanikop #include "src/symbol_decoder_context.h"
34*09537850SAkhilesh Sanikop #include "src/utils/compiler_attributes.h"
35*09537850SAkhilesh Sanikop #include "src/utils/constants.h"
36*09537850SAkhilesh Sanikop #include "src/utils/dynamic_buffer.h"
37*09537850SAkhilesh Sanikop #include "src/utils/reference_info.h"
38*09537850SAkhilesh Sanikop #include "src/utils/segmentation.h"
39*09537850SAkhilesh Sanikop #include "src/utils/segmentation_map.h"
40*09537850SAkhilesh Sanikop #include "src/utils/types.h"
41*09537850SAkhilesh Sanikop #include "src/utils/vector.h"
42*09537850SAkhilesh Sanikop #include "src/yuv_buffer.h"
43*09537850SAkhilesh Sanikop 
44*09537850SAkhilesh Sanikop namespace libgav1 {
45*09537850SAkhilesh Sanikop 
46*09537850SAkhilesh Sanikop class BufferPool;
47*09537850SAkhilesh Sanikop 
48*09537850SAkhilesh Sanikop enum FrameState : uint8_t {
49*09537850SAkhilesh Sanikop   kFrameStateUnknown,
50*09537850SAkhilesh Sanikop   kFrameStateStarted,
51*09537850SAkhilesh Sanikop   kFrameStateParsed,
52*09537850SAkhilesh Sanikop   kFrameStateDecoded
53*09537850SAkhilesh Sanikop };
54*09537850SAkhilesh Sanikop 
55*09537850SAkhilesh Sanikop // A reference-counted frame buffer. Clients should access it via
56*09537850SAkhilesh Sanikop // RefCountedBufferPtr, which manages reference counting transparently.
57*09537850SAkhilesh Sanikop // The alignment requirement is due to the SymbolDecoderContext member
58*09537850SAkhilesh Sanikop // frame_context_.
59*09537850SAkhilesh Sanikop class RefCountedBuffer : public MaxAlignedAllocable {
60*09537850SAkhilesh Sanikop  public:
61*09537850SAkhilesh Sanikop   // Not copyable or movable.
62*09537850SAkhilesh Sanikop   RefCountedBuffer(const RefCountedBuffer&) = delete;
63*09537850SAkhilesh Sanikop   RefCountedBuffer& operator=(const RefCountedBuffer&) = delete;
64*09537850SAkhilesh Sanikop 
65*09537850SAkhilesh Sanikop   // Allocates the YUV buffer. Returns true on success. Returns false on
66*09537850SAkhilesh Sanikop   // failure. This function ensures the thread safety of the |get_frame_buffer_|
67*09537850SAkhilesh Sanikop   // call (i.e.) only one |get_frame_buffer_| call will happen at a given time.
68*09537850SAkhilesh Sanikop   // TODO(b/142583029): In frame parallel mode, we can require the callbacks to
69*09537850SAkhilesh Sanikop   // be thread safe so that we can remove the thread safety of this function and
70*09537850SAkhilesh Sanikop   // applications can have fine grained locks.
71*09537850SAkhilesh Sanikop   //
72*09537850SAkhilesh Sanikop   // * |width| and |height| are the image dimensions in pixels.
73*09537850SAkhilesh Sanikop   // * |subsampling_x| and |subsampling_y| (either 0 or 1) specify the
74*09537850SAkhilesh Sanikop   //   subsampling of the width and height of the chroma planes, respectively.
75*09537850SAkhilesh Sanikop   // * |left_border|, |right_border|, |top_border|, and |bottom_border| are
76*09537850SAkhilesh Sanikop   //   the sizes (in pixels) of the borders on the left, right, top, and
77*09537850SAkhilesh Sanikop   //   bottom sides, respectively.
78*09537850SAkhilesh Sanikop   //
79*09537850SAkhilesh Sanikop   // NOTE: The strides are a multiple of 16. Since the first row in each plane
80*09537850SAkhilesh Sanikop   // is 16-byte aligned, subsequent rows are also 16-byte aligned.
81*09537850SAkhilesh Sanikop   bool Realloc(int bitdepth, bool is_monochrome, int width, int height,
82*09537850SAkhilesh Sanikop                int subsampling_x, int subsampling_y, int left_border,
83*09537850SAkhilesh Sanikop                int right_border, int top_border, int bottom_border);
84*09537850SAkhilesh Sanikop 
buffer()85*09537850SAkhilesh Sanikop   YuvBuffer* buffer() { return &yuv_buffer_; }
86*09537850SAkhilesh Sanikop 
87*09537850SAkhilesh Sanikop   // Returns the buffer private data set by the get frame buffer callback when
88*09537850SAkhilesh Sanikop   // it allocated the YUV buffer.
buffer_private_data()89*09537850SAkhilesh Sanikop   void* buffer_private_data() const {
90*09537850SAkhilesh Sanikop     assert(buffer_private_data_valid_);
91*09537850SAkhilesh Sanikop     return buffer_private_data_;
92*09537850SAkhilesh Sanikop   }
93*09537850SAkhilesh Sanikop 
94*09537850SAkhilesh Sanikop   // NOTE: In the current frame, this is the frame_type syntax element in the
95*09537850SAkhilesh Sanikop   // frame header. In a reference frame, this implements the RefFrameType array
96*09537850SAkhilesh Sanikop   // in the spec.
frame_type()97*09537850SAkhilesh Sanikop   FrameType frame_type() const { return frame_type_; }
set_frame_type(FrameType frame_type)98*09537850SAkhilesh Sanikop   void set_frame_type(FrameType frame_type) { frame_type_ = frame_type; }
99*09537850SAkhilesh Sanikop 
100*09537850SAkhilesh Sanikop   // The sample position for subsampled streams. This is the
101*09537850SAkhilesh Sanikop   // chroma_sample_position syntax element in the sequence header.
102*09537850SAkhilesh Sanikop   //
103*09537850SAkhilesh Sanikop   // NOTE: The decoder does not use chroma_sample_position, but it needs to be
104*09537850SAkhilesh Sanikop   // passed on to the client in DecoderBuffer.
chroma_sample_position()105*09537850SAkhilesh Sanikop   ChromaSamplePosition chroma_sample_position() const {
106*09537850SAkhilesh Sanikop     return chroma_sample_position_;
107*09537850SAkhilesh Sanikop   }
set_chroma_sample_position(ChromaSamplePosition chroma_sample_position)108*09537850SAkhilesh Sanikop   void set_chroma_sample_position(ChromaSamplePosition chroma_sample_position) {
109*09537850SAkhilesh Sanikop     chroma_sample_position_ = chroma_sample_position;
110*09537850SAkhilesh Sanikop   }
111*09537850SAkhilesh Sanikop 
112*09537850SAkhilesh Sanikop   // Whether the frame can be used as show existing frame in the future.
showable_frame()113*09537850SAkhilesh Sanikop   bool showable_frame() const { return showable_frame_; }
set_showable_frame(bool value)114*09537850SAkhilesh Sanikop   void set_showable_frame(bool value) { showable_frame_ = value; }
115*09537850SAkhilesh Sanikop 
116*09537850SAkhilesh Sanikop   // Sets upscaled_width_, frame_width_, frame_height_, render_width_,
117*09537850SAkhilesh Sanikop   // render_height_, rows4x4_ and columns4x4_ from the corresponding fields
118*09537850SAkhilesh Sanikop   // in frame_header. Allocates reference_info_.motion_field_reference_frame,
119*09537850SAkhilesh Sanikop   // reference_info_.motion_field_mv_, and segmentation_map_. Returns true on
120*09537850SAkhilesh Sanikop   // success, false on failure.
121*09537850SAkhilesh Sanikop   bool SetFrameDimensions(const ObuFrameHeader& frame_header);
122*09537850SAkhilesh Sanikop 
upscaled_width()123*09537850SAkhilesh Sanikop   int32_t upscaled_width() const { return upscaled_width_; }
frame_width()124*09537850SAkhilesh Sanikop   int32_t frame_width() const { return frame_width_; }
frame_height()125*09537850SAkhilesh Sanikop   int32_t frame_height() const { return frame_height_; }
126*09537850SAkhilesh Sanikop   // RenderWidth() and RenderHeight() return the render size, which is a hint
127*09537850SAkhilesh Sanikop   // to the application about the desired display size.
render_width()128*09537850SAkhilesh Sanikop   int32_t render_width() const { return render_width_; }
render_height()129*09537850SAkhilesh Sanikop   int32_t render_height() const { return render_height_; }
rows4x4()130*09537850SAkhilesh Sanikop   int32_t rows4x4() const { return rows4x4_; }
columns4x4()131*09537850SAkhilesh Sanikop   int32_t columns4x4() const { return columns4x4_; }
132*09537850SAkhilesh Sanikop 
spatial_id()133*09537850SAkhilesh Sanikop   int spatial_id() const { return spatial_id_; }
set_spatial_id(int value)134*09537850SAkhilesh Sanikop   void set_spatial_id(int value) { spatial_id_ = value; }
temporal_id()135*09537850SAkhilesh Sanikop   int temporal_id() const { return temporal_id_; }
set_temporal_id(int value)136*09537850SAkhilesh Sanikop   void set_temporal_id(int value) { temporal_id_ = value; }
137*09537850SAkhilesh Sanikop 
hdr_cll()138*09537850SAkhilesh Sanikop   ObuMetadataHdrCll hdr_cll() const { return hdr_cll_; }
set_hdr_cll(const ObuMetadataHdrCll & hdr_cll)139*09537850SAkhilesh Sanikop   void set_hdr_cll(const ObuMetadataHdrCll& hdr_cll) {
140*09537850SAkhilesh Sanikop     hdr_cll_set_ = true;
141*09537850SAkhilesh Sanikop     hdr_cll_ = hdr_cll;
142*09537850SAkhilesh Sanikop   }
hdr_cll_set()143*09537850SAkhilesh Sanikop   bool hdr_cll_set() const { return hdr_cll_set_; }
144*09537850SAkhilesh Sanikop 
hdr_mdcv()145*09537850SAkhilesh Sanikop   ObuMetadataHdrMdcv hdr_mdcv() const { return hdr_mdcv_; }
set_hdr_mdcv(const ObuMetadataHdrMdcv & hdr_mdcv)146*09537850SAkhilesh Sanikop   void set_hdr_mdcv(const ObuMetadataHdrMdcv& hdr_mdcv) {
147*09537850SAkhilesh Sanikop     hdr_mdcv_set_ = true;
148*09537850SAkhilesh Sanikop     hdr_mdcv_ = hdr_mdcv;
149*09537850SAkhilesh Sanikop   }
hdr_mdcv_set()150*09537850SAkhilesh Sanikop   bool hdr_mdcv_set() const { return hdr_mdcv_set_; }
151*09537850SAkhilesh Sanikop 
itut_t35()152*09537850SAkhilesh Sanikop   ObuMetadataItutT35 itut_t35() const { return itut_t35_; }
set_itut_t35(const ObuMetadataItutT35 & itut_t35,const uint8_t * const payload)153*09537850SAkhilesh Sanikop   bool set_itut_t35(const ObuMetadataItutT35& itut_t35,
154*09537850SAkhilesh Sanikop                     const uint8_t* const payload) {
155*09537850SAkhilesh Sanikop     itut_t35_ = itut_t35;
156*09537850SAkhilesh Sanikop     if (itut_t35.payload_size > 0) {
157*09537850SAkhilesh Sanikop       if (!itut_t35_payload_.Resize(itut_t35.payload_size)) return false;
158*09537850SAkhilesh Sanikop       memcpy(itut_t35_payload_.get(), payload, itut_t35.payload_size);
159*09537850SAkhilesh Sanikop       itut_t35_.payload_bytes = itut_t35_payload_.get();
160*09537850SAkhilesh Sanikop     } else {
161*09537850SAkhilesh Sanikop       itut_t35_.payload_bytes = nullptr;
162*09537850SAkhilesh Sanikop     }
163*09537850SAkhilesh Sanikop     itut_t35_set_ = true;
164*09537850SAkhilesh Sanikop     return true;
165*09537850SAkhilesh Sanikop   }
itut_t35_set()166*09537850SAkhilesh Sanikop   bool itut_t35_set() const { return itut_t35_set_; }
167*09537850SAkhilesh Sanikop 
segmentation_map()168*09537850SAkhilesh Sanikop   SegmentationMap* segmentation_map() { return &segmentation_map_; }
segmentation_map()169*09537850SAkhilesh Sanikop   const SegmentationMap* segmentation_map() const { return &segmentation_map_; }
170*09537850SAkhilesh Sanikop 
171*09537850SAkhilesh Sanikop   // Only the |params| field of each GlobalMotion struct should be used.
GlobalMotions()172*09537850SAkhilesh Sanikop   const std::array<GlobalMotion, kNumReferenceFrameTypes>& GlobalMotions()
173*09537850SAkhilesh Sanikop       const {
174*09537850SAkhilesh Sanikop     return global_motion_;
175*09537850SAkhilesh Sanikop   }
176*09537850SAkhilesh Sanikop   // Saves the GlobalMotion array. Only the |params| field of each GlobalMotion
177*09537850SAkhilesh Sanikop   // struct is saved.
178*09537850SAkhilesh Sanikop   void SetGlobalMotions(
179*09537850SAkhilesh Sanikop       const std::array<GlobalMotion, kNumReferenceFrameTypes>& global_motions);
180*09537850SAkhilesh Sanikop 
181*09537850SAkhilesh Sanikop   // Returns the saved CDF tables.
FrameContext()182*09537850SAkhilesh Sanikop   const SymbolDecoderContext& FrameContext() const { return frame_context_; }
183*09537850SAkhilesh Sanikop   // Saves the CDF tables. The intra_frame_y_mode_cdf table is reset to the
184*09537850SAkhilesh Sanikop   // default. The last entry in each table, representing the symbol count for
185*09537850SAkhilesh Sanikop   // that context, is set to 0.
186*09537850SAkhilesh Sanikop   void SetFrameContext(const SymbolDecoderContext& context);
187*09537850SAkhilesh Sanikop 
loop_filter_ref_deltas()188*09537850SAkhilesh Sanikop   const std::array<int8_t, kNumReferenceFrameTypes>& loop_filter_ref_deltas()
189*09537850SAkhilesh Sanikop       const {
190*09537850SAkhilesh Sanikop     return loop_filter_ref_deltas_;
191*09537850SAkhilesh Sanikop   }
loop_filter_mode_deltas()192*09537850SAkhilesh Sanikop   const std::array<int8_t, kLoopFilterMaxModeDeltas>& loop_filter_mode_deltas()
193*09537850SAkhilesh Sanikop       const {
194*09537850SAkhilesh Sanikop     return loop_filter_mode_deltas_;
195*09537850SAkhilesh Sanikop   }
196*09537850SAkhilesh Sanikop   // Saves the ref_deltas and mode_deltas arrays in loop_filter.
SetLoopFilterDeltas(const LoopFilter & loop_filter)197*09537850SAkhilesh Sanikop   void SetLoopFilterDeltas(const LoopFilter& loop_filter) {
198*09537850SAkhilesh Sanikop     loop_filter_ref_deltas_ = loop_filter.ref_deltas;
199*09537850SAkhilesh Sanikop     loop_filter_mode_deltas_ = loop_filter.mode_deltas;
200*09537850SAkhilesh Sanikop   }
201*09537850SAkhilesh Sanikop 
202*09537850SAkhilesh Sanikop   // Copies the saved values of the following fields to the Segmentation
203*09537850SAkhilesh Sanikop   // struct: feature_enabled, feature_data, segment_id_pre_skip, and
204*09537850SAkhilesh Sanikop   // last_active_segment_id. The other fields are left unchanged.
205*09537850SAkhilesh Sanikop   void GetSegmentationParameters(Segmentation* segmentation) const;
206*09537850SAkhilesh Sanikop   // Saves the feature_enabled, feature_data, segment_id_pre_skip, and
207*09537850SAkhilesh Sanikop   // last_active_segment_id fields of the Segmentation struct.
208*09537850SAkhilesh Sanikop   void SetSegmentationParameters(const Segmentation& segmentation);
209*09537850SAkhilesh Sanikop 
film_grain_params()210*09537850SAkhilesh Sanikop   const FilmGrainParams& film_grain_params() const {
211*09537850SAkhilesh Sanikop     return film_grain_params_;
212*09537850SAkhilesh Sanikop   }
set_film_grain_params(const FilmGrainParams & params)213*09537850SAkhilesh Sanikop   void set_film_grain_params(const FilmGrainParams& params) {
214*09537850SAkhilesh Sanikop     film_grain_params_ = params;
215*09537850SAkhilesh Sanikop   }
216*09537850SAkhilesh Sanikop 
reference_info()217*09537850SAkhilesh Sanikop   const ReferenceInfo* reference_info() const { return &reference_info_; }
reference_info()218*09537850SAkhilesh Sanikop   ReferenceInfo* reference_info() { return &reference_info_; }
219*09537850SAkhilesh Sanikop 
220*09537850SAkhilesh Sanikop   // This will wake up the WaitUntil*() functions and make them return false.
Abort()221*09537850SAkhilesh Sanikop   void Abort() {
222*09537850SAkhilesh Sanikop     {
223*09537850SAkhilesh Sanikop       std::lock_guard<std::mutex> lock(mutex_);
224*09537850SAkhilesh Sanikop       abort_ = true;
225*09537850SAkhilesh Sanikop     }
226*09537850SAkhilesh Sanikop     parsed_condvar_.notify_all();
227*09537850SAkhilesh Sanikop     decoded_condvar_.notify_all();
228*09537850SAkhilesh Sanikop     progress_row_condvar_.notify_all();
229*09537850SAkhilesh Sanikop   }
230*09537850SAkhilesh Sanikop 
SetFrameState(FrameState frame_state)231*09537850SAkhilesh Sanikop   void SetFrameState(FrameState frame_state) {
232*09537850SAkhilesh Sanikop     {
233*09537850SAkhilesh Sanikop       std::lock_guard<std::mutex> lock(mutex_);
234*09537850SAkhilesh Sanikop       frame_state_ = frame_state;
235*09537850SAkhilesh Sanikop     }
236*09537850SAkhilesh Sanikop     if (frame_state == kFrameStateParsed) {
237*09537850SAkhilesh Sanikop       parsed_condvar_.notify_all();
238*09537850SAkhilesh Sanikop     } else if (frame_state == kFrameStateDecoded) {
239*09537850SAkhilesh Sanikop       decoded_condvar_.notify_all();
240*09537850SAkhilesh Sanikop       progress_row_condvar_.notify_all();
241*09537850SAkhilesh Sanikop     }
242*09537850SAkhilesh Sanikop   }
243*09537850SAkhilesh Sanikop 
244*09537850SAkhilesh Sanikop   // Sets the progress of this frame to |progress_row| and notifies any threads
245*09537850SAkhilesh Sanikop   // that may be waiting on rows <= |progress_row|.
SetProgress(int progress_row)246*09537850SAkhilesh Sanikop   void SetProgress(int progress_row) {
247*09537850SAkhilesh Sanikop     {
248*09537850SAkhilesh Sanikop       std::lock_guard<std::mutex> lock(mutex_);
249*09537850SAkhilesh Sanikop       if (progress_row_ >= progress_row) return;
250*09537850SAkhilesh Sanikop       progress_row_ = progress_row;
251*09537850SAkhilesh Sanikop     }
252*09537850SAkhilesh Sanikop     progress_row_condvar_.notify_all();
253*09537850SAkhilesh Sanikop   }
254*09537850SAkhilesh Sanikop 
MarkFrameAsStarted()255*09537850SAkhilesh Sanikop   void MarkFrameAsStarted() {
256*09537850SAkhilesh Sanikop     std::lock_guard<std::mutex> lock(mutex_);
257*09537850SAkhilesh Sanikop     if (frame_state_ != kFrameStateUnknown) return;
258*09537850SAkhilesh Sanikop     frame_state_ = kFrameStateStarted;
259*09537850SAkhilesh Sanikop   }
260*09537850SAkhilesh Sanikop 
261*09537850SAkhilesh Sanikop   // All the WaitUntil* functions will return true if the desired wait state was
262*09537850SAkhilesh Sanikop   // reached successfully. If the return value is false, then the caller must
263*09537850SAkhilesh Sanikop   // assume that the wait was not successful and try to stop whatever they are
264*09537850SAkhilesh Sanikop   // doing as early as possible.
265*09537850SAkhilesh Sanikop 
266*09537850SAkhilesh Sanikop   // Waits until the frame has been parsed.
WaitUntilParsed()267*09537850SAkhilesh Sanikop   bool WaitUntilParsed() {
268*09537850SAkhilesh Sanikop     std::unique_lock<std::mutex> lock(mutex_);
269*09537850SAkhilesh Sanikop     while (frame_state_ < kFrameStateParsed && !abort_) {
270*09537850SAkhilesh Sanikop       parsed_condvar_.wait(lock);
271*09537850SAkhilesh Sanikop     }
272*09537850SAkhilesh Sanikop     return !abort_;
273*09537850SAkhilesh Sanikop   }
274*09537850SAkhilesh Sanikop 
275*09537850SAkhilesh Sanikop   // Waits until the |progress_row| has been decoded (as indicated either by
276*09537850SAkhilesh Sanikop   // |progress_row_| or |frame_state_|). |progress_row_cache| must not be
277*09537850SAkhilesh Sanikop   // nullptr and will be populated with the value of |progress_row_| after the
278*09537850SAkhilesh Sanikop   // wait.
279*09537850SAkhilesh Sanikop   //
280*09537850SAkhilesh Sanikop   // Typical usage of |progress_row_cache| is as follows:
281*09537850SAkhilesh Sanikop   //  * Initialize |*progress_row_cache| to INT_MIN.
282*09537850SAkhilesh Sanikop   //  * Call WaitUntil only if |*progress_row_cache| < |progress_row|.
WaitUntil(int progress_row,int * progress_row_cache)283*09537850SAkhilesh Sanikop   bool WaitUntil(int progress_row, int* progress_row_cache) {
284*09537850SAkhilesh Sanikop     // If |progress_row| is negative, it means that the wait is on the top
285*09537850SAkhilesh Sanikop     // border to be available. The top border will be available when row 0 has
286*09537850SAkhilesh Sanikop     // been decoded. So we can simply wait on row 0 instead.
287*09537850SAkhilesh Sanikop     progress_row = std::max(progress_row, 0);
288*09537850SAkhilesh Sanikop     std::unique_lock<std::mutex> lock(mutex_);
289*09537850SAkhilesh Sanikop     while (progress_row_ < progress_row && frame_state_ != kFrameStateDecoded &&
290*09537850SAkhilesh Sanikop            !abort_) {
291*09537850SAkhilesh Sanikop       progress_row_condvar_.wait(lock);
292*09537850SAkhilesh Sanikop     }
293*09537850SAkhilesh Sanikop     // Once |frame_state_| reaches kFrameStateDecoded, |progress_row_| may no
294*09537850SAkhilesh Sanikop     // longer be updated. So we set |*progress_row_cache| to INT_MAX in that
295*09537850SAkhilesh Sanikop     // case.
296*09537850SAkhilesh Sanikop     *progress_row_cache =
297*09537850SAkhilesh Sanikop         (frame_state_ != kFrameStateDecoded) ? progress_row_ : INT_MAX;
298*09537850SAkhilesh Sanikop     return !abort_;
299*09537850SAkhilesh Sanikop   }
300*09537850SAkhilesh Sanikop 
301*09537850SAkhilesh Sanikop   // Waits until the entire frame has been decoded.
WaitUntilDecoded()302*09537850SAkhilesh Sanikop   bool WaitUntilDecoded() {
303*09537850SAkhilesh Sanikop     std::unique_lock<std::mutex> lock(mutex_);
304*09537850SAkhilesh Sanikop     while (frame_state_ != kFrameStateDecoded && !abort_) {
305*09537850SAkhilesh Sanikop       decoded_condvar_.wait(lock);
306*09537850SAkhilesh Sanikop     }
307*09537850SAkhilesh Sanikop     return !abort_;
308*09537850SAkhilesh Sanikop   }
309*09537850SAkhilesh Sanikop 
310*09537850SAkhilesh Sanikop  private:
311*09537850SAkhilesh Sanikop   friend class BufferPool;
312*09537850SAkhilesh Sanikop 
313*09537850SAkhilesh Sanikop   // Methods for BufferPool:
314*09537850SAkhilesh Sanikop   RefCountedBuffer();
315*09537850SAkhilesh Sanikop   ~RefCountedBuffer();
316*09537850SAkhilesh Sanikop   void SetBufferPool(BufferPool* pool);
317*09537850SAkhilesh Sanikop   static void ReturnToBufferPool(RefCountedBuffer* ptr);
318*09537850SAkhilesh Sanikop 
319*09537850SAkhilesh Sanikop   BufferPool* pool_ = nullptr;
320*09537850SAkhilesh Sanikop   bool buffer_private_data_valid_ = false;
321*09537850SAkhilesh Sanikop   void* buffer_private_data_ = nullptr;
322*09537850SAkhilesh Sanikop   YuvBuffer yuv_buffer_;
323*09537850SAkhilesh Sanikop   bool in_use_ = false;  // Only used by BufferPool.
324*09537850SAkhilesh Sanikop 
325*09537850SAkhilesh Sanikop   std::mutex mutex_;
326*09537850SAkhilesh Sanikop   FrameState frame_state_ = kFrameStateUnknown LIBGAV1_GUARDED_BY(mutex_);
327*09537850SAkhilesh Sanikop   int progress_row_ = -1 LIBGAV1_GUARDED_BY(mutex_);
328*09537850SAkhilesh Sanikop   // Signaled when progress_row_ is updated or when frame_state_ is set to
329*09537850SAkhilesh Sanikop   // kFrameStateDecoded.
330*09537850SAkhilesh Sanikop   std::condition_variable progress_row_condvar_;
331*09537850SAkhilesh Sanikop   // Signaled when the frame state is set to kFrameStateParsed.
332*09537850SAkhilesh Sanikop   std::condition_variable parsed_condvar_;
333*09537850SAkhilesh Sanikop   // Signaled when the frame state is set to kFrameStateDecoded.
334*09537850SAkhilesh Sanikop   std::condition_variable decoded_condvar_;
335*09537850SAkhilesh Sanikop   bool abort_ = false LIBGAV1_GUARDED_BY(mutex_);
336*09537850SAkhilesh Sanikop 
337*09537850SAkhilesh Sanikop   FrameType frame_type_ = kFrameKey;
338*09537850SAkhilesh Sanikop   ChromaSamplePosition chroma_sample_position_ = kChromaSamplePositionUnknown;
339*09537850SAkhilesh Sanikop   bool showable_frame_ = false;
340*09537850SAkhilesh Sanikop 
341*09537850SAkhilesh Sanikop   int32_t upscaled_width_ = 0;
342*09537850SAkhilesh Sanikop   int32_t frame_width_ = 0;
343*09537850SAkhilesh Sanikop   int32_t frame_height_ = 0;
344*09537850SAkhilesh Sanikop   int32_t render_width_ = 0;
345*09537850SAkhilesh Sanikop   int32_t render_height_ = 0;
346*09537850SAkhilesh Sanikop   int32_t columns4x4_ = 0;
347*09537850SAkhilesh Sanikop   int32_t rows4x4_ = 0;
348*09537850SAkhilesh Sanikop   int spatial_id_ = 0;
349*09537850SAkhilesh Sanikop   int temporal_id_ = 0;
350*09537850SAkhilesh Sanikop 
351*09537850SAkhilesh Sanikop   ObuMetadataHdrCll hdr_cll_ = {};
352*09537850SAkhilesh Sanikop   bool hdr_cll_set_ = false;  // Set to true when set_hdr_cll() is called.
353*09537850SAkhilesh Sanikop   ObuMetadataHdrMdcv hdr_mdcv_ = {};
354*09537850SAkhilesh Sanikop   bool hdr_mdcv_set_ = false;  // Set to true when set_hdr_mdcv() is called.
355*09537850SAkhilesh Sanikop   ObuMetadataItutT35 itut_t35_ = {};
356*09537850SAkhilesh Sanikop   DynamicBuffer<uint8_t> itut_t35_payload_;
357*09537850SAkhilesh Sanikop   bool itut_t35_set_ = false;  // Set to true when set_itut_t35() is called.
358*09537850SAkhilesh Sanikop 
359*09537850SAkhilesh Sanikop   // segmentation_map_ contains a rows4x4_ by columns4x4_ 2D array.
360*09537850SAkhilesh Sanikop   SegmentationMap segmentation_map_;
361*09537850SAkhilesh Sanikop 
362*09537850SAkhilesh Sanikop   // Only the |params| field of each GlobalMotion struct is used.
363*09537850SAkhilesh Sanikop   // global_motion_[0] (for kReferenceFrameIntra) is not used.
364*09537850SAkhilesh Sanikop   std::array<GlobalMotion, kNumReferenceFrameTypes> global_motion_ = {};
365*09537850SAkhilesh Sanikop   SymbolDecoderContext frame_context_;
366*09537850SAkhilesh Sanikop   std::array<int8_t, kNumReferenceFrameTypes> loop_filter_ref_deltas_;
367*09537850SAkhilesh Sanikop   std::array<int8_t, kLoopFilterMaxModeDeltas> loop_filter_mode_deltas_;
368*09537850SAkhilesh Sanikop   // Only the feature_enabled, feature_data, segment_id_pre_skip, and
369*09537850SAkhilesh Sanikop   // last_active_segment_id fields of the Segmentation struct are used.
370*09537850SAkhilesh Sanikop   //
371*09537850SAkhilesh Sanikop   // Note: The spec only requires that we save feature_enabled and
372*09537850SAkhilesh Sanikop   // feature_data. Since segment_id_pre_skip and last_active_segment_id depend
373*09537850SAkhilesh Sanikop   // on feature_enabled only, we also save their values as an optimization.
374*09537850SAkhilesh Sanikop   Segmentation segmentation_ = {};
375*09537850SAkhilesh Sanikop   FilmGrainParams film_grain_params_ = {};
376*09537850SAkhilesh Sanikop   ReferenceInfo reference_info_;
377*09537850SAkhilesh Sanikop };
378*09537850SAkhilesh Sanikop 
379*09537850SAkhilesh Sanikop // RefCountedBufferPtr contains a reference to a RefCountedBuffer.
380*09537850SAkhilesh Sanikop //
381*09537850SAkhilesh Sanikop // Note: For simplicity, RefCountedBufferPtr is implemented as a
382*09537850SAkhilesh Sanikop // std::shared_ptr<RefCountedBuffer>. This requires a heap allocation of the
383*09537850SAkhilesh Sanikop // control block for std::shared_ptr. To avoid that heap allocation, we can
384*09537850SAkhilesh Sanikop // add a |ref_count_| field to RefCountedBuffer and implement a custom
385*09537850SAkhilesh Sanikop // RefCountedBufferPtr class.
386*09537850SAkhilesh Sanikop using RefCountedBufferPtr = std::shared_ptr<RefCountedBuffer>;
387*09537850SAkhilesh Sanikop 
388*09537850SAkhilesh Sanikop // BufferPool maintains a pool of RefCountedBuffers.
389*09537850SAkhilesh Sanikop class BufferPool {
390*09537850SAkhilesh Sanikop  public:
391*09537850SAkhilesh Sanikop   BufferPool(FrameBufferSizeChangedCallback on_frame_buffer_size_changed,
392*09537850SAkhilesh Sanikop              GetFrameBufferCallback get_frame_buffer,
393*09537850SAkhilesh Sanikop              ReleaseFrameBufferCallback release_frame_buffer,
394*09537850SAkhilesh Sanikop              void* callback_private_data);
395*09537850SAkhilesh Sanikop 
396*09537850SAkhilesh Sanikop   // Not copyable or movable.
397*09537850SAkhilesh Sanikop   BufferPool(const BufferPool&) = delete;
398*09537850SAkhilesh Sanikop   BufferPool& operator=(const BufferPool&) = delete;
399*09537850SAkhilesh Sanikop 
400*09537850SAkhilesh Sanikop   ~BufferPool();
401*09537850SAkhilesh Sanikop 
402*09537850SAkhilesh Sanikop   LIBGAV1_MUST_USE_RESULT bool OnFrameBufferSizeChanged(
403*09537850SAkhilesh Sanikop       int bitdepth, Libgav1ImageFormat image_format, int width, int height,
404*09537850SAkhilesh Sanikop       int left_border, int right_border, int top_border, int bottom_border);
405*09537850SAkhilesh Sanikop 
406*09537850SAkhilesh Sanikop   // Finds a free buffer in the buffer pool and returns a reference to the free
407*09537850SAkhilesh Sanikop   // buffer. If there is no free buffer, returns a null pointer. This function
408*09537850SAkhilesh Sanikop   // is thread safe.
409*09537850SAkhilesh Sanikop   RefCountedBufferPtr GetFreeBuffer();
410*09537850SAkhilesh Sanikop 
411*09537850SAkhilesh Sanikop   // Aborts all the buffers that are in use.
412*09537850SAkhilesh Sanikop   void Abort();
413*09537850SAkhilesh Sanikop 
414*09537850SAkhilesh Sanikop  private:
415*09537850SAkhilesh Sanikop   friend class RefCountedBuffer;
416*09537850SAkhilesh Sanikop 
417*09537850SAkhilesh Sanikop   // Returns an unused buffer to the buffer pool. Called by RefCountedBuffer
418*09537850SAkhilesh Sanikop   // only. This function is thread safe.
419*09537850SAkhilesh Sanikop   void ReturnUnusedBuffer(RefCountedBuffer* buffer);
420*09537850SAkhilesh Sanikop 
421*09537850SAkhilesh Sanikop   // Used to make the following functions thread safe: GetFreeBuffer(),
422*09537850SAkhilesh Sanikop   // ReturnUnusedBuffer(), RefCountedBuffer::Realloc().
423*09537850SAkhilesh Sanikop   std::mutex mutex_;
424*09537850SAkhilesh Sanikop 
425*09537850SAkhilesh Sanikop   // Storing a RefCountedBuffer object in a Vector is complicated because of the
426*09537850SAkhilesh Sanikop   // copy/move semantics. So the simplest way around that is to store a list of
427*09537850SAkhilesh Sanikop   // pointers in the vector.
428*09537850SAkhilesh Sanikop   Vector<RefCountedBuffer*> buffers_ LIBGAV1_GUARDED_BY(mutex_);
429*09537850SAkhilesh Sanikop   InternalFrameBufferList internal_frame_buffers_;
430*09537850SAkhilesh Sanikop 
431*09537850SAkhilesh Sanikop   // Frame buffer callbacks.
432*09537850SAkhilesh Sanikop   FrameBufferSizeChangedCallback on_frame_buffer_size_changed_;
433*09537850SAkhilesh Sanikop   GetFrameBufferCallback get_frame_buffer_;
434*09537850SAkhilesh Sanikop   ReleaseFrameBufferCallback release_frame_buffer_;
435*09537850SAkhilesh Sanikop   // Private data associated with the frame buffer callbacks.
436*09537850SAkhilesh Sanikop   void* callback_private_data_;
437*09537850SAkhilesh Sanikop };
438*09537850SAkhilesh Sanikop 
439*09537850SAkhilesh Sanikop }  // namespace libgav1
440*09537850SAkhilesh Sanikop 
441*09537850SAkhilesh Sanikop #endif  // LIBGAV1_SRC_BUFFER_POOL_H_
442