summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2020-10-29 21:33:27 -0700
committerGravatar GitHub2020-10-29 21:33:27 -0700
commit131a75b65d088686f7b50392f0ee47a34c4a0512 (patch)
treecec8eb2a2267f8c9148380c3a931ae5508878a9c
parentMerge pull request #4831 from lioncash/fmt (diff)
parentcommon/stream: Be explicit with copy and move operators (diff)
downloadyuzu-131a75b65d088686f7b50392f0ee47a34c4a0512.tar.gz
yuzu-131a75b65d088686f7b50392f0ee47a34c4a0512.tar.xz
yuzu-131a75b65d088686f7b50392f0ee47a34c4a0512.zip
Merge pull request #4867 from lioncash/vp9
VP9: Minor interface changes and safety improvements
-rw-r--r--src/common/stream.h12
-rw-r--r--src/video_core/command_classes/codecs/vp9.cpp102
-rw-r--r--src/video_core/command_classes/codecs/vp9.h48
3 files changed, 91 insertions, 71 deletions
diff --git a/src/common/stream.h b/src/common/stream.h
index 2585c16af..0e40692de 100644
--- a/src/common/stream.h
+++ b/src/common/stream.h
@@ -21,6 +21,12 @@ public:
21 explicit Stream(); 21 explicit Stream();
22 ~Stream(); 22 ~Stream();
23 23
24 Stream(const Stream&) = delete;
25 Stream& operator=(const Stream&) = delete;
26
27 Stream(Stream&&) = default;
28 Stream& operator=(Stream&&) = default;
29
24 /// Reposition bitstream "cursor" to the specified offset from origin 30 /// Reposition bitstream "cursor" to the specified offset from origin
25 void Seek(s32 offset, SeekOrigin origin); 31 void Seek(s32 offset, SeekOrigin origin);
26 32
@@ -30,15 +36,15 @@ public:
30 /// Writes byte at current position 36 /// Writes byte at current position
31 void WriteByte(u8 byte); 37 void WriteByte(u8 byte);
32 38
33 std::size_t GetPosition() const { 39 [[nodiscard]] std::size_t GetPosition() const {
34 return position; 40 return position;
35 } 41 }
36 42
37 std::vector<u8>& GetBuffer() { 43 [[nodiscard]] std::vector<u8>& GetBuffer() {
38 return buffer; 44 return buffer;
39 } 45 }
40 46
41 const std::vector<u8>& GetBuffer() const { 47 [[nodiscard]] const std::vector<u8>& GetBuffer() const {
42 return buffer; 48 return buffer;
43 } 49 }
44 50
diff --git a/src/video_core/command_classes/codecs/vp9.cpp b/src/video_core/command_classes/codecs/vp9.cpp
index b3e98aa9f..42520f856 100644
--- a/src/video_core/command_classes/codecs/vp9.cpp
+++ b/src/video_core/command_classes/codecs/vp9.cpp
@@ -197,6 +197,60 @@ constexpr std::array<s32, 254> map_lut{
197 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 18, 242, 243, 244, 245, 246, 247, 197 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 18, 242, 243, 244, 245, 246, 247,
198 248, 249, 250, 251, 252, 253, 19, 198 248, 249, 250, 251, 252, 253, 19,
199}; 199};
200
201// 6.2.14 Tile size calculation
202
203[[nodiscard]] s32 CalcMinLog2TileCols(s32 frame_width) {
204 const s32 sb64_cols = (frame_width + 63) / 64;
205 s32 min_log2 = 0;
206
207 while ((64 << min_log2) < sb64_cols) {
208 min_log2++;
209 }
210
211 return min_log2;
212}
213
214[[nodiscard]] s32 CalcMaxLog2TileCols(s32 frame_width) {
215 const s32 sb64_cols = (frame_width + 63) / 64;
216 s32 max_log2 = 1;
217
218 while ((sb64_cols >> max_log2) >= 4) {
219 max_log2++;
220 }
221
222 return max_log2 - 1;
223}
224
225// Recenters probability. Based on section 6.3.6 of VP9 Specification
226[[nodiscard]] s32 RecenterNonNeg(s32 new_prob, s32 old_prob) {
227 if (new_prob > old_prob * 2) {
228 return new_prob;
229 }
230
231 if (new_prob >= old_prob) {
232 return (new_prob - old_prob) * 2;
233 }
234
235 return (old_prob - new_prob) * 2 - 1;
236}
237
238// Adjusts old_prob depending on new_prob. Based on section 6.3.5 of VP9 Specification
239[[nodiscard]] s32 RemapProbability(s32 new_prob, s32 old_prob) {
240 new_prob--;
241 old_prob--;
242
243 std::size_t index{};
244
245 if (old_prob * 2 <= 0xff) {
246 index = static_cast<std::size_t>(std::max(0, RecenterNonNeg(new_prob, old_prob) - 1));
247 } else {
248 index = static_cast<std::size_t>(
249 std::max(0, RecenterNonNeg(0xff - 1 - new_prob, 0xff - 1 - old_prob) - 1));
250 }
251
252 return map_lut[index];
253}
200} // Anonymous namespace 254} // Anonymous namespace
201 255
202VP9::VP9(GPU& gpu) : gpu(gpu) {} 256VP9::VP9(GPU& gpu) : gpu(gpu) {}
@@ -236,32 +290,6 @@ void VP9::WriteProbabilityDelta(VpxRangeEncoder& writer, u8 new_prob, u8 old_pro
236 EncodeTermSubExp(writer, delta); 290 EncodeTermSubExp(writer, delta);
237} 291}
238 292
239s32 VP9::RemapProbability(s32 new_prob, s32 old_prob) {
240 new_prob--;
241 old_prob--;
242
243 std::size_t index{};
244
245 if (old_prob * 2 <= 0xff) {
246 index = static_cast<std::size_t>(std::max(0, RecenterNonNeg(new_prob, old_prob) - 1));
247 } else {
248 index = static_cast<std::size_t>(
249 std::max(0, RecenterNonNeg(0xff - 1 - new_prob, 0xff - 1 - old_prob) - 1));
250 }
251
252 return map_lut[index];
253}
254
255s32 VP9::RecenterNonNeg(s32 new_prob, s32 old_prob) {
256 if (new_prob > old_prob * 2) {
257 return new_prob;
258 } else if (new_prob >= old_prob) {
259 return (new_prob - old_prob) * 2;
260 } else {
261 return (old_prob - new_prob) * 2 - 1;
262 }
263}
264
265void VP9::EncodeTermSubExp(VpxRangeEncoder& writer, s32 value) { 293void VP9::EncodeTermSubExp(VpxRangeEncoder& writer, s32 value) {
266 if (WriteLessThan(writer, value, 16)) { 294 if (WriteLessThan(writer, value, 16)) {
267 writer.Write(value, 4); 295 writer.Write(value, 4);
@@ -361,28 +389,6 @@ void VP9::WriteMvProbabilityUpdate(VpxRangeEncoder& writer, u8 new_prob, u8 old_
361 } 389 }
362} 390}
363 391
364s32 VP9::CalcMinLog2TileCols(s32 frame_width) {
365 const s32 sb64_cols = (frame_width + 63) / 64;
366 s32 min_log2 = 0;
367
368 while ((64 << min_log2) < sb64_cols) {
369 min_log2++;
370 }
371
372 return min_log2;
373}
374
375s32 VP9::CalcMaxLog2TileCols(s32 frameWidth) {
376 const s32 sb64_cols = (frameWidth + 63) / 64;
377 s32 max_log2 = 1;
378
379 while ((sb64_cols >> max_log2) >= 4) {
380 max_log2++;
381 }
382
383 return max_log2 - 1;
384}
385
386Vp9PictureInfo VP9::GetVp9PictureInfo(const NvdecCommon::NvdecRegisters& state) { 392Vp9PictureInfo VP9::GetVp9PictureInfo(const NvdecCommon::NvdecRegisters& state) {
387 PictureInfo picture_info{}; 393 PictureInfo picture_info{};
388 gpu.MemoryManager().ReadBlock(state.picture_info_offset, &picture_info, sizeof(PictureInfo)); 394 gpu.MemoryManager().ReadBlock(state.picture_info_offset, &picture_info, sizeof(PictureInfo));
diff --git a/src/video_core/command_classes/codecs/vp9.h b/src/video_core/command_classes/codecs/vp9.h
index dc52ddbde..05c9682fa 100644
--- a/src/video_core/command_classes/codecs/vp9.h
+++ b/src/video_core/command_classes/codecs/vp9.h
@@ -25,6 +25,12 @@ public:
25 VpxRangeEncoder(); 25 VpxRangeEncoder();
26 ~VpxRangeEncoder(); 26 ~VpxRangeEncoder();
27 27
28 VpxRangeEncoder(const VpxRangeEncoder&) = delete;
29 VpxRangeEncoder& operator=(const VpxRangeEncoder&) = delete;
30
31 VpxRangeEncoder(VpxRangeEncoder&&) = default;
32 VpxRangeEncoder& operator=(VpxRangeEncoder&&) = default;
33
28 /// Writes the rightmost value_size bits from value into the stream 34 /// Writes the rightmost value_size bits from value into the stream
29 void Write(s32 value, s32 value_size); 35 void Write(s32 value, s32 value_size);
30 36
@@ -37,11 +43,11 @@ public:
37 /// Signal the end of the bitstream 43 /// Signal the end of the bitstream
38 void End(); 44 void End();
39 45
40 std::vector<u8>& GetBuffer() { 46 [[nodiscard]] std::vector<u8>& GetBuffer() {
41 return base_stream.GetBuffer(); 47 return base_stream.GetBuffer();
42 } 48 }
43 49
44 const std::vector<u8>& GetBuffer() const { 50 [[nodiscard]] const std::vector<u8>& GetBuffer() const {
45 return base_stream.GetBuffer(); 51 return base_stream.GetBuffer();
46 } 52 }
47 53
@@ -59,6 +65,12 @@ public:
59 VpxBitStreamWriter(); 65 VpxBitStreamWriter();
60 ~VpxBitStreamWriter(); 66 ~VpxBitStreamWriter();
61 67
68 VpxBitStreamWriter(const VpxBitStreamWriter&) = delete;
69 VpxBitStreamWriter& operator=(const VpxBitStreamWriter&) = delete;
70
71 VpxBitStreamWriter(VpxBitStreamWriter&&) = default;
72 VpxBitStreamWriter& operator=(VpxBitStreamWriter&&) = default;
73
62 /// Write an unsigned integer value 74 /// Write an unsigned integer value
63 void WriteU(u32 value, u32 value_size); 75 void WriteU(u32 value, u32 value_size);
64 76
@@ -75,10 +87,10 @@ public:
75 void Flush(); 87 void Flush();
76 88
77 /// Returns byte_array 89 /// Returns byte_array
78 std::vector<u8>& GetByteArray(); 90 [[nodiscard]] std::vector<u8>& GetByteArray();
79 91
80 /// Returns const byte_array 92 /// Returns const byte_array
81 const std::vector<u8>& GetByteArray() const; 93 [[nodiscard]] const std::vector<u8>& GetByteArray() const;
82 94
83private: 95private:
84 /// Write bit_count bits from value into buffer 96 /// Write bit_count bits from value into buffer
@@ -99,12 +111,18 @@ public:
99 explicit VP9(GPU& gpu); 111 explicit VP9(GPU& gpu);
100 ~VP9(); 112 ~VP9();
101 113
114 VP9(const VP9&) = delete;
115 VP9& operator=(const VP9&) = delete;
116
117 VP9(VP9&&) = default;
118 VP9& operator=(VP9&&) = delete;
119
102 /// Composes the VP9 frame from the GPU state information. Based on the official VP9 spec 120 /// Composes the VP9 frame from the GPU state information. Based on the official VP9 spec
103 /// documentation 121 /// documentation
104 std::vector<u8>& ComposeFrameHeader(NvdecCommon::NvdecRegisters& state); 122 std::vector<u8>& ComposeFrameHeader(NvdecCommon::NvdecRegisters& state);
105 123
106 /// Returns true if the most recent frame was a hidden frame. 124 /// Returns true if the most recent frame was a hidden frame.
107 bool WasFrameHidden() const { 125 [[nodiscard]] bool WasFrameHidden() const {
108 return hidden; 126 return hidden;
109 } 127 }
110 128
@@ -121,12 +139,6 @@ private:
121 /// Generates compressed header probability deltas in the bitstream writer 139 /// Generates compressed header probability deltas in the bitstream writer
122 void WriteProbabilityDelta(VpxRangeEncoder& writer, u8 new_prob, u8 old_prob); 140 void WriteProbabilityDelta(VpxRangeEncoder& writer, u8 new_prob, u8 old_prob);
123 141
124 /// Adjusts old_prob depending on new_prob. Based on section 6.3.5 of VP9 Specification
125 s32 RemapProbability(s32 new_prob, s32 old_prob);
126
127 /// Recenters probability. Based on section 6.3.6 of VP9 Specification
128 s32 RecenterNonNeg(s32 new_prob, s32 old_prob);
129
130 /// Inverse of 6.3.4 Decode term subexp 142 /// Inverse of 6.3.4 Decode term subexp
131 void EncodeTermSubExp(VpxRangeEncoder& writer, s32 value); 143 void EncodeTermSubExp(VpxRangeEncoder& writer, s32 value);
132 144
@@ -146,22 +158,18 @@ private:
146 /// Write motion vector probability updates. 6.3.17 in the spec 158 /// Write motion vector probability updates. 6.3.17 in the spec
147 void WriteMvProbabilityUpdate(VpxRangeEncoder& writer, u8 new_prob, u8 old_prob); 159 void WriteMvProbabilityUpdate(VpxRangeEncoder& writer, u8 new_prob, u8 old_prob);
148 160
149 /// 6.2.14 Tile size calculation
150 s32 CalcMinLog2TileCols(s32 frame_width);
151 s32 CalcMaxLog2TileCols(s32 frame_width);
152
153 /// Returns VP9 information from NVDEC provided offset and size 161 /// Returns VP9 information from NVDEC provided offset and size
154 Vp9PictureInfo GetVp9PictureInfo(const NvdecCommon::NvdecRegisters& state); 162 [[nodiscard]] Vp9PictureInfo GetVp9PictureInfo(const NvdecCommon::NvdecRegisters& state);
155 163
156 /// Read and convert NVDEC provided entropy probs to Vp9EntropyProbs struct 164 /// Read and convert NVDEC provided entropy probs to Vp9EntropyProbs struct
157 void InsertEntropy(u64 offset, Vp9EntropyProbs& dst); 165 void InsertEntropy(u64 offset, Vp9EntropyProbs& dst);
158 166
159 /// Returns frame to be decoded after buffering 167 /// Returns frame to be decoded after buffering
160 Vp9FrameContainer GetCurrentFrame(const NvdecCommon::NvdecRegisters& state); 168 [[nodiscard]] Vp9FrameContainer GetCurrentFrame(const NvdecCommon::NvdecRegisters& state);
161 169
162 /// Use NVDEC providied information to compose the headers for the current frame 170 /// Use NVDEC providied information to compose the headers for the current frame
163 std::vector<u8> ComposeCompressedHeader(); 171 [[nodiscard]] std::vector<u8> ComposeCompressedHeader();
164 VpxBitStreamWriter ComposeUncompressedHeader(); 172 [[nodiscard]] VpxBitStreamWriter ComposeUncompressedHeader();
165 173
166 GPU& gpu; 174 GPU& gpu;
167 std::vector<u8> frame; 175 std::vector<u8> frame;
@@ -169,7 +177,7 @@ private:
169 std::array<s8, 4> loop_filter_ref_deltas{}; 177 std::array<s8, 4> loop_filter_ref_deltas{};
170 std::array<s8, 2> loop_filter_mode_deltas{}; 178 std::array<s8, 2> loop_filter_mode_deltas{};
171 179
172 bool hidden; 180 bool hidden = false;
173 s64 current_frame_number = -2; // since we buffer 2 frames 181 s64 current_frame_number = -2; // since we buffer 2 frames
174 s32 grace_period = 6; // frame offsets need to stabilize 182 s32 grace_period = 6; // frame offsets need to stabilize
175 std::array<FrameContexts, 4> frame_ctxs{}; 183 std::array<FrameContexts, 4> frame_ctxs{};