yuzu-emu
/
yuzu-mainline
Archived
1
0
Fork 0

Merge pull request #4867 from lioncash/vp9

VP9: Minor interface changes and safety improvements
This commit is contained in:
bunnei 2020-10-29 21:33:27 -07:00 committed by GitHub
commit 131a75b65d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 91 additions and 71 deletions

View File

@ -21,6 +21,12 @@ public:
explicit Stream(); explicit Stream();
~Stream(); ~Stream();
Stream(const Stream&) = delete;
Stream& operator=(const Stream&) = delete;
Stream(Stream&&) = default;
Stream& operator=(Stream&&) = default;
/// Reposition bitstream "cursor" to the specified offset from origin /// Reposition bitstream "cursor" to the specified offset from origin
void Seek(s32 offset, SeekOrigin origin); void Seek(s32 offset, SeekOrigin origin);
@ -30,15 +36,15 @@ public:
/// Writes byte at current position /// Writes byte at current position
void WriteByte(u8 byte); void WriteByte(u8 byte);
std::size_t GetPosition() const { [[nodiscard]] std::size_t GetPosition() const {
return position; return position;
} }
std::vector<u8>& GetBuffer() { [[nodiscard]] std::vector<u8>& GetBuffer() {
return buffer; return buffer;
} }
const std::vector<u8>& GetBuffer() const { [[nodiscard]] const std::vector<u8>& GetBuffer() const {
return buffer; return buffer;
} }

View File

