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