diff options
| -rw-r--r-- | src/video_core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/video_core/command_classes/codecs/codec.cpp | 34 | ||||
| -rw-r--r-- | src/video_core/command_classes/codecs/codec.h | 2 | ||||
| -rw-r--r-- | src/video_core/command_classes/codecs/vp8.cpp | 20 | ||||
| -rw-r--r-- | src/video_core/command_classes/codecs/vp8.h | 31 | ||||
| -rw-r--r-- | src/video_core/command_classes/codecs/vp9.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/command_classes/codecs/vp9.h | 11 | ||||
| -rw-r--r-- | src/video_core/command_classes/nvdec.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/command_classes/nvdec_common.h | 4 |
9 files changed, 90 insertions, 20 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 269db21a5..6aac7f305 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -15,6 +15,8 @@ add_library(video_core STATIC | |||
| 15 | command_classes/codecs/codec.h | 15 | command_classes/codecs/codec.h |
| 16 | command_classes/codecs/h264.cpp | 16 | command_classes/codecs/h264.cpp |
| 17 | command_classes/codecs/h264.h | 17 | command_classes/codecs/h264.h |
| 18 | command_classes/codecs/vp8.cpp | ||
| 19 | command_classes/codecs/vp8.h | ||
| 18 | command_classes/codecs/vp9.cpp | 20 | command_classes/codecs/vp9.cpp |
| 19 | command_classes/codecs/vp9.h | 21 | command_classes/codecs/vp9.h |
| 20 | command_classes/codecs/vp9_types.h | 22 | command_classes/codecs/vp9_types.h |
diff --git a/src/video_core/command_classes/codecs/codec.cpp b/src/video_core/command_classes/codecs/codec.cpp index 61966cbfe..fc3b8db99 100644 --- a/src/video_core/command_classes/codecs/codec.cpp +++ b/src/video_core/command_classes/codecs/codec.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "common/settings.h" | 8 | #include "common/settings.h" |
| 9 | #include "video_core/command_classes/codecs/codec.h" | 9 | #include "video_core/command_classes/codecs/codec.h" |
| 10 | #include "video_core/command_classes/codecs/h264.h" | 10 | #include "video_core/command_classes/codecs/h264.h" |
| 11 | #include "video_core/command_classes/codecs/vp8.h" | ||
| 11 | #include "video_core/command_classes/codecs/vp9.h" | 12 | #include "video_core/command_classes/codecs/vp9.h" |
| 12 | #include "video_core/gpu.h" | 13 | #include "video_core/gpu.h" |
| 13 | #include "video_core/memory_manager.h" | 14 | #include "video_core/memory_manager.h" |
| @@ -46,6 +47,7 @@ void AVFrameDeleter(AVFrame* ptr) { | |||
| 46 | 47 | ||
| 47 | Codec::Codec(GPU& gpu_, const NvdecCommon::NvdecRegisters& regs) | 48 | Codec::Codec(GPU& gpu_, const NvdecCommon::NvdecRegisters& regs) |
| 48 | : gpu(gpu_), state{regs}, h264_decoder(std::make_unique<Decoder::H264>(gpu)), | 49 | : gpu(gpu_), state{regs}, h264_decoder(std::make_unique<Decoder::H264>(gpu)), |
| 50 | vp8_decoder(std::make_unique<Decoder::VP8>(gpu)), | ||
| 49 | vp9_decoder(std::make_unique<Decoder::VP9>(gpu)) {} | 51 | vp9_decoder(std::make_unique<Decoder::VP9>(gpu)) {} |
| 50 | 52 | ||
| 51 | Codec::~Codec() { | 53 | Codec::~Codec() { |
| @@ -135,7 +137,9 @@ void Codec::Initialize() { | |||
| 135 | switch (current_codec) { | 137 | switch (current_codec) { |
| 136 | case NvdecCommon::VideoCodec::H264: | 138 | case NvdecCommon::VideoCodec::H264: |
| 137 | return AV_CODEC_ID_H264; | 139 | return AV_CODEC_ID_H264; |
| 138 | case NvdecCommon::VideoCodec::Vp9: | 140 | case NvdecCommon::VideoCodec::VP8: |
| 141 | return AV_CODEC_ID_VP8; | ||
| 142 | case NvdecCommon::VideoCodec::VP9: | ||
| 139 | return AV_CODEC_ID_VP9; | 143 | return AV_CODEC_ID_VP9; |
| 140 | default: | 144 | default: |
| 141 | UNIMPLEMENTED_MSG("Unknown codec {}", current_codec); | 145 | UNIMPLEMENTED_MSG("Unknown codec {}", current_codec); |
| @@ -176,19 +180,27 @@ void Codec::Decode() { | |||
| 176 | return; | 180 | return; |
| 177 | } | 181 | } |
| 178 | bool vp9_hidden_frame = false; | 182 | bool vp9_hidden_frame = false; |
| 179 | std::vector<u8> frame_data; | 183 | const auto& frame_data = [&]() { |
| 180 | if (current_codec == NvdecCommon::VideoCodec::H264) { | 184 | switch (current_codec) { |
| 181 | frame_data = h264_decoder->ComposeFrameHeader(state, is_first_frame); | 185 | case Tegra::NvdecCommon::VideoCodec::H264: |
| 182 | } else if (current_codec == NvdecCommon::VideoCodec::Vp9) { | 186 | return h264_decoder->ComposeFrameHeader(state, is_first_frame); |
| 183 | frame_data = vp9_decoder->ComposeFrameHeader(state); | 187 | case Tegra::NvdecCommon::VideoCodec::VP8: |
| 184 | vp9_hidden_frame = vp9_decoder->WasFrameHidden(); | 188 | return vp8_decoder->ComposeFrameHeader(state, is_first_frame); |
| 185 | } | 189 | case Tegra::NvdecCommon::VideoCodec::VP9: |
| 190 | vp9_decoder->ComposeFrameHeader(state); | ||
| 191 | vp9_hidden_frame = vp9_decoder->WasFrameHidden(); | ||
| 192 | return vp9_decoder->GetFrameBytes(); | ||
| 193 | default: | ||
| 194 | UNREACHABLE(); | ||
| 195 | return std::vector<u8>{}; | ||
| 196 | } | ||
| 197 | }(); | ||
| 186 | AVPacketPtr packet{av_packet_alloc(), AVPacketDeleter}; | 198 | AVPacketPtr packet{av_packet_alloc(), AVPacketDeleter}; |
| 187 | if (!packet) { | 199 | if (!packet) { |
| 188 | LOG_ERROR(Service_NVDRV, "av_packet_alloc failed"); | 200 | LOG_ERROR(Service_NVDRV, "av_packet_alloc failed"); |
| 189 | return; | 201 | return; |
| 190 | } | 202 | } |
| 191 | packet->data = frame_data.data(); | 203 | packet->data = const_cast<u8*>(frame_data.data()); |
| 192 | packet->size = static_cast<s32>(frame_data.size()); | 204 | packet->size = static_cast<s32>(frame_data.size()); |
| 193 | if (const int res = avcodec_send_packet(av_codec_ctx, packet.get()); res != 0) { | 205 | if (const int res = avcodec_send_packet(av_codec_ctx, packet.get()); res != 0) { |
| 194 | LOG_DEBUG(Service_NVDRV, "avcodec_send_packet error {}", res); | 206 | LOG_DEBUG(Service_NVDRV, "avcodec_send_packet error {}", res); |
| @@ -252,11 +264,11 @@ std::string_view Codec::GetCurrentCodecName() const { | |||
| 252 | return "None"; | 264 | return "None"; |
| 253 | case NvdecCommon::VideoCodec::H264: | 265 | case NvdecCommon::VideoCodec::H264: |
| 254 | return "H264"; | 266 | return "H264"; |
| 255 | case NvdecCommon::VideoCodec::Vp8: | 267 | case NvdecCommon::VideoCodec::VP8: |
| 256 | return "VP8"; | 268 | return "VP8"; |
| 257 | case NvdecCommon::VideoCodec::H265: | 269 | case NvdecCommon::VideoCodec::H265: |
| 258 | return "H265"; | 270 | return "H265"; |
| 259 | case NvdecCommon::VideoCodec::Vp9: | 271 | case NvdecCommon::VideoCodec::VP9: |
| 260 | return "VP9"; | 272 | return "VP9"; |
| 261 | default: | 273 | default: |
| 262 | return "Unknown"; | 274 | return "Unknown"; |
diff --git a/src/video_core/command_classes/codecs/codec.h b/src/video_core/command_classes/codecs/codec.h index f9a80886f..13ed88382 100644 --- a/src/video_core/command_classes/codecs/codec.h +++ b/src/video_core/command_classes/codecs/codec.h | |||
| @@ -29,6 +29,7 @@ using AVFramePtr = std::unique_ptr<AVFrame, decltype(&AVFrameDeleter)>; | |||
| 29 | 29 | ||
| 30 | namespace Decoder { | 30 | namespace Decoder { |
| 31 | class H264; | 31 | class H264; |
| 32 | class VP8; | ||
| 32 | class VP9; | 33 | class VP9; |
| 33 | } // namespace Decoder | 34 | } // namespace Decoder |
| 34 | 35 | ||
| @@ -72,6 +73,7 @@ private: | |||
| 72 | GPU& gpu; | 73 | GPU& gpu; |
| 73 | const NvdecCommon::NvdecRegisters& state; | 74 | const NvdecCommon::NvdecRegisters& state; |
| 74 | std::unique_ptr<Decoder::H264> h264_decoder; | 75 | std::unique_ptr<Decoder::H264> h264_decoder; |
| 76 | std::unique_ptr<Decoder::VP8> vp8_decoder; | ||
| 75 | std::unique_ptr<Decoder::VP9> vp9_decoder; | 77 | std::unique_ptr<Decoder::VP9> vp9_decoder; |
| 76 | 78 | ||
| 77 | std::queue<AVFramePtr> av_frames{}; | 79 | std::queue<AVFramePtr> av_frames{}; |
diff --git a/src/video_core/command_classes/codecs/vp8.cpp b/src/video_core/command_classes/codecs/vp8.cpp new file mode 100644 index 000000000..976e9f9b7 --- /dev/null +++ b/src/video_core/command_classes/codecs/vp8.cpp | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <array> | ||
| 6 | #include <vector> | ||
| 7 | |||
| 8 | #include "video_core/command_classes/codecs/vp8.h" | ||
| 9 | |||
| 10 | namespace Tegra::Decoder { | ||
| 11 | VP8::VP8(GPU& gpu_) : gpu(gpu_) {} | ||
| 12 | |||
| 13 | VP8::~VP8() = default; | ||
| 14 | |||
| 15 | const std::vector<u8>& VP8::ComposeFrameHeader(const NvdecCommon::NvdecRegisters& state, | ||
| 16 | bool is_first_frame) { | ||
| 17 | return {}; | ||
| 18 | } | ||
| 19 | |||
| 20 | } // namespace Tegra::Decoder | ||
diff --git a/src/video_core/command_classes/codecs/vp8.h b/src/video_core/command_classes/codecs/vp8.h new file mode 100644 index 000000000..70c75f414 --- /dev/null +++ b/src/video_core/command_classes/codecs/vp8.h | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <vector> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "video_core/command_classes/nvdec_common.h" | ||
| 11 | |||
| 12 | namespace Tegra { | ||
| 13 | class GPU; | ||
| 14 | namespace Decoder { | ||
| 15 | |||
| 16 | class VP8 { | ||
| 17 | public: | ||
| 18 | explicit VP8(GPU& gpu); | ||
| 19 | ~VP8(); | ||
| 20 | |||
| 21 | /// Compose the VP8 header of the frame for FFmpeg decoding | ||
| 22 | [[nodiscard]] const std::vector<u8>& ComposeFrameHeader( | ||
| 23 | const NvdecCommon::NvdecRegisters& state, bool is_first_frame = false); | ||
| 24 | |||
| 25 | private: | ||
| 26 | std::vector<u8> frame; | ||
| 27 | GPU& gpu; | ||
| 28 | }; | ||
| 29 | |||
| 30 | } // namespace Decoder | ||
| 31 | } // namespace Tegra | ||
diff --git a/src/video_core/command_classes/codecs/vp9.cpp b/src/video_core/command_classes/codecs/vp9.cpp index d7e749485..269adc3f1 100644 --- a/src/video_core/command_classes/codecs/vp9.cpp +++ b/src/video_core/command_classes/codecs/vp9.cpp | |||
| @@ -770,7 +770,7 @@ VpxBitStreamWriter VP9::ComposeUncompressedHeader() { | |||
| 770 | return uncomp_writer; | 770 | return uncomp_writer; |
| 771 | } | 771 | } |
| 772 | 772 | ||
| 773 | const std::vector<u8>& VP9::ComposeFrameHeader(const NvdecCommon::NvdecRegisters& state) { | 773 | void VP9::ComposeFrameHeader(const NvdecCommon::NvdecRegisters& state) { |
| 774 | std::vector<u8> bitstream; | 774 | std::vector<u8> bitstream; |
| 775 | { | 775 | { |
| 776 | Vp9FrameContainer curr_frame = GetCurrentFrame(state); | 776 | Vp9FrameContainer curr_frame = GetCurrentFrame(state); |
| @@ -792,7 +792,6 @@ const std::vector<u8>& VP9::ComposeFrameHeader(const NvdecCommon::NvdecRegisters | |||
| 792 | frame.begin() + uncompressed_header.size()); | 792 | frame.begin() + uncompressed_header.size()); |
| 793 | std::copy(bitstream.begin(), bitstream.end(), | 793 | std::copy(bitstream.begin(), bitstream.end(), |
| 794 | frame.begin() + uncompressed_header.size() + compressed_header.size()); | 794 | frame.begin() + uncompressed_header.size() + compressed_header.size()); |
| 795 | return frame; | ||
| 796 | } | 795 | } |
| 797 | 796 | ||
| 798 | VpxRangeEncoder::VpxRangeEncoder() { | 797 | VpxRangeEncoder::VpxRangeEncoder() { |
diff --git a/src/video_core/command_classes/codecs/vp9.h b/src/video_core/command_classes/codecs/vp9.h index e6e9fc17e..6ab9ef5b5 100644 --- a/src/video_core/command_classes/codecs/vp9.h +++ b/src/video_core/command_classes/codecs/vp9.h | |||
| @@ -116,16 +116,19 @@ public: | |||
| 116 | VP9(VP9&&) = default; | 116 | VP9(VP9&&) = default; |
| 117 | VP9& operator=(VP9&&) = delete; | 117 | VP9& operator=(VP9&&) = delete; |
| 118 | 118 | ||
| 119 | /// Composes the VP9 frame from the GPU state information. Based on the official VP9 spec | 119 | /// Composes the VP9 frame from the GPU state information. |
| 120 | /// documentation | 120 | /// Based on the official VP9 spec documentation |
| 121 | [[nodiscard]] const std::vector<u8>& ComposeFrameHeader( | 121 | void ComposeFrameHeader(const NvdecCommon::NvdecRegisters& state); |
| 122 | const NvdecCommon::NvdecRegisters& state); | ||
| 123 | 122 | ||
| 124 | /// Returns true if the most recent frame was a hidden frame. | 123 | /// Returns true if the most recent frame was a hidden frame. |
| 125 | [[nodiscard]] bool WasFrameHidden() const { | 124 | [[nodiscard]] bool WasFrameHidden() const { |
| 126 | return !current_frame_info.show_frame; | 125 | return !current_frame_info.show_frame; |
| 127 | } | 126 | } |
| 128 | 127 | ||
| 128 | [[nodiscard]] const std::vector<u8>& GetFrameBytes() const { | ||
| 129 | return frame; | ||
| 130 | } | ||
| 131 | |||
| 129 | private: | 132 | private: |
| 130 | /// Generates compressed header probability updates in the bitstream writer | 133 | /// Generates compressed header probability updates in the bitstream writer |
| 131 | template <typename T, std::size_t N> | 134 | template <typename T, std::size_t N> |
diff --git a/src/video_core/command_classes/nvdec.cpp b/src/video_core/command_classes/nvdec.cpp index b5c55f14a..9aaf5247e 100644 --- a/src/video_core/command_classes/nvdec.cpp +++ b/src/video_core/command_classes/nvdec.cpp | |||
| @@ -35,7 +35,8 @@ AVFramePtr Nvdec::GetFrame() { | |||
| 35 | void Nvdec::Execute() { | 35 | void Nvdec::Execute() { |
| 36 | switch (codec->GetCurrentCodec()) { | 36 | switch (codec->GetCurrentCodec()) { |
| 37 | case NvdecCommon::VideoCodec::H264: | 37 | case NvdecCommon::VideoCodec::H264: |
| 38 | case NvdecCommon::VideoCodec::Vp9: | 38 | case NvdecCommon::VideoCodec::VP8: |
| 39 | case NvdecCommon::VideoCodec::VP9: | ||
| 39 | codec->Decode(); | 40 | codec->Decode(); |
| 40 | break; | 41 | break; |
| 41 | default: | 42 | default: |
diff --git a/src/video_core/command_classes/nvdec_common.h b/src/video_core/command_classes/nvdec_common.h index 6a24e00a0..26c974b00 100644 --- a/src/video_core/command_classes/nvdec_common.h +++ b/src/video_core/command_classes/nvdec_common.h | |||
| @@ -13,9 +13,9 @@ namespace Tegra::NvdecCommon { | |||
| 13 | enum class VideoCodec : u64 { | 13 | enum class VideoCodec : u64 { |
| 14 | None = 0x0, | 14 | None = 0x0, |
| 15 | H264 = 0x3, | 15 | H264 = 0x3, |
| 16 | Vp8 = 0x5, | 16 | VP8 = 0x5, |
| 17 | H265 = 0x7, | 17 | H265 = 0x7, |
| 18 | Vp9 = 0x9, | 18 | VP9 = 0x9, |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | // NVDEC should use a 32-bit address space, but is mapped to 64-bit, | 21 | // NVDEC should use a 32-bit address space, but is mapped to 64-bit, |