|
|
@ -9,7 +9,7 @@ |
|
|
#include "video_core/memory_manager.h"
|
|
|
#include "video_core/memory_manager.h"
|
|
|
|
|
|
|
|
|
namespace Tegra::Decoder { |
|
|
namespace Tegra::Decoder { |
|
|
|
|
|
|
|
|
|
|
|
namespace { |
|
|
// Default compressed header probabilities once frame context resets
|
|
|
// Default compressed header probabilities once frame context resets
|
|
|
constexpr Vp9EntropyProbs default_probs{ |
|
|
constexpr Vp9EntropyProbs default_probs{ |
|
|
.y_mode_prob{ |
|
|
.y_mode_prob{ |
|
|
@ -170,6 +170,35 @@ constexpr Vp9EntropyProbs default_probs{ |
|
|
.high_precision{128, 128}, |
|
|
.high_precision{128, 128}, |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
constexpr std::array<s32, 256> norm_lut{ |
|
|
|
|
|
0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
|
|
|
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
constexpr std::array<s32, 254> map_lut{ |
|
|
|
|
|
20, 21, 22, 23, 24, 25, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, |
|
|
|
|
|
1, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 2, 50, 51, 52, 53, 54, |
|
|
|
|
|
55, 56, 57, 58, 59, 60, 61, 3, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, |
|
|
|
|
|
73, 4, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 5, 86, 87, 88, 89, |
|
|
|
|
|
90, 91, 92, 93, 94, 95, 96, 97, 6, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, |
|
|
|
|
|
108, 109, 7, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 8, 122, 123, 124, |
|
|
|
|
|
125, 126, 127, 128, 129, 130, 131, 132, 133, 9, 134, 135, 136, 137, 138, 139, 140, 141, 142, |
|
|
|
|
|
143, 144, 145, 10, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 11, 158, 159, |
|
|
|
|
|
160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 12, 170, 171, 172, 173, 174, 175, 176, 177, |
|
|
|
|
|
178, 179, 180, 181, 13, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 14, 194, |
|
|
|
|
|
195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 15, 206, 207, 208, 209, 210, 211, 212, |
|
|
|
|
|
213, 214, 215, 216, 217, 16, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 17, |
|
|
|
|
|
230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 18, 242, 243, 244, 245, 246, 247, |
|
|
|
|
|
248, 249, 250, 251, 252, 253, 19, |
|
|
|
|
|
}; |
|
|
|
|
|
} // Anonymous namespace
|
|
|
|
|
|
|
|
|
VP9::VP9(GPU& gpu) : gpu(gpu) {} |
|
|
VP9::VP9(GPU& gpu) : gpu(gpu) {} |
|
|
|
|
|
|
|
|
VP9::~VP9() = default; |
|
|
VP9::~VP9() = default; |
|
|
@ -379,14 +408,14 @@ Vp9FrameContainer VP9::GetCurrentFrame(const NvdecCommon::NvdecRegisters& state) |
|
|
Vp9FrameContainer frame{}; |
|
|
Vp9FrameContainer frame{}; |
|
|
{ |
|
|
{ |
|
|
gpu.SyncGuestHost(); |
|
|
gpu.SyncGuestHost(); |
|
|
frame.info = std::move(GetVp9PictureInfo(state)); |
|
|
|
|
|
|
|
|
frame.info = GetVp9PictureInfo(state); |
|
|
|
|
|
|
|
|
frame.bit_stream.resize(frame.info.bitstream_size); |
|
|
frame.bit_stream.resize(frame.info.bitstream_size); |
|
|
gpu.MemoryManager().ReadBlock(state.frame_bitstream_offset, frame.bit_stream.data(), |
|
|
gpu.MemoryManager().ReadBlock(state.frame_bitstream_offset, frame.bit_stream.data(), |
|
|
frame.info.bitstream_size); |
|
|
frame.info.bitstream_size); |
|
|
} |
|
|
} |
|
|
// Buffer two frames, saving the last show frame info
|
|
|
// Buffer two frames, saving the last show frame info
|
|
|
if (next_next_frame.bit_stream.size() != 0) { |
|
|
|
|
|
|
|
|
if (!next_next_frame.bit_stream.empty()) { |
|
|
Vp9FrameContainer temp{ |
|
|
Vp9FrameContainer temp{ |
|
|
.info = frame.info, |
|
|
.info = frame.info, |
|
|
.bit_stream = frame.bit_stream, |
|
|
.bit_stream = frame.bit_stream, |
|
|
@ -396,15 +425,15 @@ Vp9FrameContainer VP9::GetCurrentFrame(const NvdecCommon::NvdecRegisters& state) |
|
|
frame.bit_stream = next_next_frame.bit_stream; |
|
|
frame.bit_stream = next_next_frame.bit_stream; |
|
|
next_next_frame = std::move(temp); |
|
|
next_next_frame = std::move(temp); |
|
|
|
|
|
|
|
|
if (next_frame.bit_stream.size() != 0) { |
|
|
|
|
|
Vp9FrameContainer temp{ |
|
|
|
|
|
|
|
|
if (!next_frame.bit_stream.empty()) { |
|
|
|
|
|
Vp9FrameContainer temp2{ |
|
|
.info = frame.info, |
|
|
.info = frame.info, |
|
|
.bit_stream = frame.bit_stream, |
|
|
.bit_stream = frame.bit_stream, |
|
|
}; |
|
|
}; |
|
|
next_frame.info.show_frame = frame.info.last_frame_shown; |
|
|
next_frame.info.show_frame = frame.info.last_frame_shown; |
|
|
frame.info = next_frame.info; |
|
|
frame.info = next_frame.info; |
|
|
frame.bit_stream = next_frame.bit_stream; |
|
|
frame.bit_stream = next_frame.bit_stream; |
|
|
next_frame = std::move(temp); |
|
|
|
|
|
|
|
|
next_frame = std::move(temp2); |
|
|
} else { |
|
|
} else { |
|
|
next_frame.info = frame.info; |
|
|
next_frame.info = frame.info; |
|
|
next_frame.bit_stream = frame.bit_stream; |
|
|
next_frame.bit_stream = frame.bit_stream; |
|
|
@ -605,12 +634,6 @@ std::vector<u8> VP9::ComposeCompressedHeader() { |
|
|
|
|
|
|
|
|
writer.End(); |
|
|
writer.End(); |
|
|
return writer.GetBuffer(); |
|
|
return writer.GetBuffer(); |
|
|
|
|
|
|
|
|
const auto writer_bytearray = writer.GetBuffer(); |
|
|
|
|
|
|
|
|
|
|
|
std::vector<u8> compressed_header(writer_bytearray.size()); |
|
|
|
|
|
std::memcpy(compressed_header.data(), writer_bytearray.data(), writer_bytearray.size()); |
|
|
|
|
|
return compressed_header; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VpxBitStreamWriter VP9::ComposeUncompressedHeader() { |
|
|
VpxBitStreamWriter VP9::ComposeUncompressedHeader() { |
|
|
@ -648,7 +671,6 @@ VpxBitStreamWriter VP9::ComposeUncompressedHeader() { |
|
|
current_frame_info.intra_only = true; |
|
|
current_frame_info.intra_only = true; |
|
|
|
|
|
|
|
|
} else { |
|
|
} else { |
|
|
std::array<s32, 3> ref_frame_index; |
|
|
|
|
|
|
|
|
|
|
|
if (!current_frame_info.show_frame) { |
|
|
if (!current_frame_info.show_frame) { |
|
|
uncomp_writer.WriteBit(current_frame_info.intra_only); |
|
|
uncomp_writer.WriteBit(current_frame_info.intra_only); |
|
|
@ -663,9 +685,9 @@ VpxBitStreamWriter VP9::ComposeUncompressedHeader() { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Last, Golden, Altref frames
|
|
|
// Last, Golden, Altref frames
|
|
|
ref_frame_index = std::array<s32, 3>{0, 1, 2}; |
|
|
|
|
|
|
|
|
std::array<s32, 3> ref_frame_index{0, 1, 2}; |
|
|
|
|
|
|
|
|
// set when next frame is hidden
|
|
|
|
|
|
|
|
|
// Set when next frame is hidden
|
|
|
// altref and golden references are swapped
|
|
|
// altref and golden references are swapped
|
|
|
if (swap_next_golden) { |
|
|
if (swap_next_golden) { |
|
|
ref_frame_index = std::array<s32, 3>{0, 2, 1}; |
|
|
ref_frame_index = std::array<s32, 3>{0, 2, 1}; |
|
|
@ -754,17 +776,19 @@ VpxBitStreamWriter VP9::ComposeUncompressedHeader() { |
|
|
for (std::size_t index = 0; index < current_frame_info.ref_deltas.size(); index++) { |
|
|
for (std::size_t index = 0; index < current_frame_info.ref_deltas.size(); index++) { |
|
|
const s8 old_deltas = loop_filter_ref_deltas[index]; |
|
|
const s8 old_deltas = loop_filter_ref_deltas[index]; |
|
|
const s8 new_deltas = current_frame_info.ref_deltas[index]; |
|
|
const s8 new_deltas = current_frame_info.ref_deltas[index]; |
|
|
|
|
|
const bool differing_delta = old_deltas != new_deltas; |
|
|
|
|
|
|
|
|
loop_filter_delta_update |= |
|
|
|
|
|
(update_loop_filter_ref_deltas[index] = old_deltas != new_deltas); |
|
|
|
|
|
|
|
|
update_loop_filter_ref_deltas[index] = differing_delta; |
|
|
|
|
|
loop_filter_delta_update |= differing_delta; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for (std::size_t index = 0; index < current_frame_info.mode_deltas.size(); index++) { |
|
|
for (std::size_t index = 0; index < current_frame_info.mode_deltas.size(); index++) { |
|
|
const s8 old_deltas = loop_filter_mode_deltas[index]; |
|
|
const s8 old_deltas = loop_filter_mode_deltas[index]; |
|
|
const s8 new_deltas = current_frame_info.mode_deltas[index]; |
|
|
const s8 new_deltas = current_frame_info.mode_deltas[index]; |
|
|
|
|
|
const bool differing_delta = old_deltas != new_deltas; |
|
|
|
|
|
|
|
|
loop_filter_delta_update |= |
|
|
|
|
|
(update_loop_filter_mode_deltas[index] = old_deltas != new_deltas); |
|
|
|
|
|
|
|
|
update_loop_filter_mode_deltas[index] = differing_delta; |
|
|
|
|
|
loop_filter_delta_update |= differing_delta; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
uncomp_writer.WriteBit(loop_filter_delta_update); |
|
|
uncomp_writer.WriteBit(loop_filter_delta_update); |
|
|
@ -829,7 +853,7 @@ std::vector<u8>& VP9::ComposeFrameHeader(NvdecCommon::NvdecRegisters& state) { |
|
|
{ |
|
|
{ |
|
|
Vp9FrameContainer curr_frame = GetCurrentFrame(state); |
|
|
Vp9FrameContainer curr_frame = GetCurrentFrame(state); |
|
|
current_frame_info = curr_frame.info; |
|
|
current_frame_info = curr_frame.info; |
|
|
bitstream = curr_frame.bit_stream; |
|
|
|
|
|
|
|
|
bitstream = std::move(curr_frame.bit_stream); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// The uncompressed header routine sets PrevProb parameters needed for the compressed header
|
|
|
// The uncompressed header routine sets PrevProb parameters needed for the compressed header
|
|
|
|