@ -197,6 +197,60 @@ constexpr std::array<s32, 254> map_lut{
230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 18, 242, 243, 244, 245, 246, 247, 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, 248, 249, 250, 251, 252, 253, 19,
}; };
// 6.2.14 Tile size calculation
[[nodiscard]] s32 CalcMinLog2TileCols(s32 frame_width) {
const s32 sb64_cols = (frame_width + 63) / 64;
s32 min_log2 = 0;
while ((64 << min_log2) < sb64_cols) {
min_log2++;
}
return min_log2;
}
[[nodiscard]] s32 CalcMaxLog2TileCols(s32 frame_width) {
const s32 sb64_cols = (frame_width + 63) / 64;
s32 max_log2 = 1;
while ((sb64_cols >> max_log2) >= 4) {
max_log2++;
}
return max_log2 - 1;
}
// Recenters probability. Based on section 6.3.6 of VP9 Specification
[[nodiscard]] s32 RecenterNonNeg(s32 new_prob, s32 old_prob) {
if (new_prob > old_prob * 2) {
return new_prob;
}
if (new_prob >= old_prob) {
return (new_prob - old_prob) * 2;
}
return (old_prob - new_prob) * 2 - 1;
}
// Adjusts old_prob depending on new_prob. Based on section 6.3.5 of VP9 Specification
[[nodiscard]] s32 RemapProbability(s32 new_prob, s32 old_prob) {
new_prob--;
old_prob--;
std::size_t index{};
if (old_prob * 2 <= 0xff) {
index = static_cast<std::size_t>(std::max(0, RecenterNonNeg(new_prob, old_prob) - 1));
} else {
index = static_cast<std::size_t>(
std::max(0, RecenterNonNeg(0xff - 1 - new_prob, 0xff - 1 - old_prob) - 1));
}
return map_lut[index];
}
} // Anonymous namespace } // Anonymous namespace
VP9::VP9(GPU& gpu) : gpu(gpu) {} VP9::VP9(GPU& gpu) : gpu(gpu) {}
@ -236,32 +290,6 @@ void VP9::WriteProbabilityDelta(VpxRangeEncoder& writer, u8 new_prob, u8 old_pro
EncodeTermSubExp(writer, delta); EncodeTermSubExp(writer, delta);
} }
s32 VP9::RemapProbability(s32 new_prob, s32 old_prob) {
new_prob--;
old_prob--;
std::size_t index{};
if (old_prob * 2 <= 0xff) {
index = static_cast<std::size_t>(std::max(0, RecenterNonNeg(new_prob, old_prob) - 1));
} else {
index = static_cast<std::size_t>(
std::max(0, RecenterNonNeg(0xff - 1 - new_prob, 0xff - 1 - old_prob) - 1));
}
return map_lut[index];
}
s32 VP9::RecenterNonNeg(s32 new_prob, s32 old_prob) {
if (new_prob > old_prob * 2) {
return new_prob;
} else if (new_prob >= old_prob) {
return (new_prob - old_prob) * 2;
} else {
return (old_prob - new_prob) * 2 - 1;
}
}
void VP9::EncodeTermSubExp(VpxRangeEncoder& writer, s32 value) { void VP9::EncodeTermSubExp(VpxRangeEncoder& writer, s32 value) {
if (WriteLessThan(writer, value, 16)) { if (WriteLessThan(writer, value, 16)) {
writer.Write(value, 4); writer.Write(value, 4);
@ -361,28 +389,6 @@ void VP9::WriteMvProbabilityUpdate(VpxRangeEncoder& writer, u8 new_prob, u8 old_
} }
} }
s32 VP9::CalcMinLog2TileCols(s32 frame_width) {
const s32 sb64_cols = (frame_width + 63) / 64;
s32 min_log2 = 0;
while ((64 << min_log2) < sb64_cols) {
min_log2++;
}
return min_log2;
}
s32 VP9::CalcMaxLog2TileCols(s32 frameWidth) {
const s32 sb64_cols = (frameWidth + 63) / 64;
s32 max_log2 = 1;
while ((sb64_cols >> max_log2) >= 4) {
max_log2++;
}
return max_log2 - 1;
}
Vp9PictureInfo VP9::GetVp9PictureInfo(const NvdecCommon::NvdecRegisters& state) { Vp9PictureInfo VP9::GetVp9PictureInfo(const NvdecCommon::NvdecRegisters& state) {
PictureInfo picture_info{}; PictureInfo picture_info{};
gpu.MemoryManager().ReadBlock(state.picture_info_offset, &picture_info, sizeof(PictureInfo)); gpu.MemoryManager().ReadBlock(state.picture_info_offset, &picture_info, sizeof(PictureInfo));

View File

@ -25,6 +25,12 @@ public:
VpxRangeEncoder(); VpxRangeEncoder();
~VpxRangeEncoder(); ~VpxRangeEncoder();
VpxRangeEncoder(const VpxRangeEncoder&) = delete;
VpxRangeEncoder& operator=(const VpxRangeEncoder&) = delete;
VpxRangeEncoder(VpxRangeEncoder&&) = default;
VpxRangeEncoder& operator=(VpxRangeEncoder&&) = default;
/// Writes the rightmost value_size bits from value into the stream /// Writes the rightmost value_size bits from value into the stream
void Write(s32 value, s32 value_size); void Write(s32 value, s32 value_size);
@ -37,11 +43,11 @@ public:
/// Signal the end of the bitstream /// Signal the end of the bitstream
void End(); void End();
std::vector<u8>& GetBuffer() { [[nodiscard]] std::vector<u8>& GetBuffer() {
return base_stream.GetBuffer(); return base_stream.GetBuffer();
} }
const std::vector<u8>& GetBuffer() const { [[nodiscard]] const std::vector<u8>& GetBuffer() const {
return base_stream.GetBuffer(); return base_stream.GetBuffer();
} }
@ -59,6 +65,12 @@ public:
VpxBitStreamWriter(); VpxBitStreamWriter();
~VpxBitStreamWriter(); ~VpxBitStreamWriter();
VpxBitStreamWriter(const VpxBitStreamWriter&) = delete;
VpxBitStreamWriter& operator=(const VpxBitStreamWriter&) = delete;
VpxBitStreamWriter(VpxBitStreamWriter&&) = default;
VpxBitStreamWriter& operator=(VpxBitStreamWriter&&) = default;
/// Write an unsigned integer value /// Write an unsigned integer value
void WriteU(u32 value, u32 value_size); void WriteU(u32 value, u32 value_size);
@ -75,10 +87,10 @@ public:
void Flush(); void Flush();
/// Returns byte_array /// Returns byte_array
std::vector<u8>& GetByteArray(); [[nodiscard]] std::vector<u8>& GetByteArray();
/// Returns const byte_array /// Returns const byte_array
const std::vector<u8>& GetByteArray() const; [[nodiscard]] const std::vector<u8>& GetByteArray() const;
private: private:
/// Write bit_count bits from value into buffer /// Write bit_count bits from value into buffer
@ -99,12 +111,18 @@ public:
explicit VP9(GPU& gpu); explicit VP9(GPU& gpu);
~VP9(); ~VP9();
VP9(const VP9&) = delete;
VP9& operator=(const VP9&) = delete;
VP9(VP9&&) = default;
VP9& operator=(VP9&&) = delete;
/// Composes the VP9 frame from the GPU state information. Based on the official VP9 spec /// Composes the VP9 frame from the GPU state information. Based on the official VP9 spec
/// documentation /// documentation
std::vector<u8>& ComposeFrameHeader(NvdecCommon::NvdecRegisters& state); std::vector<u8>& ComposeFrameHeader(NvdecCommon::NvdecRegisters& state);
/// Returns true if the most recent frame was a hidden frame. /// Returns true if the most recent frame was a hidden frame.
bool WasFrameHidden() const { [[nodiscard]] bool WasFrameHidden() const {
return hidden; return hidden;
} }
@ -121,12 +139,6 @@ private:
/// Generates compressed header probability deltas in the bitstream writer /// Generates compressed header probability deltas in the bitstream writer
void WriteProbabilityDelta(VpxRangeEncoder& writer, u8 new_prob, u8 old_prob); void WriteProbabilityDelta(VpxRangeEncoder& writer, u8 new_prob, u8 old_prob);
/// Adjusts old_prob depending on new_prob. Based on section 6.3.5 of VP9 Specification
s32 RemapProbability(s32 new_prob, s32 old_prob);
/// Recenters probability. Based on section 6.3.6 of VP9 Specification
s32 RecenterNonNeg(s32 new_prob, s32 old_prob);
/// Inverse of 6.3.4 Decode term subexp /// Inverse of 6.3.4 Decode term subexp
void EncodeTermSubExp(VpxRangeEncoder& writer, s32 value); void EncodeTermSubExp(VpxRangeEncoder& writer, s32 value);
@ -146,22 +158,18 @@ private:
/// Write motion vector probability updates. 6.3.17 in the spec /// Write motion vector probability updates. 6.3.17 in the spec
void WriteMvProbabilityUpdate(VpxRangeEncoder& writer, u8 new_prob, u8 old_prob); void WriteMvProbabilityUpdate(VpxRangeEncoder& writer, u8 new_prob, u8 old_prob);
/// 6.2.14 Tile size calculation
s32 CalcMinLog2TileCols(s32 frame_width);
s32 CalcMaxLog2TileCols(s32 frame_width);
/// Returns VP9 information from NVDEC provided offset and size /// Returns VP9 information from NVDEC provided offset and size
Vp9PictureInfo GetVp9PictureInfo(const NvdecCommon::NvdecRegisters& state); [[nodiscard]] Vp9PictureInfo GetVp9PictureInfo(const NvdecCommon::NvdecRegisters& state);
/// Read and convert NVDEC provided entropy probs to Vp9EntropyProbs struct /// Read and convert NVDEC provided entropy probs to Vp9EntropyProbs struct
void InsertEntropy(u64 offset, Vp9EntropyProbs& dst); void InsertEntropy(u64 offset, Vp9EntropyProbs& dst);
/// Returns frame to be decoded after buffering /// Returns frame to be decoded after buffering
Vp9FrameContainer GetCurrentFrame(const NvdecCommon::NvdecRegisters& state); [[nodiscard]] Vp9FrameContainer GetCurrentFrame(const NvdecCommon::NvdecRegisters& state);
/// Use NVDEC providied information to compose the headers for the current frame /// Use NVDEC providied information to compose the headers for the current frame
std::vector<u8> ComposeCompressedHeader(); [[nodiscard]] std::vector<u8> ComposeCompressedHeader();
VpxBitStreamWriter ComposeUncompressedHeader(); [[nodiscard]] VpxBitStreamWriter ComposeUncompressedHeader();
GPU& gpu; GPU& gpu;
std::vector<u8> frame; std::vector<u8> frame;
@ -169,7 +177,7 @@ private:
std::array<s8, 4> loop_filter_ref_deltas{}; std::array<s8, 4> loop_filter_ref_deltas{};
std::array<s8, 2> loop_filter_mode_deltas{}; std::array<s8, 2> loop_filter_mode_deltas{};
bool hidden; bool hidden = false;
s64 current_frame_number = -2; // since we buffer 2 frames s64 current_frame_number = -2; // since we buffer 2 frames
s32 grace_period = 6; // frame offsets need to stabilize s32 grace_period = 6; // frame offsets need to stabilize
std::array<FrameContexts, 4> frame_ctxs{}; std::array<FrameContexts, 4> frame_ctxs{};