1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 12:17:44 +00:00

LibVideo/VP9: Use an enum to select segment features

This throws out some ugly `#define`s we had that were taking the role
of an enum anyway. We now have some nice getters in the contexts that
take the place of the combo of `seg_feature_active()` and then doing a
lookup in `FrameContext::m_segmentation_features` directly.
This commit is contained in:
Zaggy1024 2023-04-16 23:29:48 -05:00 committed by Tim Flynn
parent 6e6cc1ddb2
commit 094b0d8a78
8 changed files with 46 additions and 29 deletions

View file

@ -143,7 +143,11 @@ public:
bool use_predicted_segment_id_tree { false }; bool use_predicted_segment_id_tree { false };
Array<u8, 3> predicted_segment_id_tree_probabilities; Array<u8, 3> predicted_segment_id_tree_probabilities;
bool should_use_absolute_segment_base_quantizer { false }; bool should_use_absolute_segment_base_quantizer { false };
Array<Array<SegmentFeature, SEG_LVL_MAX>, MAX_SEGMENTS> segmentation_features; SegmentationFeatures segmentation_features;
SegmentFeatureStatus get_segment_feature(u8 segment_id, SegmentFeature feature) const
{
return segmentation_features[segment_id][to_underlying(feature)];
}
u16 header_size_in_bytes { 0 }; u16 header_size_in_bytes { 0 };
@ -334,6 +338,11 @@ struct BlockContext {
SegmentationPredictionContextView above_segmentation_ids; SegmentationPredictionContextView above_segmentation_ids;
NonZeroTokensView left_non_zero_tokens; NonZeroTokensView left_non_zero_tokens;
SegmentationPredictionContextView left_segmentation_ids; SegmentationPredictionContextView left_segmentation_ids;
SegmentFeatureStatus get_segment_feature(SegmentFeature feature) const
{
return frame_context.get_segment_feature(segment_id, feature);
}
}; };
struct BlockMotionVectorCandidateSet { struct BlockMotionVectorCandidateSet {

View file

@ -243,11 +243,14 @@ struct PersistentBlockContext {
u8 segment_id { 0 }; u8 segment_id { 0 };
}; };
struct SegmentFeature { struct SegmentFeatureStatus {
bool enabled { false }; bool enabled { false };
u8 value { 0 }; u8 value { 0 };
}; };
using SegmentFeatures = Array<SegmentFeatureStatus, to_underlying(SegmentFeature::Sentinel)>;
using SegmentationFeatures = Array<SegmentFeatures, MAX_SEGMENTS>;
struct ColorConfig { struct ColorConfig {
u8 bit_depth { 8 }; u8 bit_depth { 8 };
ColorSpace color_space { ColorSpace::Bt601 }; ColorSpace color_space { ColorSpace::Bt601 };

View file

@ -1173,9 +1173,10 @@ u8 Decoder::get_base_quantizer_index(BlockContext const& block_context)
{ {
// The function get_qindex( ) returns the quantizer index for the current block and is specified by the following: // The function get_qindex( ) returns the quantizer index for the current block and is specified by the following:
// If seg_feature_active( SEG_LVL_ALT_Q ) is equal to 1 the following ordered steps apply: // If seg_feature_active( SEG_LVL_ALT_Q ) is equal to 1 the following ordered steps apply:
if (Parser::seg_feature_active(block_context, SEG_LVL_ALT_Q)) { auto alternative_quantizer_feature = block_context.get_segment_feature(SegmentFeature::UseAlternativeQuantizerBase);
if (alternative_quantizer_feature.enabled) {
// 1. Set the variable data equal to FeatureData[ segment_id ][ SEG_LVL_ALT_Q ]. // 1. Set the variable data equal to FeatureData[ segment_id ][ SEG_LVL_ALT_Q ].
auto data = block_context.frame_context.segmentation_features[block_context.segment_id][SEG_LVL_ALT_Q].value; auto data = alternative_quantizer_feature.value;
// 2. If segmentation_abs_or_delta_update is equal to 0, set data equal to base_q_idx + data // 2. If segmentation_abs_or_delta_update is equal to 0, set data equal to base_q_idx + data
if (!block_context.frame_context.should_use_absolute_segment_base_quantizer) { if (!block_context.frame_context.should_use_absolute_segment_base_quantizer) {

View file

@ -161,4 +161,17 @@ enum Token : u8 {
DctValCat6 = 10, DctValCat6 = 10,
}; };
enum class SegmentFeature : u8 {
// SEG_LVL_ALT_Q
UseAlternativeQuantizerBase,
// SEG_LVL_ALT_L
UseAlternativeLoopFilterBase,
// SEG_LVL_REF_FRAME
ReferenceFrameOverride,
// SEG_LVL_SKIP
SkipResidualsOverride,
// SEG_LVL_MAX
Sentinel,
};
} }

View file

@ -15,8 +15,8 @@ namespace Video::VP9 {
static constexpr InterpolationFilter literal_to_type[4] = { EightTapSmooth, EightTap, EightTapSharp, Bilinear }; static constexpr InterpolationFilter literal_to_type[4] = { EightTapSmooth, EightTap, EightTapSharp, Bilinear };
static constexpr TransformSize tx_mode_to_biggest_tx_size[TX_MODES] = { Transform_4x4, Transform_8x8, Transform_16x16, Transform_32x32, Transform_32x32 }; static constexpr TransformSize tx_mode_to_biggest_tx_size[TX_MODES] = { Transform_4x4, Transform_8x8, Transform_16x16, Transform_32x32, Transform_32x32 };
static constexpr u8 segmentation_feature_bits[SEG_LVL_MAX] = { 8, 6, 2, 0 }; static constexpr u8 segmentation_feature_bits[to_underlying(SegmentFeature::Sentinel)] = { 8, 6, 2, 0 };
static constexpr bool segmentation_feature_signed[SEG_LVL_MAX] = { true, true, false, false }; static constexpr bool segmentation_feature_signed[to_underlying(SegmentFeature::Sentinel)] = { true, true, false, false };
static constexpr u8 inv_map_table[MAX_PROB] = { static constexpr u8 inv_map_table[MAX_PROB] = {
7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176, 189, 202, 215, 228, 241, 254, 7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176, 189, 202, 215, 228, 241, 254,
1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27,

View file

@ -476,14 +476,14 @@ DecoderErrorOr<void> Parser::segmentation_params(FrameContext& frame_context)
return {}; return {};
frame_context.should_use_absolute_segment_base_quantizer = TRY_READ(frame_context.bit_stream.read_bit()); frame_context.should_use_absolute_segment_base_quantizer = TRY_READ(frame_context.bit_stream.read_bit());
for (auto i = 0; i < MAX_SEGMENTS; i++) { for (auto segment_id = 0; segment_id < MAX_SEGMENTS; segment_id++) {
for (auto j = 0; j < SEG_LVL_MAX; j++) { for (auto feature_id = 0; feature_id < to_underlying(SegmentFeature::Sentinel); feature_id++) {
auto& feature = frame_context.segmentation_features[i][j]; auto& feature = frame_context.segmentation_features[segment_id][feature_id];
feature.enabled = TRY_READ(frame_context.bit_stream.read_bit()); feature.enabled = TRY_READ(frame_context.bit_stream.read_bit());
if (feature.enabled) { if (feature.enabled) {
auto bits_to_read = segmentation_feature_bits[j]; auto bits_to_read = segmentation_feature_bits[feature_id];
feature.value = TRY_READ(frame_context.bit_stream.read_bits(bits_to_read)); feature.value = TRY_READ(frame_context.bit_stream.read_bits(bits_to_read));
if (segmentation_feature_signed[j]) { if (segmentation_feature_signed[feature_id]) {
if (TRY_READ(frame_context.bit_stream.read_bit())) if (TRY_READ(frame_context.bit_stream.read_bit()))
feature.value = -feature.value; feature.value = -feature.value;
} }
@ -1094,16 +1094,11 @@ DecoderErrorOr<void> Parser::set_intra_segment_id(BlockContext& block_context)
DecoderErrorOr<bool> Parser::read_should_skip_residuals(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context) DecoderErrorOr<bool> Parser::read_should_skip_residuals(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context)
{ {
if (seg_feature_active(block_context, SEG_LVL_SKIP)) if (block_context.get_segment_feature(SegmentFeature::SkipResidualsOverride).enabled)
return true; return true;
return TRY_READ(TreeParser::parse_skip(block_context.decoder, *m_probability_tables, block_context.counter, above_context, left_context)); return TRY_READ(TreeParser::parse_skip(block_context.decoder, *m_probability_tables, block_context.counter, above_context, left_context));
} }
bool Parser::seg_feature_active(BlockContext const& block_context, u8 feature)
{
return block_context.frame_context.segmentation_features[block_context.segment_id][feature].enabled;
}
DecoderErrorOr<TransformSize> Parser::read_tx_size(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context, bool allow_select) DecoderErrorOr<TransformSize> Parser::read_tx_size(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context, bool allow_select)
{ {
auto max_tx_size = max_txsize_lookup[block_context.size]; auto max_tx_size = max_txsize_lookup[block_context.size];
@ -1176,8 +1171,9 @@ u8 Parser::get_segment_id(BlockContext const& block_context)
DecoderErrorOr<bool> Parser::read_is_inter(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context) DecoderErrorOr<bool> Parser::read_is_inter(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context)
{ {
if (seg_feature_active(block_context, SEG_LVL_REF_FRAME)) auto reference_frame_override_feature = block_context.get_segment_feature(SegmentFeature::ReferenceFrameOverride);
return block_context.frame_context.segmentation_features[block_context.segment_id][SEG_LVL_REF_FRAME].value != ReferenceFrameType::None; if (reference_frame_override_feature.enabled)
return reference_frame_override_feature.value != ReferenceFrameType::None;
return TRY_READ(TreeParser::parse_block_is_inter_predicted(block_context.decoder, *m_probability_tables, block_context.counter, above_context, left_context)); return TRY_READ(TreeParser::parse_block_is_inter_predicted(block_context.decoder, *m_probability_tables, block_context.counter, above_context, left_context));
} }
@ -1221,7 +1217,7 @@ DecoderErrorOr<void> Parser::inter_block_mode_info(BlockContext& block_context,
select_best_reference_motion_vectors(block_context, reference_motion_vectors, motion_vector_candidates, ReferenceIndex::Secondary); select_best_reference_motion_vectors(block_context, reference_motion_vectors, motion_vector_candidates, ReferenceIndex::Secondary);
} }
if (seg_feature_active(block_context, SEG_LVL_SKIP)) { if (block_context.get_segment_feature(SegmentFeature::SkipResidualsOverride).enabled) {
block_context.y_prediction_mode() = PredictionMode::ZeroMv; block_context.y_prediction_mode() = PredictionMode::ZeroMv;
} else if (block_context.size >= Block_8x8) { } else if (block_context.size >= Block_8x8) {
block_context.y_prediction_mode() = TRY_READ(TreeParser::parse_inter_mode(block_context.decoder, *m_probability_tables, block_context.counter, block_context.mode_context[block_context.reference_frame_types.primary])); block_context.y_prediction_mode() = TRY_READ(TreeParser::parse_inter_mode(block_context.decoder, *m_probability_tables, block_context.counter, block_context.mode_context[block_context.reference_frame_types.primary]));
@ -1259,8 +1255,9 @@ DecoderErrorOr<void> Parser::inter_block_mode_info(BlockContext& block_context,
DecoderErrorOr<void> Parser::read_ref_frames(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context) DecoderErrorOr<void> Parser::read_ref_frames(BlockContext& block_context, FrameBlockContext above_context, FrameBlockContext left_context)
{ {
if (seg_feature_active(block_context, SEG_LVL_REF_FRAME)) { auto reference_frame_override_feature = block_context.get_segment_feature(SegmentFeature::ReferenceFrameOverride);
block_context.reference_frame_types = { static_cast<ReferenceFrameType>(block_context.frame_context.segmentation_features[block_context.segment_id][SEG_LVL_REF_FRAME].value), ReferenceFrameType::None }; if (reference_frame_override_feature.enabled) {
block_context.reference_frame_types = { static_cast<ReferenceFrameType>(reference_frame_override_feature.value), ReferenceFrameType::None };
return {}; return {};
} }

View file

@ -98,7 +98,6 @@ private:
DecoderErrorOr<void> intra_frame_mode_info(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context); DecoderErrorOr<void> intra_frame_mode_info(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> set_intra_segment_id(BlockContext&); DecoderErrorOr<void> set_intra_segment_id(BlockContext&);
DecoderErrorOr<bool> read_should_skip_residuals(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context); DecoderErrorOr<bool> read_should_skip_residuals(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context);
static bool seg_feature_active(BlockContext const&, u8 feature);
DecoderErrorOr<TransformSize> read_tx_size(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context, bool allow_select); DecoderErrorOr<TransformSize> read_tx_size(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context, bool allow_select);
DecoderErrorOr<void> inter_frame_mode_info(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context); DecoderErrorOr<void> inter_frame_mode_info(BlockContext&, FrameBlockContext above_context, FrameBlockContext left_context);
DecoderErrorOr<void> set_inter_segment_id(BlockContext&); DecoderErrorOr<void> set_inter_segment_id(BlockContext&);
@ -130,7 +129,7 @@ private:
Array<i8, MAX_REF_FRAMES> m_previous_loop_filter_ref_deltas; Array<i8, MAX_REF_FRAMES> m_previous_loop_filter_ref_deltas;
Array<i8, 2> m_previous_loop_filter_mode_deltas; Array<i8, 2> m_previous_loop_filter_mode_deltas;
bool m_previous_should_use_absolute_segment_base_quantizer; bool m_previous_should_use_absolute_segment_base_quantizer;
Array<Array<SegmentFeature, SEG_LVL_MAX>, MAX_SEGMENTS> m_previous_segmentation_features; SegmentationFeatures m_previous_segmentation_features;
ReferenceFrame m_reference_frames[NUM_REF_FRAMES]; ReferenceFrame m_reference_frames[NUM_REF_FRAMES];

View file

@ -33,11 +33,6 @@ namespace Video::VP9 {
#define COMP_MODE_CONTEXTS 5 #define COMP_MODE_CONTEXTS 5
#define REF_CONTEXTS 5 #define REF_CONTEXTS 5
#define MAX_SEGMENTS 8 #define MAX_SEGMENTS 8
#define SEG_LVL_ALT_Q 0
#define SEG_LVL_ALT_L 1
#define SEG_LVL_REF_FRAME 2
#define SEG_LVL_SKIP 3
#define SEG_LVL_MAX 4
#define BLOCK_TYPES 2 #define BLOCK_TYPES 2
#define REF_TYPES 2 #define REF_TYPES 2
#define COEF_BANDS 6 #define COEF_BANDS 6