diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | 58 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h | 45 | ||||
| -rw-r--r-- | src/video_core/command_classes/codecs/vp9.cpp | 134 | ||||
| -rw-r--r-- | src/video_core/command_classes/codecs/vp9.h | 14 | ||||
| -rw-r--r-- | src/video_core/command_classes/codecs/vp9_types.h | 6 |
5 files changed, 52 insertions, 205 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index 1403a39d0..845de724d 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | |||
| @@ -166,8 +166,6 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vecto | |||
| 166 | LOG_ERROR(Service_NVDRV, "failed to map size={}", object->size); | 166 | LOG_ERROR(Service_NVDRV, "failed to map size={}", object->size); |
| 167 | } else { | 167 | } else { |
| 168 | cmd_buffer.map_address = object->dma_map_addr; | 168 | cmd_buffer.map_address = object->dma_map_addr; |
| 169 | AddBufferMap(object->dma_map_addr, object->size, object->addr, | ||
| 170 | object->status == nvmap::Object::Status::Allocated); | ||
| 171 | } | 169 | } |
| 172 | } | 170 | } |
| 173 | std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBuffer)); | 171 | std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBuffer)); |
| @@ -178,30 +176,11 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vecto | |||
| 178 | } | 176 | } |
| 179 | 177 | ||
| 180 | NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { | 178 | NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { |
| 181 | IoctlMapBuffer params{}; | 179 | // This is intntionally stubbed. |
| 182 | std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); | 180 | // Skip unmapping buffers here, as to not break the continuity of the VP9 reference frame |
| 183 | std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); | 181 | // addresses, and risk invalidating data before the async GPU thread is done with it |
| 184 | SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer)); | ||
| 185 | |||
| 186 | auto& gpu = system.GPU(); | ||
| 187 | |||
| 188 | for (auto& cmd_buffer : cmd_buffer_handles) { | ||
| 189 | const auto object{nvmap_dev->GetObject(cmd_buffer.map_handle)}; | ||
| 190 | if (!object) { | ||
| 191 | LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmd_buffer.map_handle); | ||
| 192 | std::memcpy(output.data(), ¶ms, output.size()); | ||
| 193 | return NvResult::InvalidState; | ||
| 194 | } | ||
| 195 | if (const auto size{RemoveBufferMap(object->dma_map_addr)}; size) { | ||
| 196 | gpu.MemoryManager().Unmap(object->dma_map_addr, *size); | ||
| 197 | } else { | ||
| 198 | // This occurs quite frequently, however does not seem to impact functionality | ||
| 199 | LOG_DEBUG(Service_NVDRV, "invalid offset=0x{:X} dma=0x{:X}", object->addr, | ||
| 200 | object->dma_map_addr); | ||
| 201 | } | ||
| 202 | object->dma_map_addr = 0; | ||
| 203 | } | ||
| 204 | std::memset(output.data(), 0, output.size()); | 182 | std::memset(output.data(), 0, output.size()); |
| 183 | LOG_DEBUG(Service_NVDRV, "(STUBBED) called"); | ||
| 205 | return NvResult::Success; | 184 | return NvResult::Success; |
| 206 | } | 185 | } |
| 207 | 186 | ||
| @@ -212,33 +191,4 @@ NvResult nvhost_nvdec_common::SetSubmitTimeout(const std::vector<u8>& input, | |||
| 212 | return NvResult::Success; | 191 | return NvResult::Success; |
| 213 | } | 192 | } |
| 214 | 193 | ||
| 215 | std::optional<nvhost_nvdec_common::BufferMap> nvhost_nvdec_common::FindBufferMap( | ||
| 216 | GPUVAddr gpu_addr) const { | ||
| 217 | const auto it = std::find_if( | ||
| 218 | buffer_mappings.begin(), buffer_mappings.upper_bound(gpu_addr), [&](const auto& entry) { | ||
| 219 | return (gpu_addr >= entry.second.StartAddr() && gpu_addr < entry.second.EndAddr()); | ||
| 220 | }); | ||
| 221 | |||
| 222 | ASSERT(it != buffer_mappings.end()); | ||
| 223 | return it->second; | ||
| 224 | } | ||
| 225 | |||
| 226 | void nvhost_nvdec_common::AddBufferMap(GPUVAddr gpu_addr, std::size_t size, VAddr cpu_addr, | ||
| 227 | bool is_allocated) { | ||
| 228 | buffer_mappings.insert_or_assign(gpu_addr, BufferMap{gpu_addr, size, cpu_addr, is_allocated}); | ||
| 229 | } | ||
| 230 | |||
| 231 | std::optional<std::size_t> nvhost_nvdec_common::RemoveBufferMap(GPUVAddr gpu_addr) { | ||
| 232 | const auto iter{buffer_mappings.find(gpu_addr)}; | ||
| 233 | if (iter == buffer_mappings.end()) { | ||
| 234 | return std::nullopt; | ||
| 235 | } | ||
| 236 | std::size_t size = 0; | ||
| 237 | if (iter->second.IsAllocated()) { | ||
| 238 | size = iter->second.Size(); | ||
| 239 | } | ||
| 240 | buffer_mappings.erase(iter); | ||
| 241 | return size; | ||
| 242 | } | ||
| 243 | |||
| 244 | } // namespace Service::Nvidia::Devices | 194 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h index da10f5f41..af59f00d2 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h | |||
| @@ -23,45 +23,6 @@ public: | |||
| 23 | ~nvhost_nvdec_common() override; | 23 | ~nvhost_nvdec_common() override; |
| 24 | 24 | ||
| 25 | protected: | 25 | protected: |
| 26 | class BufferMap final { | ||
| 27 | public: | ||
| 28 | constexpr BufferMap() = default; | ||
| 29 | |||
| 30 | constexpr BufferMap(GPUVAddr start_addr_, std::size_t size_) | ||
| 31 | : start_addr{start_addr_}, end_addr{start_addr_ + size_} {} | ||
| 32 | |||
| 33 | constexpr BufferMap(GPUVAddr start_addr_, std::size_t size_, VAddr cpu_addr_, | ||
| 34 | bool is_allocated_) | ||
| 35 | : start_addr{start_addr_}, end_addr{start_addr_ + size_}, cpu_addr{cpu_addr_}, | ||
| 36 | is_allocated{is_allocated_} {} | ||
| 37 | |||
| 38 | constexpr VAddr StartAddr() const { | ||
| 39 | return start_addr; | ||
| 40 | } | ||
| 41 | |||
| 42 | constexpr VAddr EndAddr() const { | ||
| 43 | return end_addr; | ||
| 44 | } | ||
| 45 | |||
| 46 | constexpr std::size_t Size() const { | ||
| 47 | return end_addr - start_addr; | ||
| 48 | } | ||
| 49 | |||
| 50 | constexpr VAddr CpuAddr() const { | ||
| 51 | return cpu_addr; | ||
| 52 | } | ||
| 53 | |||
| 54 | constexpr bool IsAllocated() const { | ||
| 55 | return is_allocated; | ||
| 56 | } | ||
| 57 | |||
| 58 | private: | ||
| 59 | GPUVAddr start_addr{}; | ||
| 60 | GPUVAddr end_addr{}; | ||
| 61 | VAddr cpu_addr{}; | ||
| 62 | bool is_allocated{}; | ||
| 63 | }; | ||
| 64 | |||
| 65 | struct IoctlSetNvmapFD { | 26 | struct IoctlSetNvmapFD { |
| 66 | s32_le nvmap_fd{}; | 27 | s32_le nvmap_fd{}; |
| 67 | }; | 28 | }; |
| @@ -154,17 +115,11 @@ protected: | |||
| 154 | NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); | 115 | NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); |
| 155 | NvResult SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output); | 116 | NvResult SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output); |
| 156 | 117 | ||
| 157 | std::optional<BufferMap> FindBufferMap(GPUVAddr gpu_addr) const; | ||
| 158 | void AddBufferMap(GPUVAddr gpu_addr, std::size_t size, VAddr cpu_addr, bool is_allocated); | ||
| 159 | std::optional<std::size_t> RemoveBufferMap(GPUVAddr gpu_addr); | ||
| 160 | |||
| 161 | s32_le nvmap_fd{}; | 118 | s32_le nvmap_fd{}; |
| 162 | u32_le submit_timeout{}; | 119 | u32_le submit_timeout{}; |
| 163 | std::shared_ptr<nvmap> nvmap_dev; | 120 | std::shared_ptr<nvmap> nvmap_dev; |
| 164 | SyncpointManager& syncpoint_manager; | 121 | SyncpointManager& syncpoint_manager; |
| 165 | std::array<u32, MaxSyncPoints> device_syncpoints{}; | 122 | std::array<u32, MaxSyncPoints> device_syncpoints{}; |
| 166 | // This is expected to be ordered, therefore we must use a map, not unordered_map | ||
| 167 | std::map<GPUVAddr, BufferMap> buffer_mappings; | ||
| 168 | }; | 123 | }; |
| 169 | }; // namespace Devices | 124 | }; // namespace Devices |
| 170 | } // namespace Service::Nvidia | 125 | } // namespace Service::Nvidia |
diff --git a/src/video_core/command_classes/codecs/vp9.cpp b/src/video_core/command_classes/codecs/vp9.cpp index 902bc2a98..7eecb3991 100644 --- a/src/video_core/command_classes/codecs/vp9.cpp +++ b/src/video_core/command_classes/codecs/vp9.cpp | |||
| @@ -11,6 +11,9 @@ | |||
| 11 | 11 | ||
| 12 | namespace Tegra::Decoder { | 12 | namespace Tegra::Decoder { |
| 13 | namespace { | 13 | namespace { |
| 14 | constexpr u32 diff_update_probability = 252; | ||
| 15 | constexpr u32 frame_sync_code = 0x498342; | ||
| 16 | |||
| 14 | // Default compressed header probabilities once frame context resets | 17 | // Default compressed header probabilities once frame context resets |
| 15 | constexpr Vp9EntropyProbs default_probs{ | 18 | constexpr Vp9EntropyProbs default_probs{ |
| 16 | .y_mode_prob{ | 19 | .y_mode_prob{ |
| @@ -361,8 +364,7 @@ Vp9PictureInfo VP9::GetVp9PictureInfo(const NvdecCommon::NvdecRegisters& state) | |||
| 361 | InsertEntropy(state.vp9_entropy_probs_offset, vp9_info.entropy); | 364 | InsertEntropy(state.vp9_entropy_probs_offset, vp9_info.entropy); |
| 362 | 365 | ||
| 363 | // surface_luma_offset[0:3] contains the address of the reference frame offsets in the following | 366 | // surface_luma_offset[0:3] contains the address of the reference frame offsets in the following |
| 364 | // order: last, golden, altref, current. It may be worthwhile to track the updates done here | 367 | // order: last, golden, altref, current. |
| 365 | // to avoid buffering frame data needed for reference frame updating in the header composition. | ||
| 366 | std::copy(state.surface_luma_offset.begin(), state.surface_luma_offset.begin() + 4, | 368 | std::copy(state.surface_luma_offset.begin(), state.surface_luma_offset.begin() + 4, |
| 367 | vp9_info.frame_offsets.begin()); | 369 | vp9_info.frame_offsets.begin()); |
| 368 | 370 | ||
| @@ -384,33 +386,18 @@ Vp9FrameContainer VP9::GetCurrentFrame(const NvdecCommon::NvdecRegisters& state) | |||
| 384 | gpu.MemoryManager().ReadBlock(state.frame_bitstream_offset, current_frame.bit_stream.data(), | 386 | gpu.MemoryManager().ReadBlock(state.frame_bitstream_offset, current_frame.bit_stream.data(), |
| 385 | current_frame.info.bitstream_size); | 387 | current_frame.info.bitstream_size); |
| 386 | } | 388 | } |
| 387 | // Buffer two frames, saving the last show frame info | 389 | if (!next_frame.bit_stream.empty()) { |
| 388 | if (!next_next_frame.bit_stream.empty()) { | ||
| 389 | Vp9FrameContainer temp{ | 390 | Vp9FrameContainer temp{ |
| 390 | .info = current_frame.info, | 391 | .info = current_frame.info, |
| 391 | .bit_stream = std::move(current_frame.bit_stream), | 392 | .bit_stream = std::move(current_frame.bit_stream), |
| 392 | }; | 393 | }; |
| 393 | next_next_frame.info.show_frame = current_frame.info.last_frame_shown; | 394 | next_frame.info.show_frame = current_frame.info.last_frame_shown; |
| 394 | current_frame.info = next_next_frame.info; | 395 | current_frame.info = next_frame.info; |
| 395 | current_frame.bit_stream = std::move(next_next_frame.bit_stream); | 396 | current_frame.bit_stream = std::move(next_frame.bit_stream); |
| 396 | next_next_frame = std::move(temp); | 397 | next_frame = std::move(temp); |
| 397 | |||
| 398 | if (!next_frame.bit_stream.empty()) { | ||
| 399 | Vp9FrameContainer temp2{ | ||
| 400 | .info = current_frame.info, | ||
| 401 | .bit_stream = std::move(current_frame.bit_stream), | ||
| 402 | }; | ||
| 403 | next_frame.info.show_frame = current_frame.info.last_frame_shown; | ||
| 404 | current_frame.info = next_frame.info; | ||
| 405 | current_frame.bit_stream = std::move(next_frame.bit_stream); | ||
| 406 | next_frame = std::move(temp2); | ||
| 407 | } else { | ||
| 408 | next_frame.info = current_frame.info; | ||
| 409 | next_frame.bit_stream = std::move(current_frame.bit_stream); | ||
| 410 | } | ||
| 411 | } else { | 398 | } else { |
| 412 | next_next_frame.info = current_frame.info; | 399 | next_frame.info = current_frame.info; |
| 413 | next_next_frame.bit_stream = std::move(current_frame.bit_stream); | 400 | next_frame.bit_stream = std::move(current_frame.bit_stream); |
| 414 | } | 401 | } |
| 415 | return current_frame; | 402 | return current_frame; |
| 416 | } | 403 | } |
| @@ -613,86 +600,64 @@ VpxBitStreamWriter VP9::ComposeUncompressedHeader() { | |||
| 613 | 600 | ||
| 614 | // Reset context | 601 | // Reset context |
| 615 | prev_frame_probs = default_probs; | 602 | prev_frame_probs = default_probs; |
| 616 | swap_next_golden = false; | 603 | swap_ref_indices = false; |
| 617 | loop_filter_ref_deltas.fill(0); | 604 | loop_filter_ref_deltas.fill(0); |
| 618 | loop_filter_mode_deltas.fill(0); | 605 | loop_filter_mode_deltas.fill(0); |
| 619 | 606 | frame_ctxs.fill(default_probs); | |
| 620 | // allow frames offsets to stabilize before checking for golden frames | ||
| 621 | grace_period = 4; | ||
| 622 | |||
| 623 | // On key frames, all frame slots are set to the current frame, | ||
| 624 | // so the value of the selected slot doesn't really matter. | ||
| 625 | frame_ctxs.fill({current_frame_number, false, default_probs}); | ||
| 626 | 607 | ||
| 627 | // intra only, meaning the frame can be recreated with no other references | 608 | // intra only, meaning the frame can be recreated with no other references |
| 628 | current_frame_info.intra_only = true; | 609 | current_frame_info.intra_only = true; |
| 629 | |||
| 630 | } else { | 610 | } else { |
| 631 | |||
| 632 | if (!current_frame_info.show_frame) { | 611 | if (!current_frame_info.show_frame) { |
| 633 | uncomp_writer.WriteBit(current_frame_info.intra_only); | 612 | uncomp_writer.WriteBit(current_frame_info.intra_only); |
| 634 | if (!current_frame_info.last_frame_was_key) { | ||
| 635 | swap_next_golden = !swap_next_golden; | ||
| 636 | } | ||
| 637 | } else { | 613 | } else { |
| 638 | current_frame_info.intra_only = false; | 614 | current_frame_info.intra_only = false; |
| 639 | } | 615 | } |
| 640 | if (!current_frame_info.error_resilient_mode) { | 616 | if (!current_frame_info.error_resilient_mode) { |
| 641 | uncomp_writer.WriteU(0, 2); // Reset frame context. | 617 | uncomp_writer.WriteU(0, 2); // Reset frame context. |
| 642 | } | 618 | } |
| 643 | 619 | const auto& curr_offsets = current_frame_info.frame_offsets; | |
| 644 | // Last, Golden, Altref frames | 620 | const auto& next_offsets = next_frame.info.frame_offsets; |
| 645 | std::array<s32, 3> ref_frame_index{0, 1, 2}; | 621 | const bool ref_frames_different = curr_offsets[1] != curr_offsets[2]; |
| 646 | 622 | const bool next_references_swap = | |
| 647 | // Set when next frame is hidden | 623 | (next_offsets[1] == curr_offsets[2]) || (next_offsets[2] == curr_offsets[1]); |
| 648 | // altref and golden references are swapped | 624 | const bool needs_ref_swap = ref_frames_different && next_references_swap; |
| 649 | if (swap_next_golden) { | 625 | if (needs_ref_swap) { |
| 650 | ref_frame_index = std::array<s32, 3>{0, 2, 1}; | 626 | swap_ref_indices = !swap_ref_indices; |
| 651 | } | 627 | } |
| 652 | 628 | union { | |
| 653 | // update Last Frame | 629 | u32 raw; |
| 654 | u64 refresh_frame_flags = 1; | 630 | BitField<0, 1, u32> refresh_last; |
| 655 | 631 | BitField<1, 2, u32> refresh_golden; | |
| 656 | // golden frame may refresh, determined if the next golden frame offset is changed | 632 | BitField<2, 1, u32> refresh_alt; |
| 657 | bool golden_refresh = false; | 633 | } refresh_frame_flags; |
| 658 | if (grace_period <= 0) { | 634 | |
| 659 | for (s32 index = 1; index < 3; ++index) { | 635 | refresh_frame_flags.raw = 0; |
| 660 | if (current_frame_info.frame_offsets[index] != | 636 | for (u32 index = 0; index < 3; ++index) { |
| 661 | next_frame.info.frame_offsets[index]) { | 637 | // Refresh indices that use the current frame as an index |
| 662 | current_frame_info.refresh_frame[index] = true; | 638 | if (curr_offsets[3] == next_offsets[index]) { |
| 663 | golden_refresh = true; | 639 | refresh_frame_flags.raw |= 1u << index; |
| 664 | grace_period = 3; | ||
| 665 | } | ||
| 666 | } | 640 | } |
| 667 | } | 641 | } |
| 668 | 642 | if (swap_ref_indices) { | |
| 669 | if (current_frame_info.show_frame && | 643 | const u32 temp = refresh_frame_flags.refresh_golden; |
| 670 | (!next_frame.info.show_frame || next_frame.info.is_key_frame)) { | 644 | refresh_frame_flags.refresh_golden.Assign(refresh_frame_flags.refresh_alt.Value()); |
| 671 | // Update golden frame | 645 | refresh_frame_flags.refresh_alt.Assign(temp); |
| 672 | refresh_frame_flags = swap_next_golden ? 2 : 4; | ||
| 673 | } | ||
| 674 | |||
| 675 | if (!current_frame_info.show_frame) { | ||
| 676 | // Update altref | ||
| 677 | refresh_frame_flags = swap_next_golden ? 2 : 4; | ||
| 678 | } else if (golden_refresh) { | ||
| 679 | refresh_frame_flags = 3; | ||
| 680 | } | 646 | } |
| 681 | |||
| 682 | if (current_frame_info.intra_only) { | 647 | if (current_frame_info.intra_only) { |
| 683 | uncomp_writer.WriteU(frame_sync_code, 24); | 648 | uncomp_writer.WriteU(frame_sync_code, 24); |
| 684 | uncomp_writer.WriteU(static_cast<s32>(refresh_frame_flags), 8); | 649 | uncomp_writer.WriteU(refresh_frame_flags.raw, 8); |
| 685 | uncomp_writer.WriteU(current_frame_info.frame_size.width - 1, 16); | 650 | uncomp_writer.WriteU(current_frame_info.frame_size.width - 1, 16); |
| 686 | uncomp_writer.WriteU(current_frame_info.frame_size.height - 1, 16); | 651 | uncomp_writer.WriteU(current_frame_info.frame_size.height - 1, 16); |
| 687 | uncomp_writer.WriteBit(false); // Render and frame size different. | 652 | uncomp_writer.WriteBit(false); // Render and frame size different. |
| 688 | } else { | 653 | } else { |
| 689 | uncomp_writer.WriteU(static_cast<s32>(refresh_frame_flags), 8); | 654 | const bool swap_indices = needs_ref_swap ^ swap_ref_indices; |
| 690 | 655 | const auto ref_frame_index = swap_indices ? std::array{0, 2, 1} : std::array{0, 1, 2}; | |
| 691 | for (s32 index = 1; index < 4; index++) { | 656 | uncomp_writer.WriteU(refresh_frame_flags.raw, 8); |
| 657 | for (size_t index = 1; index < 4; index++) { | ||
| 692 | uncomp_writer.WriteU(ref_frame_index[index - 1], 3); | 658 | uncomp_writer.WriteU(ref_frame_index[index - 1], 3); |
| 693 | uncomp_writer.WriteU(current_frame_info.ref_frame_sign_bias[index], 1); | 659 | uncomp_writer.WriteU(current_frame_info.ref_frame_sign_bias[index], 1); |
| 694 | } | 660 | } |
| 695 | |||
| 696 | uncomp_writer.WriteBit(true); // Frame size with refs. | 661 | uncomp_writer.WriteBit(true); // Frame size with refs. |
| 697 | uncomp_writer.WriteBit(false); // Render and frame size different. | 662 | uncomp_writer.WriteBit(false); // Render and frame size different. |
| 698 | uncomp_writer.WriteBit(current_frame_info.allow_high_precision_mv); | 663 | uncomp_writer.WriteBit(current_frame_info.allow_high_precision_mv); |
| @@ -714,10 +679,9 @@ VpxBitStreamWriter VP9::ComposeUncompressedHeader() { | |||
| 714 | frame_ctx_idx = 1; | 679 | frame_ctx_idx = 1; |
| 715 | } | 680 | } |
| 716 | 681 | ||
| 717 | uncomp_writer.WriteU(frame_ctx_idx, 2); // Frame context index. | 682 | uncomp_writer.WriteU(frame_ctx_idx, 2); // Frame context index. |
| 718 | prev_frame_probs = | 683 | prev_frame_probs = frame_ctxs[frame_ctx_idx]; // reference probabilities for compressed header |
| 719 | frame_ctxs[frame_ctx_idx].probs; // reference probabilities for compressed header | 684 | frame_ctxs[frame_ctx_idx] = current_frame_info.entropy; |
| 720 | frame_ctxs[frame_ctx_idx] = {current_frame_number, false, current_frame_info.entropy}; | ||
| 721 | 685 | ||
| 722 | uncomp_writer.WriteU(current_frame_info.first_level, 6); | 686 | uncomp_writer.WriteU(current_frame_info.first_level, 6); |
| 723 | uncomp_writer.WriteU(current_frame_info.sharpness_level, 3); | 687 | uncomp_writer.WriteU(current_frame_info.sharpness_level, 3); |
| @@ -812,7 +776,6 @@ const std::vector<u8>& VP9::ComposeFrameHeader(const NvdecCommon::NvdecRegisters | |||
| 812 | current_frame_info = curr_frame.info; | 776 | current_frame_info = curr_frame.info; |
| 813 | bitstream = std::move(curr_frame.bit_stream); | 777 | bitstream = std::move(curr_frame.bit_stream); |
| 814 | } | 778 | } |
| 815 | |||
| 816 | // The uncompressed header routine sets PrevProb parameters needed for the compressed header | 779 | // The uncompressed header routine sets PrevProb parameters needed for the compressed header |
| 817 | auto uncomp_writer = ComposeUncompressedHeader(); | 780 | auto uncomp_writer = ComposeUncompressedHeader(); |
| 818 | std::vector<u8> compressed_header = ComposeCompressedHeader(); | 781 | std::vector<u8> compressed_header = ComposeCompressedHeader(); |
| @@ -828,13 +791,6 @@ const std::vector<u8>& VP9::ComposeFrameHeader(const NvdecCommon::NvdecRegisters | |||
| 828 | frame.begin() + uncompressed_header.size()); | 791 | frame.begin() + uncompressed_header.size()); |
| 829 | std::copy(bitstream.begin(), bitstream.end(), | 792 | std::copy(bitstream.begin(), bitstream.end(), |
| 830 | frame.begin() + uncompressed_header.size() + compressed_header.size()); | 793 | frame.begin() + uncompressed_header.size() + compressed_header.size()); |
| 831 | |||
| 832 | // keep track of frame number | ||
| 833 | current_frame_number++; | ||
| 834 | grace_period--; | ||
| 835 | |||
| 836 | // don't display hidden frames | ||
| 837 | hidden = !current_frame_info.show_frame; | ||
| 838 | return frame; | 794 | return frame; |
| 839 | } | 795 | } |
| 840 | 796 | ||
diff --git a/src/video_core/command_classes/codecs/vp9.h b/src/video_core/command_classes/codecs/vp9.h index 8396c8105..e6e9fc17e 100644 --- a/src/video_core/command_classes/codecs/vp9.h +++ b/src/video_core/command_classes/codecs/vp9.h | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | 14 | ||
| 15 | namespace Tegra { | 15 | namespace Tegra { |
| 16 | class GPU; | 16 | class GPU; |
| 17 | enum class FrameType { KeyFrame = 0, InterFrame = 1 }; | ||
| 18 | namespace Decoder { | 17 | namespace Decoder { |
| 19 | 18 | ||
| 20 | /// The VpxRangeEncoder, and VpxBitStreamWriter classes are used to compose the | 19 | /// The VpxRangeEncoder, and VpxBitStreamWriter classes are used to compose the |
| @@ -124,7 +123,7 @@ public: | |||
| 124 | 123 | ||
| 125 | /// Returns true if the most recent frame was a hidden frame. | 124 | /// Returns true if the most recent frame was a hidden frame. |
| 126 | [[nodiscard]] bool WasFrameHidden() const { | 125 | [[nodiscard]] bool WasFrameHidden() const { |
| 127 | return hidden; | 126 | return !current_frame_info.show_frame; |
| 128 | } | 127 | } |
| 129 | 128 | ||
| 130 | private: | 129 | private: |
| @@ -178,19 +177,12 @@ private: | |||
| 178 | std::array<s8, 4> loop_filter_ref_deltas{}; | 177 | std::array<s8, 4> loop_filter_ref_deltas{}; |
| 179 | std::array<s8, 2> loop_filter_mode_deltas{}; | 178 | std::array<s8, 2> loop_filter_mode_deltas{}; |
| 180 | 179 | ||
| 181 | bool hidden = false; | ||
| 182 | s64 current_frame_number = -2; // since we buffer 2 frames | ||
| 183 | s32 grace_period = 6; // frame offsets need to stabilize | ||
| 184 | std::array<FrameContexts, 4> frame_ctxs{}; | ||
| 185 | Vp9FrameContainer next_frame{}; | 180 | Vp9FrameContainer next_frame{}; |
| 186 | Vp9FrameContainer next_next_frame{}; | 181 | std::array<Vp9EntropyProbs, 4> frame_ctxs{}; |
| 187 | bool swap_next_golden{}; | 182 | bool swap_ref_indices{}; |
| 188 | 183 | ||
| 189 | Vp9PictureInfo current_frame_info{}; | 184 | Vp9PictureInfo current_frame_info{}; |
| 190 | Vp9EntropyProbs prev_frame_probs{}; | 185 | Vp9EntropyProbs prev_frame_probs{}; |
| 191 | |||
| 192 | s32 diff_update_probability = 252; | ||
| 193 | s32 frame_sync_code = 0x498342; | ||
| 194 | }; | 186 | }; |
| 195 | 187 | ||
| 196 | } // namespace Decoder | 188 | } // namespace Decoder |
diff --git a/src/video_core/command_classes/codecs/vp9_types.h b/src/video_core/command_classes/codecs/vp9_types.h index 2da14f3ca..6820afa26 100644 --- a/src/video_core/command_classes/codecs/vp9_types.h +++ b/src/video_core/command_classes/codecs/vp9_types.h | |||
| @@ -296,12 +296,6 @@ struct RefPoolElement { | |||
| 296 | bool refresh{}; | 296 | bool refresh{}; |
| 297 | }; | 297 | }; |
| 298 | 298 | ||
| 299 | struct FrameContexts { | ||
| 300 | s64 from; | ||
| 301 | bool adapted; | ||
| 302 | Vp9EntropyProbs probs; | ||
| 303 | }; | ||
| 304 | |||
| 305 | #define ASSERT_POSITION(field_name, position) \ | 299 | #define ASSERT_POSITION(field_name, position) \ |
| 306 | static_assert(offsetof(Vp9EntropyProbs, field_name) == position, \ | 300 | static_assert(offsetof(Vp9EntropyProbs, field_name) == position, \ |
| 307 | "Field " #field_name " has invalid position") | 301 | "Field " #field_name " has invalid position") |