blob: c4ea52627da80c6c0b0b2d7242142cf87e9f2a3b [file] [log] [blame]
#ifndef LIBGAV1_SRC_DECODER_IMPL_H_
#define LIBGAV1_SRC_DECODER_IMPL_H_
#include <array>
#include <cstddef>
#include <cstdint>
#include <memory>
#include "src/buffer_pool.h"
#include "src/decoder_buffer.h"
#include "src/decoder_settings.h"
#include "src/dsp/constants.h"
#include "src/loop_filter_mask.h"
#include "src/obu_parser.h"
#include "src/residual_buffer_pool.h"
#include "src/status_code.h"
#include "src/symbol_decoder_context.h"
#include "src/threading_strategy.h"
#include "src/tile.h"
#include "src/utils/array_2d.h"
#include "src/utils/block_parameters_holder.h"
#include "src/utils/constants.h"
#include "src/utils/memory.h"
#include "src/utils/queue.h"
#include "src/utils/segmentation_map.h"
#include "src/utils/types.h"
namespace libgav1 {
struct EncodedFrame : public Allocable {
// The default constructor is invoked by the Queue<EncodedFrame>::Init()
// method. Queue<> does not use the default-constructed elements, so it is
// safe for the default constructor to not initialize the members.
EncodedFrame() = default;
EncodedFrame(const uint8_t* data, size_t size, int64_t user_private_data)
: data(data), size(size), user_private_data(user_private_data) {}
const uint8_t* data;
size_t size;
int64_t user_private_data;
};
struct DecoderState {
ObuSequenceHeader sequence_header = {};
// If true, sequence_header is valid.
bool has_sequence_header = false;
// reference_valid and reference_frame_id are used only if
// sequence_header_.frame_id_numbers_present is true.
// The reference_valid array is indexed by a reference picture slot number.
// A value (boolean) in the array signifies whether the corresponding
// reference picture slot is valid for use as a reference picture.
std::array<bool, kNumReferenceFrameTypes> reference_valid = {};
std::array<uint16_t, kNumReferenceFrameTypes> reference_frame_id = {};
// A valid value of current_frame_id is an unsigned integer of at most 16
// bits. -1 indicates current_frame_id is not initialized.
int current_frame_id = -1;
// The RefOrderHint array variable in the spec.
std::array<uint8_t, kNumReferenceFrameTypes> reference_order_hint = {};
// The OrderHint variable in the spec. Its value comes from either the
// order_hint syntax element in the uncompressed header (if
// show_existing_frame is false) or RefOrderHint[ frame_to_show_map_idx ]
// (if show_existing_frame is true and frame_type is KEY_FRAME). See Section
// 5.9.2 and Section 7.4.
//
// NOTE: When show_existing_frame is false, it is often more convenient to
// just use the order_hint field of the frame header as OrderHint. So this
// field is mainly used to update the state_.reference_order_hint array in
// DecoderImpl::UpdateReferenceFrames().
uint8_t order_hint = 0;
// reference_frame_sign_bias[i] (a boolean) specifies the intended direction
// of the motion vector in time for each reference frame.
// * |false| indicates that the reference frame is a forwards reference (i.e.
// the reference frame is expected to be output before the current frame);
// * |true| indicates that the reference frame is a backwards reference.
// Note: reference_frame_sign_bias[0] (for kReferenceFrameIntra) is not used.
std::array<bool, kNumReferenceFrameTypes> reference_frame_sign_bias = {};
std::array<RefCountedBufferPtr, kNumReferenceFrameTypes> reference_frame;
RefCountedBufferPtr current_frame;
// wedge_master_mask has to be initialized to zero.
std::array<uint8_t, 6 * kWedgeMaskMasterSize* kWedgeMaskMasterSize>
wedge_master_mask = {};
// TODO(chengchen): It is possible to reduce the buffer size. Because wedge
// mask sizes are 8x8, 8x16, ..., 32x32. This buffer size can fit 32x32.
std::array<uint8_t, kWedgeMaskSize> wedge_masks = {};
Array2D<TemporalMotionVector> motion_field_mv;
};
class DecoderImpl : public Allocable {
public:
// The constructor saves a const reference to |*settings|. Therefore
// |*settings| must outlive the DecoderImpl object. On success, |*output|
// contains a pointer to the newly-created DecoderImpl object. On failure,
// |*output| is not modified.
static StatusCode Create(const DecoderSettings* settings,
std::unique_ptr<DecoderImpl>* output);
~DecoderImpl();
StatusCode EnqueueFrame(const uint8_t* data, size_t size,
int64_t user_private_data);
StatusCode DequeueFrame(const DecoderBuffer** out_ptr);
static constexpr int GetMaxBitdepth() {
#if LIBGAV1_MAX_BITDEPTH >= 10
return 10;
#else
return 8;
#endif
}
private:
explicit DecoderImpl(const DecoderSettings* settings);
StatusCode Init();
bool AllocateCurrentFrame(const ObuFrameHeader& frame_header);
void ReleaseOutputFrame();
// Populates buffer_ with values from |frame|. Adds a reference to |frame|
// in output_frame_.
StatusCode CopyFrameToOutputBuffer(const RefCountedBufferPtr& frame);
StatusCode DecodeTiles(const ObuParser* obu);
// Sets the current frame's segmentation map for two cases. The third case
// is handled in Tile::DecodeBlock().
void SetCurrentFrameSegmentationMap(const ObuFrameHeader& frame_header,
const SegmentationMap* prev_segment_ids);
// Section 7.20. Updates frames in the state_.reference_frame array with
// state_.current_frame, based on the refresh_frame_flags bitmask.
void UpdateReferenceFrames(int refresh_frame_flags);
Queue<EncodedFrame> encoded_frames_;
DecoderState state_;
ThreadingStrategy threading_strategy_;
SymbolDecoderContext symbol_decoder_context_;
// TODO(vigneshv): Only support one buffer for now. Eventually this has to be
// a vector or an array.
DecoderBuffer buffer_ = {};
// output_frame_ holds a reference to the output frame on behalf of buffer_.
RefCountedBufferPtr output_frame_;
BufferPool buffer_pool_;
std::unique_ptr<ResidualBufferPool> residual_buffer_pool_;
AlignedUniquePtr<uint8_t> threaded_window_buffer_;
size_t threaded_window_buffer_size_ = 0;
Array2D<TransformSize> inter_transform_sizes_;
LoopFilterMask loop_filter_mask_;
const DecoderSettings& settings_;
};
} // namespace libgav1
#endif // LIBGAV1_SRC_DECODER_IMPL_H_