[video_core/host1x] VP9 Video Playback Fixes (#4590)

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
https://git.eden-emu.dev/eden-emu/eden/pulls/4542

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4590
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: John <john@eden-emu.dev>
This commit is contained in:
PavelBARABANOV
2026-10-30 03:06:33 +01:00
committed by crueter
parent 3e6a5566cf
commit 0731f40f4d
2 changed files with 32 additions and 19 deletions
+8
View File
@@ -312,6 +312,10 @@ struct Vp9PictureInfo {
bool allow_high_precision_mv; bool allow_high_precision_mv;
bool segment_enabled; bool segment_enabled;
bool mode_ref_delta_enabled; bool mode_ref_delta_enabled;
Segmentation segmentation;
std::array<u8, 7> seg_tree_probs;
std::array<u8, 3> seg_pred_probs;
}; };
struct Vp9FrameContainer { struct Vp9FrameContainer {
@@ -377,6 +381,10 @@ struct PictureInfo {
.allow_high_precision_mv = allow_high_precision_mv != 0, .allow_high_precision_mv = allow_high_precision_mv != 0,
.segment_enabled = segmentation.enabled != 0, .segment_enabled = segmentation.enabled != 0,
.mode_ref_delta_enabled = loop_filter.mode_ref_delta_enabled != 0, .mode_ref_delta_enabled = loop_filter.mode_ref_delta_enabled != 0,
.segmentation = segmentation,
.seg_tree_probs = {},
.seg_pred_probs = {},
}; };
} }
}; };
+24 -19
View File
@@ -331,19 +331,16 @@ void VP9::WriteMvProbabilityUpdate(VpxRangeEncoder& writer, u8 new_prob, u8 old_
} }
void VP9::WriteSegmentation(VpxBitStreamWriter& writer) { void VP9::WriteSegmentation(VpxBitStreamWriter& writer) {
bool enabled = current_picture_info.segmentation.enabled != 0; bool enabled = current_frame_info.segmentation.enabled != 0;
writer.WriteBit(enabled); writer.WriteBit(enabled);
if (!enabled) { if (!enabled) {
return; return;
} }
auto update_map = current_picture_info.segmentation.update_map != 0; auto update_map = current_frame_info.segmentation.update_map != 0;
writer.WriteBit(update_map); writer.WriteBit(update_map);
if (update_map) { if (update_map) {
EntropyProbs entropy_probs{};
host1x.gmmu_manager.ReadBlock(regs.vp9_prob_tab_buffer_offset.Address(), &entropy_probs, sizeof(entropy_probs));
auto WriteProb = [&](u8 prob) { auto WriteProb = [&](u8 prob) {
bool coded = prob != 255; bool coded = prob != 255;
writer.WriteBit(coded); writer.WriteBit(coded);
@@ -352,55 +349,55 @@ void VP9::WriteSegmentation(VpxBitStreamWriter& writer) {
} }
}; };
for (size_t i = 0; i < entropy_probs.mb_segment_tree_probs.size(); i++) { for (size_t i = 0; i < current_frame_info.seg_tree_probs.size(); i++) {
WriteProb(entropy_probs.mb_segment_tree_probs[i]); WriteProb(current_frame_info.seg_tree_probs[i]);
} }
auto temporal_update = current_picture_info.segmentation.temporal_update != 0; auto temporal_update = current_frame_info.segmentation.temporal_update != 0;
writer.WriteBit(temporal_update); writer.WriteBit(temporal_update);
if (temporal_update) { if (temporal_update) {
for (s32 i = 0; i < 3; i++) { for (s32 i = 0; i < 3; i++) {
WriteProb(entropy_probs.segment_pred_probs[i]); WriteProb(current_frame_info.seg_pred_probs[i]);
} }
} }
} }
if (last_segmentation == current_picture_info.segmentation) { if (last_segmentation == current_frame_info.segmentation) {
writer.WriteBit(false); writer.WriteBit(false);
return; return;
} }
last_segmentation = current_picture_info.segmentation; last_segmentation = current_frame_info.segmentation;
writer.WriteBit(true); writer.WriteBit(true);
writer.WriteBit(current_picture_info.segmentation.abs_delta != 0); writer.WriteBit(current_frame_info.segmentation.abs_delta != 0);
constexpr s32 MAX_SEGMENTS = 8; constexpr s32 MAX_SEGMENTS = 8;
constexpr std::array SegmentationFeatureBits = {8, 6, 2, 0}; constexpr std::array SegmentationFeatureBits = {8, 6, 2, 0};
for (s32 i = 0; i < MAX_SEGMENTS; i++) { for (s32 i = 0; i < MAX_SEGMENTS; i++) {
auto q_enabled = current_picture_info.segmentation.feature_enabled[i][0] != 0; auto q_enabled = current_frame_info.segmentation.feature_enabled[i][0] != 0;
writer.WriteBit(q_enabled); writer.WriteBit(q_enabled);
if (q_enabled) { if (q_enabled) {
writer.WriteS(current_picture_info.segmentation.feature_data[i][0], writer.WriteS(current_frame_info.segmentation.feature_data[i][0],
SegmentationFeatureBits[0]); SegmentationFeatureBits[0]);
} }
auto lf_enabled = current_picture_info.segmentation.feature_enabled[i][1] != 0; auto lf_enabled = current_frame_info.segmentation.feature_enabled[i][1] != 0;
writer.WriteBit(lf_enabled); writer.WriteBit(lf_enabled);
if (lf_enabled) { if (lf_enabled) {
writer.WriteS(current_picture_info.segmentation.feature_data[i][1], writer.WriteS(current_frame_info.segmentation.feature_data[i][1],
SegmentationFeatureBits[1]); SegmentationFeatureBits[1]);
} }
auto ref_enabled = current_picture_info.segmentation.feature_enabled[i][2] != 0; auto ref_enabled = current_frame_info.segmentation.feature_enabled[i][2] != 0;
writer.WriteBit(ref_enabled); writer.WriteBit(ref_enabled);
if (ref_enabled) { if (ref_enabled) {
writer.WriteU(current_picture_info.segmentation.feature_data[i][2], writer.WriteU(current_frame_info.segmentation.feature_data[i][2],
SegmentationFeatureBits[2]); SegmentationFeatureBits[2]);
} }
auto skip_enabled = current_picture_info.segmentation.feature_enabled[i][3] != 0; auto skip_enabled = current_frame_info.segmentation.feature_enabled[i][3] != 0;
writer.WriteBit(skip_enabled); writer.WriteBit(skip_enabled);
} }
} }
@@ -411,6 +408,14 @@ Vp9PictureInfo VP9::GetVp9PictureInfo() {
InsertEntropy(regs.vp9_prob_tab_buffer_offset.Address(), vp9_info.entropy); InsertEntropy(regs.vp9_prob_tab_buffer_offset.Address(), vp9_info.entropy);
EntropyProbs entropy_probs{};
host1x.gmmu_manager.ReadBlock(regs.vp9_prob_tab_buffer_offset.Address(),
&entropy_probs, sizeof(entropy_probs));
vp9_info.seg_tree_probs = entropy_probs.mb_segment_tree_probs;
vp9_info.seg_pred_probs = entropy_probs.segment_pred_probs;
// surface_luma_offset[0:3] contains the address of the reference frame offsets in the following // surface_luma_offset[0:3] contains the address of the reference frame offsets in the following
// order: last, golden, altref, current. // order: last, golden, altref, current.
for (size_t i = 0; i < 4; i++) { for (size_t i = 0; i < 4; i++) {