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