blob: c50888b9bb0993f94fe41caeb97ca45173c78c10 [file] [log] [blame]
#ifndef LIBGAV1_SRC_BUFFER_POOL_H_
#define LIBGAV1_SRC_BUFFER_POOL_H_
#include <array>
#include <cstdint>
#include <memory>
#include "src/decoder_buffer.h"
#include "src/decoder_settings.h"
#include "src/dsp/common.h"
#include "src/frame_buffer.h"
#include "src/internal_frame_buffer_list.h"
#include "src/obu_parser.h"
#include "src/symbol_decoder_context.h"
#include "src/utils/array_2d.h"
#include "src/utils/constants.h"
#include "src/utils/segmentation.h"
#include "src/utils/segmentation_map.h"
#include "src/utils/types.h"
#include "src/yuv_buffer.h"
namespace libgav1 {
class BufferPool;
// A reference-counted frame buffer. Clients should access it via
// RefCountedBufferPtr, which manages reference counting transparently.
class RefCountedBuffer {
public:
// Not copyable or movable.
RefCountedBuffer(const RefCountedBuffer&) = delete;
RefCountedBuffer& operator=(const RefCountedBuffer&) = delete;
// Allocates the YUV buffer. Returns true on success. Returns false on
// failure.
//
// * |width| and |height| are the image dimensions in pixels.
// * |subsampling_x| and |subsampling_y| (either 0 or 1) specify the
// subsampling of the width and height of the chroma planes, respectively.
// * |border| is the size of the borders (on all four sides) in pixels.
// * |byte_alignment| specifies the additional alignment requirement of the
// data buffers of the Y, U, and V planes. If |byte_alignment| is 0, there
// is no additional alignment requirement. Otherwise, |byte_alignment|
// must be a power of 2 and greater than or equal to 16.
// NOTE: The strides are a multiple of 16. Therefore only the first row in
// each plane is aligned to |byte_alignment|. Subsequent rows are only
// 16-byte aligned.
bool Realloc(int bitdepth, bool is_monochrome, int width, int height,
int subsampling_x, int subsampling_y, int border,
int byte_alignment);
YuvBuffer* buffer() { return &yuv_buffer_; }
// Returns the buffer private data set by the get frame buffer callback when
// it allocated the YUV buffer.
void* buffer_private_data() const { return raw_frame_buffer_.private_data; }
// NOTE: In the current frame, this is the frame_type syntax element in the
// frame header. In a reference frame, this implements the RefFrameType array
// in the spec.
FrameType frame_type() const { return frame_type_; }
void set_frame_type(enum FrameType frame_type) { frame_type_ = frame_type; }
// The sample position for subsampled streams. This is the
// chroma_sample_position syntax element in the sequence header.
//
// NOTE: The decoder does not use chroma_sample_position, but it needs to be
// passed on to the client in DecoderBuffer.
ChromaSamplePosition chroma_sample_position() const {
return chroma_sample_position_;
}
void set_chroma_sample_position(
enum ChromaSamplePosition chroma_sample_position) {
chroma_sample_position_ = chroma_sample_position;
}
// Whether the frame can be used as show existing frame in the future.
bool showable_frame() const { return showable_frame_; }
void set_showable_frame(bool value) { showable_frame_ = value; }
uint8_t order_hint(ReferenceFrameType reference_frame) const {
return order_hint_[reference_frame];
}
void set_order_hint(ReferenceFrameType reference_frame, uint8_t order_hint) {
order_hint_[reference_frame] = order_hint;
}
void ClearOrderHints() { order_hint_.fill(0); }
// Sets upscaled_width_, frame_width_, frame_height_, render_width_,
// render_height_, rows4x4_ and columns4x4_ from the corresponding fields
// in frame_header. Allocates motion_field_reference_frame_,
// motion_field_mv_, and segmentation_map_. Returns true on success, false
// on failure.
bool SetFrameDimensions(const ObuFrameHeader& frame_header);
int32_t upscaled_width() const { return upscaled_width_; }
int32_t frame_width() const { return frame_width_; }
int32_t frame_height() const { return frame_height_; }
// RenderWidth() and RenderHeight() return the render size, which is a hint
// to the application about the desired display size.
int32_t render_width() const { return render_width_; }
int32_t render_height() const { return render_height_; }
int32_t rows4x4() const { return rows4x4_; }
int32_t columns4x4() const { return columns4x4_; }
// Entry at |row|, |column| corresponds to
// MfRefFrames[row * 2 + 1][column * 2 + 1] in the spec.
ReferenceFrameType* motion_field_reference_frame(int row, int column) {
return &motion_field_reference_frame_[row][column];
}
// Entry at |row|, |column| corresponds to
// MfMvs[row * 2 + 1][column * 2 + 1] in the spec.
MotionVector* motion_field_mv(int row, int column) {
return &motion_field_mv_[row][column];
}
SegmentationMap* segmentation_map() { return &segmentation_map_; }
const SegmentationMap* segmentation_map() const { return &segmentation_map_; }
// Only the |params| field of each GlobalMotion struct should be used.
const std::array<GlobalMotion, kNumReferenceFrameTypes>& GlobalMotions()
const {
return global_motion_;
}
// Saves the GlobalMotion array. Only the |params| field of each GlobalMotion
// struct is saved.
void SetGlobalMotions(
const std::array<GlobalMotion, kNumReferenceFrameTypes>& global_motions);
// Returns the saved CDF tables.
const SymbolDecoderContext& FrameContext() const { return frame_context_; }
// Saves the CDF tables. The intra_frame_y_mode_cdf table is reset to the
// default. The last entry in each table, representing the symbol count for
// that context, is set to 0.
void SetFrameContext(const SymbolDecoderContext& context);
const std::array<int8_t, kNumReferenceFrameTypes>& loop_filter_ref_deltas()
const {
return loop_filter_ref_deltas_;
}
const std::array<int8_t, kLoopFilterMaxModeDeltas>& loop_filter_mode_deltas()
const {
return loop_filter_mode_deltas_;
}
// Saves the ref_deltas and mode_deltas arrays in loop_filter.
void SetLoopFilterDeltas(const LoopFilter& loop_filter) {
loop_filter_ref_deltas_ = loop_filter.ref_deltas;
loop_filter_mode_deltas_ = loop_filter.mode_deltas;
}
// Copies the saved values of the following fields to the Segmentation
// struct: feature_enabled, feature_data, segment_id_pre_skip, and
// last_active_segment_id. The other fields are left unchanged.
void GetSegmentationParameters(Segmentation* segmentation) const;
// Saves the feature_enabled, feature_data, segment_id_pre_skip, and
// last_active_segment_id fields of the Segmentation struct.
void SetSegmentationParameters(const Segmentation& segmentation);
const FilmGrainParams& film_grain_params() const {
return film_grain_params_;
}
void set_film_grain_params(const FilmGrainParams& params) {
film_grain_params_ = params;
}
private:
friend class BufferPool;
// Methods for BufferPool:
RefCountedBuffer();
~RefCountedBuffer();
void SetBufferPool(BufferPool* pool);
static void ReturnToBufferPool(RefCountedBuffer* ptr);
BufferPool* pool_ = nullptr;
FrameBuffer raw_frame_buffer_;
YuvBuffer yuv_buffer_;
bool in_use_ = false; // Only used by BufferPool.
enum FrameType frame_type_ = kFrameKey;
enum ChromaSamplePosition chroma_sample_position_ =
kChromaSamplePositionUnknown;
bool showable_frame_ = false;
// Note: order_hint_[0] (for kReferenceFrameIntra) is not used.
std::array<uint8_t, kNumReferenceFrameTypes> order_hint_ = {};
int32_t upscaled_width_ = 0;
int32_t frame_width_ = 0;
int32_t frame_height_ = 0;
int32_t render_width_ = 0;
int32_t render_height_ = 0;
int32_t columns4x4_ = 0;
int32_t rows4x4_ = 0;
// Array of size (rows4x4 / 2) x (columns4x4 / 2). Entry at i, j corresponds
// to MfRefFrames[i * 2 + 1][j * 2 + 1] in the spec.
Array2D<ReferenceFrameType> motion_field_reference_frame_;
// Array of size (rows4x4 / 2) x (columns4x4 / 2). Entry at i, j corresponds
// to MfMvs[i * 2 + 1][j * 2 + 1] in the spec.
Array2D<MotionVector> motion_field_mv_;
// segmentation_map_ contains a rows4x4_ by columns4x4_ 2D array.
SegmentationMap segmentation_map_;
// Only the |params| field of each GlobalMotion struct is used.
// global_motion_[0] (for kReferenceFrameIntra) is not used.
std::array<GlobalMotion, kNumReferenceFrameTypes> global_motion_ = {};
SymbolDecoderContext frame_context_;
std::array<int8_t, kNumReferenceFrameTypes> loop_filter_ref_deltas_;
std::array<int8_t, kLoopFilterMaxModeDeltas> loop_filter_mode_deltas_;
// Only the feature_enabled, feature_data, segment_id_pre_skip, and
// last_active_segment_id fields of the Segmentation struct are used.
//
// Note: The spec only requires that we save feature_enabled and
// feature_data. Since segment_id_pre_skip and last_active_segment_id depend
// on feature_enabled only, we also save their values as an optimization.
Segmentation segmentation_ = {};
FilmGrainParams film_grain_params_ = {};
};
// RefCountedBufferPtr contains a reference to a RefCountedBuffer.
//
// Note: For simplicity, RefCountedBufferPtr is implemented as a
// std::shared_ptr<RefCountedBuffer>. This requires a heap allocation of the
// control block for std::shared_ptr. To avoid that heap allocation, we can
// add a |ref_count_| field to RefCountedBuffer and implement a custom
// RefCountedBufferPtr class.
using RefCountedBufferPtr = std::shared_ptr<RefCountedBuffer>;
// BufferPool maintains a pool of RefCountedBuffers.
class BufferPool {
public:
explicit BufferPool(const DecoderSettings& settings);
// Not copyable or movable.
BufferPool(const BufferPool&) = delete;
BufferPool& operator=(const BufferPool&) = delete;
~BufferPool();
// Finds a free buffer in the buffer pool and returns a reference to the
// free buffer. If there is no free buffer, returns a null pointer.
RefCountedBufferPtr GetFreeBuffer();
private:
friend class RefCountedBuffer;
// Reference frames + 1 scratch frame (for either the current frame or the
// film grain frame).
static constexpr int kNumBuffers = kNumReferenceFrameTypes + 1;
// Returns an unused buffer to the buffer pool. Called by RefCountedBuffer
// only.
void ReturnUnusedBuffer(RefCountedBuffer* buffer);
RefCountedBuffer buffers_[kNumBuffers];
std::unique_ptr<InternalFrameBufferList> internal_frame_buffers_;
// Frame buffer callbacks.
GetFrameBufferCallback get_frame_buffer_;
ReleaseFrameBufferCallback release_frame_buffer_;
// Private data associated with the frame buffer callbacks.
void* callback_private_data_;
};
} // namespace libgav1
#endif // LIBGAV1_SRC_BUFFER_POOL_H_