blob: c0ac76c53b9fc7e7cf72cb531f55e0c8417fc232 [file] [log] [blame]
/*
* Copyright 2019 The libgav1 Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIBGAV1_SRC_UTILS_TYPES_H_
#define LIBGAV1_SRC_UTILS_TYPES_H_
#include <array>
#include <cstdint>
#include <memory>
#include "src/utils/array_2d.h"
#include "src/utils/constants.h"
#include "src/utils/memory.h"
namespace libgav1 {
struct MotionVector : public Allocable {
static constexpr int kRow = 0;
static constexpr int kColumn = 1;
MotionVector() = default;
MotionVector(const MotionVector& mv) = default;
MotionVector& operator=(const MotionVector& rhs) {
mv32 = rhs.mv32;
return *this;
}
bool operator==(const MotionVector& rhs) const { return mv32 == rhs.mv32; }
union {
// Motion vectors will always fit in int16_t and using int16_t here instead
// of int saves significant memory since some of the frame sized structures
// store motion vectors.
int16_t mv[2];
// A uint32_t view into the |mv| array. Useful for cases where both the
// motion vectors have to be copied or compared with a single 32 bit
// instruction.
uint32_t mv32;
};
};
union CompoundMotionVector {
CompoundMotionVector() = default;
CompoundMotionVector(const CompoundMotionVector& mv) = default;
CompoundMotionVector& operator=(const CompoundMotionVector& rhs) {
mv64 = rhs.mv64;
return *this;
}
bool operator==(const CompoundMotionVector& rhs) const {
return mv64 == rhs.mv64;
}
MotionVector mv[2];
// A uint64_t view into the |mv| array. Useful for cases where all the motion
// vectors have to be copied or compared with a single 64 bit instruction.
uint64_t mv64;
};
// Stores the motion information used for motion field estimation.
struct TemporalMotionField : public Allocable {
Array2D<MotionVector> mv;
Array2D<int8_t> reference_offset;
};
// MvContexts contains the contexts used to decode portions of an inter block
// mode info to set the y_mode field in BlockParameters.
//
// The contexts in the struct correspond to the ZeroMvContext, RefMvContext,
// and NewMvContext variables in the spec.
struct MvContexts {
int zero_mv;
int reference_mv;
int new_mv;
};
struct PaletteModeInfo {
uint8_t size[kNumPlaneTypes];
uint16_t color[kMaxPlanes][kMaxPaletteSize];
};
// Stores the parameters used by the prediction process. The members of the
// struct are filled in when parsing the bitstream and used when the prediction
// is computed. The information in this struct is associated with a single
// block.
// While both BlockParameters and PredictionParameters store information
// pertaining to a Block, the only difference is that BlockParameters outlives
// the block itself (for example, some of the variables in BlockParameters are
// used to compute the context for reading elements in the subsequent blocks).
struct PredictionParameters : public Allocable {
// Restore the index in the unsorted mv stack from the least 3 bits of sorted
// |weight_index_stack|.
const MotionVector& reference_mv(int stack_index) const {
return ref_mv_stack[7 - (weight_index_stack[stack_index] & 7)];
}
const MotionVector& reference_mv(int stack_index, int mv_index) const {
return compound_ref_mv_stack[7 - (weight_index_stack[stack_index] & 7)]
.mv[mv_index];
}
void IncreaseWeight(ptrdiff_t index, int weight) {
weight_index_stack[index] += weight << 3;
}
void SetWeightIndexStackEntry(int index, int weight) {
weight_index_stack[index] = (weight << 3) + 7 - index;
}
bool use_filter_intra;
FilterIntraPredictor filter_intra_mode;
int angle_delta[kNumPlaneTypes];
int8_t cfl_alpha_u;
int8_t cfl_alpha_v;
int max_luma_width;
int max_luma_height;
Array2D<uint8_t> color_index_map[kNumPlaneTypes];
bool use_intra_block_copy;
InterIntraMode inter_intra_mode;
bool is_wedge_inter_intra;
int wedge_index;
int wedge_sign;
bool mask_is_inverse;
MotionMode motion_mode;
CompoundPredictionType compound_prediction_type;
union {
// |ref_mv_stack| and |compound_ref_mv_stack| are not sorted after
// construction. reference_mv() must be called to get the correct element.
MotionVector ref_mv_stack[kMaxRefMvStackSize];
CompoundMotionVector compound_ref_mv_stack[kMaxRefMvStackSize];
};
// The least 3 bits of |weight_index_stack| store the index information, and
// the other bits store the weight. The index information is actually 7 -
// index to make the descending order sort stable (preserves the original
// order for elements with the same weight). Sorting an int16_t array is much
// faster than sorting a struct array with weight and index stored separately.
int16_t weight_index_stack[kMaxRefMvStackSize];
// In the spec, the weights of all the nearest mvs are incremented by a bonus
// weight which is larger than any natural weight, and later the weights of
// the mvs are compared with this bonus weight to determine their contexts. We
// replace this procedure by introducing |nearest_mv_count|, which records the
// count of the nearest mvs. Since all the nearest mvs are in the beginning of
// the mv stack, the index of a mv in the mv stack can be compared with
// |nearest_mv_count| to get that mv's context.
int nearest_mv_count;
int ref_mv_count;
int ref_mv_index;
MotionVector global_mv[2];
int num_warp_samples;
int warp_estimate_candidates[kMaxLeastSquaresSamples][4];
};
// A lot of BlockParameters objects are created, so the smallest type is used
// for each field. The ranges of some fields are documented to justify why
// their types are large enough.
struct BlockParameters : public Allocable {
BlockSize size;
bool skip;
// True means that this block will use some default settings (that
// correspond to compound prediction) and so most of the mode info is
// skipped. False means that the mode info is not skipped.
bool skip_mode;
bool is_inter;
bool is_explicit_compound_type; // comp_group_idx in the spec.
bool is_compound_type_average; // compound_idx in the spec.
bool is_global_mv_block;
bool use_predicted_segment_id; // only valid with temporal update enabled.
int8_t segment_id; // segment_id is in the range [0, 7].
PredictionMode y_mode;
PredictionMode uv_mode;
TransformSize transform_size;
TransformSize uv_transform_size;
InterpolationFilter interpolation_filter[2];
ReferenceFrameType reference_frame[2];
// The index of this array is as follows:
// 0 - Y plane vertical filtering.
// 1 - Y plane horizontal filtering.
// 2 - U plane (both directions).
// 3 - V plane (both directions).
uint8_t deblock_filter_level[kFrameLfCount];
CompoundMotionVector mv;
PaletteModeInfo palette_mode_info;
// When |Tile::split_parse_and_decode_| is true, each block gets its own
// instance of |prediction_parameters|. When it is false, all the blocks point
// to |Tile::prediction_parameters_|. This field is valid only as long as the
// block is *being* decoded. The lifetime and usage of this field can be
// better understood by following its flow in tile.cc.
std::unique_ptr<PredictionParameters> prediction_parameters;
};
// A five dimensional array used to store the wedge masks. The dimensions are:
// - block_size_index (returned by GetWedgeBlockSizeIndex() in prediction.cc).
// - flip_sign (0 or 1).
// - wedge_index (0 to 15).
// - each of those three dimensions is a 2d array of block_width by
// block_height.
using WedgeMaskArray =
std::array<std::array<std::array<Array2D<uint8_t>, 16>, 2>, 9>;
enum GlobalMotionTransformationType : uint8_t {
kGlobalMotionTransformationTypeIdentity,
kGlobalMotionTransformationTypeTranslation,
kGlobalMotionTransformationTypeRotZoom,
kGlobalMotionTransformationTypeAffine,
kNumGlobalMotionTransformationTypes
};
// Global motion and warped motion parameters. See the paper for more info:
// S. Parker, Y. Chen, D. Barker, P. de Rivaz, D. Mukherjee, "Global and locally
// adaptive warped motion compensation in video compression", Proc. IEEE
// International Conference on Image Processing (ICIP), pp. 275-279, Sep. 2017.
struct GlobalMotion {
GlobalMotionTransformationType type;
int32_t params[6];
// Represent two shearing operations. Computed from |params| by SetupShear().
//
// The least significant six (= kWarpParamRoundingBits) bits are all zeros.
// (This means alpha, beta, gamma, and delta could be represented by a 10-bit
// signed integer.) The minimum value is INT16_MIN (= -32768) and the maximum
// value is 32704 = 0x7fc0, the largest int16_t value whose least significant
// six bits are all zeros.
//
// Valid warp parameters (as validated by SetupShear()) have smaller ranges.
// Their absolute values are less than 2^14 (= 16384). (This follows from
// the warpValid check at the end of Section 7.11.3.6.)
//
// NOTE: Section 7.11.3.6 of the spec allows a maximum value of 32768, which
// is outside the range of int16_t. When cast to int16_t, 32768 becomes
// -32768. This potential int16_t overflow does not matter because either
// 32768 or -32768 causes SetupShear() to return false,
int16_t alpha;
int16_t beta;
int16_t gamma;
int16_t delta;
};
// Loop filter parameters:
//
// If level[0] and level[1] are both equal to 0, the loop filter process is
// not invoked.
//
// |sharpness| and |delta_enabled| are only used by the loop filter process.
//
// The |ref_deltas| and |mode_deltas| arrays are used not only by the loop
// filter process but also by the reference frame update and loading
// processes. The loop filter process uses |ref_deltas| and |mode_deltas| only
// when |delta_enabled| is true.
struct LoopFilter {
// Contains loop filter strength values in the range of [0, 63].
std::array<int8_t, kFrameLfCount> level;
// Indicates the sharpness level in the range of [0, 7].
int8_t sharpness;
// Whether the filter level depends on the mode and reference frame used to
// predict a block.
bool delta_enabled;
// Whether additional syntax elements were read that specify which mode and
// reference frame deltas are to be updated. loop_filter_delta_update field in
// Section 5.9.11 of the spec.
bool delta_update;
// Contains the adjustment needed for the filter level based on the chosen
// reference frame, in the range of [-64, 63].
std::array<int8_t, kNumReferenceFrameTypes> ref_deltas;
// Contains the adjustment needed for the filter level based on the chosen
// mode, in the range of [-64, 63].
std::array<int8_t, kLoopFilterMaxModeDeltas> mode_deltas;
};
struct Delta {
bool present;
uint8_t scale;
bool multi;
};
struct Cdef {
uint8_t damping; // damping value from the spec + (bitdepth - 8).
uint8_t bits;
// All the strength values are the values from the spec and left shifted by
// (bitdepth - 8).
uint8_t y_primary_strength[kMaxCdefStrengths];
uint8_t y_secondary_strength[kMaxCdefStrengths];
uint8_t uv_primary_strength[kMaxCdefStrengths];
uint8_t uv_secondary_strength[kMaxCdefStrengths];
};
struct TileInfo {
bool uniform_spacing;
int sb_rows;
int sb_columns;
int tile_count;
int tile_columns_log2;
int tile_columns;
int tile_column_start[kMaxTileColumns + 1];
// This field is not used by libgav1, but is populated for use by some
// hardware decoders. So it must not be removed.
int tile_column_width_in_superblocks[kMaxTileColumns + 1];
int tile_rows_log2;
int tile_rows;
int tile_row_start[kMaxTileRows + 1];
// This field is not used by libgav1, but is populated for use by some
// hardware decoders. So it must not be removed.
int tile_row_height_in_superblocks[kMaxTileRows + 1];
int16_t context_update_id;
uint8_t tile_size_bytes;
};
struct LoopRestoration {
LoopRestorationType type[kMaxPlanes];
int unit_size[kMaxPlanes];
};
// Stores the quantization parameters of Section 5.9.12.
struct QuantizerParameters {
// base_index is in the range [0, 255].
uint8_t base_index;
int8_t delta_dc[kMaxPlanes];
// delta_ac[kPlaneY] is always 0.
int8_t delta_ac[kMaxPlanes];
bool use_matrix;
// The |matrix_level| array is used only when |use_matrix| is true.
// matrix_level[plane] specifies the level in the quantizer matrix that
// should be used for decoding |plane|. The quantizer matrix has 15 levels,
// from 0 to 14. The range of matrix_level[plane] is [0, 15]. If
// matrix_level[plane] is 15, the quantizer matrix is not used.
int8_t matrix_level[kMaxPlanes];
};
// The corresponding segment feature constants in the AV1 spec are named
// SEG_LVL_xxx.
enum SegmentFeature : uint8_t {
kSegmentFeatureQuantizer,
kSegmentFeatureLoopFilterYVertical,
kSegmentFeatureLoopFilterYHorizontal,
kSegmentFeatureLoopFilterU,
kSegmentFeatureLoopFilterV,
kSegmentFeatureReferenceFrame,
kSegmentFeatureSkip,
kSegmentFeatureGlobalMv,
kSegmentFeatureMax
};
struct Segmentation {
// 5.11.14.
// Returns true if the feature is enabled in the segment.
bool FeatureActive(int segment_id, SegmentFeature feature) const {
return enabled && segment_id < kMaxSegments &&
feature_enabled[segment_id][feature];
}
// Returns true if the feature is signed.
static bool FeatureSigned(SegmentFeature feature) {
// Only the first five segment features are signed, so this comparison
// suffices.
return feature <= kSegmentFeatureLoopFilterV;
}
bool enabled;
bool update_map;
bool update_data;
bool temporal_update;
// True if the segment id will be read before the skip syntax element. False
// if the skip syntax element will be read first.
bool segment_id_pre_skip;
// The highest numbered segment id that has some enabled feature. Used as
// the upper bound for decoding segment ids.
int8_t last_active_segment_id;
bool feature_enabled[kMaxSegments][kSegmentFeatureMax];
int16_t feature_data[kMaxSegments][kSegmentFeatureMax];
bool lossless[kMaxSegments];
// Cached values of get_qindex(1, segmentId), to be consumed by
// Tile::ReadTransformType(). The values are in the range [0, 255].
uint8_t qindex[kMaxSegments];
};
// Section 6.8.20.
// Note: In spec, film grain section uses YCbCr to denote variable names,
// such as num_cb_points, num_cr_points. To keep it consistent with other
// parts of code, we use YUV, i.e., num_u_points, num_v_points, etc.
struct FilmGrainParams {
bool apply_grain;
bool update_grain;
bool chroma_scaling_from_luma;
bool overlap_flag;
bool clip_to_restricted_range;
uint8_t num_y_points; // [0, 14].
uint8_t num_u_points; // [0, 10].
uint8_t num_v_points; // [0, 10].
// Must be [0, 255]. 10/12 bit /= 4 or 16. Must be in increasing order.
uint8_t point_y_value[14];
uint8_t point_y_scaling[14];
uint8_t point_u_value[10];
uint8_t point_u_scaling[10];
uint8_t point_v_value[10];
uint8_t point_v_scaling[10];
uint8_t chroma_scaling; // [8, 11].
uint8_t auto_regression_coeff_lag; // [0, 3].
int8_t auto_regression_coeff_y[24]; // [-128, 127]
int8_t auto_regression_coeff_u[25]; // [-128, 127]
int8_t auto_regression_coeff_v[25]; // [-128, 127]
// Shift value: auto regression coeffs range
// 6: [-2, 2)
// 7: [-1, 1)
// 8: [-0.5, 0.5)
// 9: [-0.25, 0.25)
uint8_t auto_regression_shift;
uint16_t grain_seed;
int reference_index;
int grain_scale_shift;
// These multipliers are encoded as nonnegative values by adding 128 first.
// The 128 is subtracted during parsing.
int8_t u_multiplier; // [-128, 127]
int8_t u_luma_multiplier; // [-128, 127]
// These offsets are encoded as nonnegative values by adding 256 first. The
// 256 is subtracted during parsing.
int16_t u_offset; // [-256, 255]
int8_t v_multiplier; // [-128, 127]
int8_t v_luma_multiplier; // [-128, 127]
int16_t v_offset; // [-256, 255]
};
struct ObuFrameHeader {
uint16_t display_frame_id;
uint16_t current_frame_id;
int64_t frame_offset;
uint16_t expected_frame_id[kNumInterReferenceFrameTypes];
int32_t width;
int32_t height;
int32_t columns4x4;
int32_t rows4x4;
// The render size (render_width and render_height) is a hint to the
// application about the desired display size. It has no effect on the
// decoding process.
int32_t render_width;
int32_t render_height;
int32_t upscaled_width;
LoopRestoration loop_restoration;
uint32_t buffer_removal_time[kMaxOperatingPoints];
uint32_t frame_presentation_time;
// Note: global_motion[0] (for kReferenceFrameIntra) is not used.
std::array<GlobalMotion, kNumReferenceFrameTypes> global_motion;
TileInfo tile_info;
QuantizerParameters quantizer;
Segmentation segmentation;
bool show_existing_frame;
// frame_to_show is in the range [0, 7]. Only used if show_existing_frame is
// true.
int8_t frame_to_show;
FrameType frame_type;
bool show_frame;
bool showable_frame;
bool error_resilient_mode;
bool enable_cdf_update;
bool frame_size_override_flag;
// The order_hint syntax element in the uncompressed header. If
// show_existing_frame is false, the OrderHint variable in the spec is equal
// to this field, and so this field can be used in place of OrderHint when
// show_existing_frame is known to be false, such as during tile decoding.
uint8_t order_hint;
int8_t primary_reference_frame;
bool render_and_frame_size_different;
bool use_superres;
uint8_t superres_scale_denominator;
bool allow_screen_content_tools;
bool allow_intrabc;
bool frame_refs_short_signaling;
// A bitmask that specifies which reference frame slots will be updated with
// the current frame after it is decoded.
uint8_t refresh_frame_flags;
static_assert(sizeof(ObuFrameHeader::refresh_frame_flags) * 8 ==
kNumReferenceFrameTypes,
"");
bool found_reference;
int8_t force_integer_mv;
bool allow_high_precision_mv;
InterpolationFilter interpolation_filter;
bool is_motion_mode_switchable;
bool use_ref_frame_mvs;
bool enable_frame_end_update_cdf;
// True if all segments are losslessly encoded at the coded resolution.
bool coded_lossless;
// True if all segments are losslessly encoded at the upscaled resolution.
bool upscaled_lossless;
TxMode tx_mode;
// True means that the mode info for inter blocks contains the syntax
// element comp_mode that indicates whether to use single or compound
// prediction. False means that all inter blocks will use single prediction.
bool reference_mode_select;
// The frames to use for compound prediction when skip_mode is true.
ReferenceFrameType skip_mode_frame[2];
bool skip_mode_present;
bool reduced_tx_set;
bool allow_warped_motion;
Delta delta_q;
Delta delta_lf;
// A valid value of reference_frame_index[i] is in the range [0, 7]. -1
// indicates an invalid value.
int8_t reference_frame_index[kNumInterReferenceFrameTypes];
// The ref_order_hint[ i ] syntax element in the uncompressed header.
// Specifies the expected output order hint for each reference frame.
uint8_t reference_order_hint[kNumReferenceFrameTypes];
LoopFilter loop_filter;
Cdef cdef;
FilmGrainParams film_grain_params;
};
} // namespace libgav1
#endif // LIBGAV1_SRC_UTILS_TYPES_H_