diff options
Diffstat (limited to 'libgav1/src/tile/bitstream/mode_info.cc')
-rw-r--r-- | libgav1/src/tile/bitstream/mode_info.cc | 261 |
1 files changed, 128 insertions, 133 deletions
diff --git a/libgav1/src/tile/bitstream/mode_info.cc b/libgav1/src/tile/bitstream/mode_info.cc index a50a195..d73ebed 100644 --- a/libgav1/src/tile/bitstream/mode_info.cc +++ b/libgav1/src/tile/bitstream/mode_info.cc @@ -109,29 +109,21 @@ int DecodeSegmentId(int diff, int reference, int max) { } // This is called DrlCtxStack in section 7.10.2.14 of the spec. -int GetRefMvIndexContext( - const CandidateMotionVector ref_mv_stack[kMaxRefMvStackSize], int count, - int index) { - if (index + 1 >= count || - (ref_mv_stack[index].weight >= kExtraWeightForNearestMvs && - ref_mv_stack[index + 1].weight >= kExtraWeightForNearestMvs)) { +// In the spec, the weights of all the nearest mvs are incremented by a bonus +// weight which is larger than any natural weight, and the weights of the mvs +// are compared with this bonus weight to determine their contexts. We replace +// this procedure by introducing |nearest_mv_count| in PredictionParameters, +// 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 GetRefMvIndexContext(int nearest_mv_count, int index) { + if (index + 1 < nearest_mv_count) { return 0; } - if (ref_mv_stack[index].weight >= kExtraWeightForNearestMvs && - ref_mv_stack[index + 1].weight < kExtraWeightForNearestMvs) { + if (index + 1 == nearest_mv_count) { return 1; } - if (ref_mv_stack[index].weight < kExtraWeightForNearestMvs && - ref_mv_stack[index + 1].weight < kExtraWeightForNearestMvs) { - return 2; - } - return 0; -} - -// Returns true if the either the width or the height of the block is equal to -// four. -bool IsBlockDimension4(BlockSize size) { - return size < kBlock8x8 || size == kBlock16x4; + return 2; } // Returns true if both the width and height of the block is less than 64. @@ -139,21 +131,73 @@ bool IsBlockDimensionLessThan64(BlockSize size) { return size <= kBlock32x32 && size != kBlock16x64; } +int GetUseCompoundReferenceContext(const Tile::Block& block) { + if (block.top_available[kPlaneY] && block.left_available[kPlaneY]) { + if (block.IsTopSingle() && block.IsLeftSingle()) { + return static_cast<int>(IsBackwardReference(block.TopReference(0))) ^ + static_cast<int>(IsBackwardReference(block.LeftReference(0))); + } + if (block.IsTopSingle()) { + return 2 + static_cast<int>(IsBackwardReference(block.TopReference(0)) || + block.IsTopIntra()); + } + if (block.IsLeftSingle()) { + return 2 + static_cast<int>(IsBackwardReference(block.LeftReference(0)) || + block.IsLeftIntra()); + } + return 4; + } + if (block.top_available[kPlaneY]) { + return block.IsTopSingle() + ? static_cast<int>(IsBackwardReference(block.TopReference(0))) + : 3; + } + if (block.left_available[kPlaneY]) { + return block.IsLeftSingle() + ? static_cast<int>(IsBackwardReference(block.LeftReference(0))) + : 3; + } + return 1; +} + +// Calculates count0 by calling block.CountReferences() on the frame types from +// type0_start to type0_end, inclusive, and summing the results. +// Calculates count1 by calling block.CountReferences() on the frame types from +// type1_start to type1_end, inclusive, and summing the results. +// Compares count0 with count1 and returns 0, 1 or 2. +// +// See count_refs and ref_count_ctx in 8.3.2. +int GetReferenceContext(const Tile::Block& block, + ReferenceFrameType type0_start, + ReferenceFrameType type0_end, + ReferenceFrameType type1_start, + ReferenceFrameType type1_end) { + int count0 = 0; + int count1 = 0; + for (int type = type0_start; type <= type0_end; ++type) { + count0 += block.CountReferences(static_cast<ReferenceFrameType>(type)); + } + for (int type = type1_start; type <= type1_end; ++type) { + count1 += block.CountReferences(static_cast<ReferenceFrameType>(type)); + } + return (count0 < count1) ? 0 : (count0 == count1 ? 1 : 2); +} + } // namespace bool Tile::ReadSegmentId(const Block& block) { int top_left = -1; - if (block.top_available && block.left_available) { + if (block.top_available[kPlaneY] && block.left_available[kPlaneY]) { top_left = block_parameters_holder_.Find(block.row4x4 - 1, block.column4x4 - 1) ->segment_id; } int top = -1; - if (block.top_available) { + if (block.top_available[kPlaneY]) { top = block.bp_top->segment_id; } int left = -1; - if (block.left_available) { + if (block.left_available[kPlaneY]) { left = block.bp_left->segment_id; } int pred; @@ -215,10 +259,10 @@ void Tile::ReadSkip(const Block& block) { return; } int context = 0; - if (block.top_available && block.bp_top->skip) { + if (block.top_available[kPlaneY] && block.bp_top->skip) { ++context; } - if (block.left_available && block.bp_left->skip) { + if (block.left_available[kPlaneY] && block.bp_left->skip) { ++context; } uint16_t* const skip_cdf = symbol_decoder_context_.skip_cdf[context]; @@ -239,8 +283,11 @@ void Tile::ReadSkipMode(const Block& block) { return; } const int context = - (block.left_available ? static_cast<int>(block.bp_left->skip_mode) : 0) + - (block.top_available ? static_cast<int>(block.bp_top->skip_mode) : 0); + (block.left_available[kPlaneY] + ? static_cast<int>(block.bp_left->skip_mode) + : 0) + + (block.top_available[kPlaneY] ? static_cast<int>(block.bp_top->skip_mode) + : 0); bp.skip_mode = reader_.ReadSymbol(symbol_decoder_context_.skip_mode_cdf[context]); } @@ -259,11 +306,12 @@ void Tile::ReadCdef(const Block& block) { const int column = DivideBy16(column4x4); if (cdef_index_[row][column] == -1) { cdef_index_[row][column] = - static_cast<int16_t>(reader_.ReadLiteral(frame_header_.cdef.bits)); - const int width4x4 = kNum4x4BlocksWide[block.size]; - const int height4x4 = kNum4x4BlocksHigh[block.size]; - for (int i = row4x4; i < row4x4 + height4x4; i += cdef_size4x4) { - for (int j = column4x4; j < column4x4 + width4x4; j += cdef_size4x4) { + frame_header_.cdef.bits > 0 + ? static_cast<int16_t>(reader_.ReadLiteral(frame_header_.cdef.bits)) + : 0; + for (int i = row4x4; i < row4x4 + block.height4x4; i += cdef_size4x4) { + for (int j = column4x4; j < column4x4 + block.width4x4; + j += cdef_size4x4) { cdef_index_[DivideBy16(i)][DivideBy16(j)] = cdef_index_[row][column]; } } @@ -337,9 +385,10 @@ void Tile::ReadPredictionModeY(const Block& block, bool intra_y_mode) { uint16_t* cdf; if (intra_y_mode) { const PredictionMode top_mode = - block.top_available ? block.bp_top->y_mode : kPredictionModeDc; - const PredictionMode left_mode = - block.left_available ? block.bp_left->y_mode : kPredictionModeDc; + block.top_available[kPlaneY] ? block.bp_top->y_mode : kPredictionModeDc; + const PredictionMode left_mode = block.left_available[kPlaneY] + ? block.bp_left->y_mode + : kPredictionModeDc; const int top_context = kIntraYModeContext[top_mode]; const int left_context = kIntraYModeContext[left_mode]; cdf = symbol_decoder_context_ @@ -398,17 +447,20 @@ void Tile::ReadPredictionModeUV(const Block& block) { BlockParameters& bp = *block.bp; bool chroma_from_luma_allowed; if (frame_header_.segmentation.lossless[bp.segment_id]) { - chroma_from_luma_allowed = block.residual_size[kPlaneTypeUV] == kBlock4x4; + chroma_from_luma_allowed = block.residual_size[kPlaneU] == kBlock4x4; } else { chroma_from_luma_allowed = IsBlockDimensionLessThan64(block.size); } uint16_t* const cdf = symbol_decoder_context_ .uv_mode_cdf[static_cast<int>(chroma_from_luma_allowed)][bp.y_mode]; - const int symbol_count = - kIntraPredictionModesUV - static_cast<int>(!chroma_from_luma_allowed); - bp.uv_mode = - static_cast<PredictionMode>(reader_.ReadSymbol(cdf, symbol_count)); + if (chroma_from_luma_allowed) { + bp.uv_mode = static_cast<PredictionMode>( + reader_.ReadSymbol<kIntraPredictionModesUV>(cdf)); + } else { + bp.uv_mode = static_cast<PredictionMode>( + reader_.ReadSymbol<kIntraPredictionModesUV - 1>(cdf)); + } } int Tile::ReadMotionVectorComponent(const Block& block, const int component) { @@ -463,11 +515,11 @@ void Tile::ReadMotionVector(const Block& block, int index) { static_cast<int>(kNumMvJointTypes))); if (mv_joint == kMvJointTypeHorizontalZeroVerticalNonZero || mv_joint == kMvJointTypeNonZero) { - bp.mv[index].mv[0] = ReadMotionVectorComponent(block, 0); + bp.mv.mv[index].mv[0] = ReadMotionVectorComponent(block, 0); } if (mv_joint == kMvJointTypeHorizontalNonZeroVerticalZero || mv_joint == kMvJointTypeNonZero) { - bp.mv[index].mv[1] = ReadMotionVectorComponent(block, 1); + bp.mv.mv[index].mv[1] = ReadMotionVectorComponent(block, 1); } } @@ -529,11 +581,9 @@ bool Tile::DecodeIntraModeInfo(const Block& block) { bp.palette_mode_info.size[kPlaneTypeUV] = 0; bp.interpolation_filter[0] = kInterpolationFilterBilinear; bp.interpolation_filter[1] = kInterpolationFilterBilinear; - FindMvStack(block, /*is_compound=*/false, reference_frame_sign_bias_, - *motion_field_mv_, prediction_parameters.ref_mv_stack, - &prediction_parameters.ref_mv_count, /*contexts=*/nullptr, - prediction_parameters.global_mv); - return AssignMv(block, /*is_compound=*/false); + MvContexts dummy_mode_contexts; + FindMvStack(block, /*is_compound=*/false, &dummy_mode_contexts); + return AssignIntraMv(block); } bp.is_inter = false; return ReadIntraBlockModeInfo(block, /*intra_y_mode=*/true); @@ -545,9 +595,9 @@ int8_t Tile::ComputePredictedSegmentId(const Block& block) const { if (prev_segment_ids_ == nullptr) return 0; const int x_limit = std::min(frame_header_.columns4x4 - block.column4x4, - static_cast<int>(kNum4x4BlocksWide[block.size])); + static_cast<int>(block.width4x4)); const int y_limit = std::min(frame_header_.rows4x4 - block.row4x4, - static_cast<int>(kNum4x4BlocksHigh[block.size])); + static_cast<int>(block.height4x4)); int8_t id = 7; for (int y = 0; y < y_limit; ++y) { for (int x = 0; x < x_limit; ++x) { @@ -580,10 +630,10 @@ bool Tile::ReadInterSegmentId(const Block& block, bool pre_skip) { } if (frame_header_.segmentation.temporal_update) { const int context = - (block.left_available + (block.left_available[kPlaneY] ? static_cast<int>(block.bp_left->use_predicted_segment_id) : 0) + - (block.top_available + (block.top_available[kPlaneY] ? static_cast<int>(block.bp_top->use_predicted_segment_id) : 0); bp.use_predicted_segment_id = reader_.ReadSymbol( @@ -616,13 +666,14 @@ void Tile::ReadIsInter(const Block& block) { return; } int context = 0; - if (block.top_available && block.left_available) { + if (block.top_available[kPlaneY] && block.left_available[kPlaneY]) { context = (block.IsTopIntra() && block.IsLeftIntra()) ? 3 : static_cast<int>(block.IsTopIntra() || block.IsLeftIntra()); - } else if (block.top_available || block.left_available) { - context = 2 * static_cast<int>(block.top_available ? block.IsTopIntra() - : block.IsLeftIntra()); + } else if (block.top_available[kPlaneY] || block.left_available[kPlaneY]) { + context = 2 * static_cast<int>(block.top_available[kPlaneY] + ? block.IsTopIntra() + : block.IsLeftIntra()); } bp.is_inter = reader_.ReadSymbol(symbol_decoder_context_.is_inter_cdf[context]); @@ -646,41 +697,12 @@ bool Tile::ReadIntraBlockModeInfo(const Block& block, bool intra_y_mode) { return true; } -int Tile::GetUseCompoundReferenceContext(const Block& block) { - if (block.top_available && block.left_available) { - if (block.IsTopSingle() && block.IsLeftSingle()) { - return static_cast<int>(IsBackwardReference(block.TopReference(0))) ^ - static_cast<int>(IsBackwardReference(block.LeftReference(0))); - } - if (block.IsTopSingle()) { - return 2 + static_cast<int>(IsBackwardReference(block.TopReference(0)) || - block.IsTopIntra()); - } - if (block.IsLeftSingle()) { - return 2 + static_cast<int>(IsBackwardReference(block.LeftReference(0)) || - block.IsLeftIntra()); - } - return 4; - } - if (block.top_available) { - return block.IsTopSingle() - ? static_cast<int>(IsBackwardReference(block.TopReference(0))) - : 3; - } - if (block.left_available) { - return block.IsLeftSingle() - ? static_cast<int>(IsBackwardReference(block.LeftReference(0))) - : 3; - } - return 1; -} - CompoundReferenceType Tile::ReadCompoundReferenceType(const Block& block) { // compound and inter. - const bool top_comp_inter = - block.top_available && !block.IsTopIntra() && !block.IsTopSingle(); - const bool left_comp_inter = - block.left_available && !block.IsLeftIntra() && !block.IsLeftSingle(); + const bool top_comp_inter = block.top_available[kPlaneY] && + !block.IsTopIntra() && !block.IsTopSingle(); + const bool left_comp_inter = block.left_available[kPlaneY] && + !block.IsLeftIntra() && !block.IsLeftSingle(); // unidirectional compound. const bool top_uni_comp = top_comp_inter && IsSameDirectionReferencePair(block.TopReference(0), @@ -689,8 +711,8 @@ CompoundReferenceType Tile::ReadCompoundReferenceType(const Block& block) { left_comp_inter && IsSameDirectionReferencePair(block.LeftReference(0), block.LeftReference(1)); int context; - if (block.top_available && !block.IsTopIntra() && block.left_available && - !block.IsLeftIntra()) { + if (block.top_available[kPlaneY] && !block.IsTopIntra() && + block.left_available[kPlaneY] && !block.IsLeftIntra()) { const int same_direction = static_cast<int>(IsSameDirectionReferencePair( block.TopReference(0), block.LeftReference(0))); if (!top_comp_inter && !left_comp_inter) { @@ -710,7 +732,7 @@ CompoundReferenceType Tile::ReadCompoundReferenceType(const Block& block) { (block.LeftReference(0) == kReferenceFrameBackward)); } } - } else if (block.top_available && block.left_available) { + } else if (block.top_available[kPlaneY] && block.left_available[kPlaneY]) { if (top_comp_inter) { context = 1 + MultiplyBy2(static_cast<int>(top_uni_comp)); } else if (left_comp_inter) { @@ -729,22 +751,6 @@ CompoundReferenceType Tile::ReadCompoundReferenceType(const Block& block) { symbol_decoder_context_.compound_reference_type_cdf[context])); } -int Tile::GetReferenceContext(const Block& block, - ReferenceFrameType type0_start, - ReferenceFrameType type0_end, - ReferenceFrameType type1_start, - ReferenceFrameType type1_end) const { - int count0 = 0; - int count1 = 0; - for (int type = type0_start; type <= type0_end; ++type) { - count0 += block.CountReferences(static_cast<ReferenceFrameType>(type)); - } - for (int type = type1_start; type <= type1_end; ++type) { - count1 += block.CountReferences(static_cast<ReferenceFrameType>(type)); - } - return (count0 < count1) ? 0 : (count0 == count1 ? 1 : 2); -} - template <bool is_single, bool is_backward, int index> uint16_t* Tile::GetReferenceCdf( const Block& block, @@ -826,11 +832,9 @@ void Tile::ReadReferenceFrames(const Block& block) { bp.reference_frame[1] = kReferenceFrameNone; return; } - const int block_width4x4 = kNum4x4BlocksWide[block.size]; - const int block_height4x4 = kNum4x4BlocksHigh[block.size]; const bool use_compound_reference = frame_header_.reference_mode_select && - std::min(block_width4x4, block_height4x4) >= 2 && + std::min(block.width4x4, block.height4x4) >= 2 && reader_.ReadSymbol(symbol_decoder_context_.use_compound_reference_cdf [GetUseCompoundReferenceContext(block)]); if (use_compound_reference) { @@ -982,12 +986,11 @@ void Tile::ReadRefMvIndex(const Block& block) { static_cast<int>(kPredictionModeHasNearMvMask.Contains(bp.y_mode)); prediction_parameters.ref_mv_index = start; for (int i = start; i < start + 2; ++i) { - if (prediction_parameters.ref_mv_count <= i + 1) continue; + if (prediction_parameters.ref_mv_count <= i + 1) break; // drl_mode in the spec. const bool ref_mv_index_bit = reader_.ReadSymbol( symbol_decoder_context_.ref_mv_index_cdf[GetRefMvIndexContext( - prediction_parameters.ref_mv_stack, - prediction_parameters.ref_mv_count, i)]); + prediction_parameters.nearest_mv_count, i)]); prediction_parameters.ref_mv_index = i + static_cast<int>(ref_mv_index_bit); if (!ref_mv_index_bit) return; } @@ -1084,14 +1087,14 @@ void Tile::ReadMotionMode(const Block& block, bool is_compound) { uint16_t* Tile::GetIsExplicitCompoundTypeCdf(const Block& block) { int context = 0; - if (block.top_available) { + if (block.top_available[kPlaneY]) { if (!block.IsTopSingle()) { context += static_cast<int>(block.bp_top->is_explicit_compound_type); } else if (block.TopReference(0) == kReferenceFrameAlternate) { context += 3; } } - if (block.left_available) { + if (block.left_available[kPlaneY]) { if (!block.IsLeftSingle()) { context += static_cast<int>(block.bp_left->is_explicit_compound_type); } else if (block.LeftReference(0) == kReferenceFrameAlternate) { @@ -1104,23 +1107,20 @@ uint16_t* Tile::GetIsExplicitCompoundTypeCdf(const Block& block) { uint16_t* Tile::GetIsCompoundTypeAverageCdf(const Block& block) { const BlockParameters& bp = *block.bp; - const int forward = std::abs(GetRelativeDistance( - current_frame_.order_hint(bp.reference_frame[0]), - frame_header_.order_hint, sequence_header_.enable_order_hint, - sequence_header_.order_hint_bits)); - const int backward = std::abs(GetRelativeDistance( - current_frame_.order_hint(bp.reference_frame[1]), - frame_header_.order_hint, sequence_header_.enable_order_hint, - sequence_header_.order_hint_bits)); + const ReferenceInfo& reference_info = *current_frame_.reference_info(); + const int forward = + std::abs(reference_info.relative_distance_from[bp.reference_frame[0]]); + const int backward = + std::abs(reference_info.relative_distance_from[bp.reference_frame[1]]); int context = (forward == backward) ? 3 : 0; - if (block.top_available) { + if (block.top_available[kPlaneY]) { if (!block.IsTopSingle()) { context += static_cast<int>(block.bp_top->is_compound_type_average); } else if (block.TopReference(0) == kReferenceFrameAlternate) { ++context; } } - if (block.left_available) { + if (block.left_available[kPlaneY]) { if (!block.IsLeftSingle()) { context += static_cast<int>(block.bp_left->is_compound_type_average); } else if (block.LeftReference(0) == kReferenceFrameAlternate) { @@ -1200,14 +1200,14 @@ uint16_t* Tile::GetInterpolationFilterCdf(const Block& block, int direction) { MultiplyBy4(static_cast<int>(bp.reference_frame[1] > kReferenceFrameIntra)); int top_type = kNumExplicitInterpolationFilters; - if (block.top_available) { + if (block.top_available[kPlaneY]) { if (block.bp_top->reference_frame[0] == bp.reference_frame[0] || block.bp_top->reference_frame[1] == bp.reference_frame[0]) { top_type = block.bp_top->interpolation_filter[direction]; } } int left_type = kNumExplicitInterpolationFilters; - if (block.left_available) { + if (block.left_available[kPlaneY]) { if (block.bp_left->reference_frame[0] == bp.reference_frame[0] || block.bp_left->reference_frame[1] == bp.reference_frame[0]) { left_type = block.bp_left->interpolation_filter[direction]; @@ -1273,16 +1273,11 @@ bool Tile::ReadInterBlockModeInfo(const Block& block) { bp.palette_mode_info.size[kPlaneTypeUV] = 0; ReadReferenceFrames(block); const bool is_compound = bp.reference_frame[1] > kReferenceFrameIntra; - PredictionParameters& prediction_parameters = - *block.bp->prediction_parameters; MvContexts mode_contexts; - FindMvStack(block, is_compound, reference_frame_sign_bias_, *motion_field_mv_, - prediction_parameters.ref_mv_stack, - &prediction_parameters.ref_mv_count, &mode_contexts, - prediction_parameters.global_mv); + FindMvStack(block, is_compound, &mode_contexts); ReadInterPredictionModeY(block, mode_contexts); ReadRefMvIndex(block); - if (!AssignMv(block, is_compound)) return false; + if (!AssignInterMv(block, is_compound)) return false; ReadInterIntraMode(block, is_compound); ReadMotionMode(block, is_compound); ReadCompoundType(block, is_compound); |