diff options
Diffstat (limited to '')
| -rw-r--r-- | src/core/hle/service/audio/hwopus.cpp | 34 |
1 files changed, 17 insertions, 17 deletions
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index 00a4b9d53..61af2e6d6 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp | |||
| @@ -23,6 +23,12 @@ struct OpusDeleter { | |||
| 23 | } | 23 | } |
| 24 | }; | 24 | }; |
| 25 | 25 | ||
| 26 | struct OpusPacketHeader { | ||
| 27 | u32_be size; | ||
| 28 | INSERT_PADDING_WORDS(1); | ||
| 29 | }; | ||
| 30 | static_assert(sizeof(OpusPacketHeader) == 0x8, "OpusHeader is an invalid size"); | ||
| 31 | |||
| 26 | class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> { | 32 | class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> { |
| 27 | public: | 33 | public: |
| 28 | IHardwareOpusDecoderManager(std::unique_ptr<OpusDecoder, OpusDeleter> decoder, u32 sample_rate, | 34 | IHardwareOpusDecoderManager(std::unique_ptr<OpusDecoder, OpusDeleter> decoder, u32 sample_rate, |
| @@ -113,23 +119,23 @@ private: | |||
| 113 | std::vector<opus_int16>& output, u64* out_performance_time) { | 119 | std::vector<opus_int16>& output, u64* out_performance_time) { |
| 114 | const auto start_time = std::chrono::high_resolution_clock::now(); | 120 | const auto start_time = std::chrono::high_resolution_clock::now(); |
| 115 | const std::size_t raw_output_sz = output.size() * sizeof(opus_int16); | 121 | const std::size_t raw_output_sz = output.size() * sizeof(opus_int16); |
| 116 | if (sizeof(OpusHeader) > input.size()) { | 122 | if (sizeof(OpusPacketHeader) > input.size()) { |
| 117 | LOG_ERROR(Audio, "Input is smaller than the header size, header_sz={}, input_sz={}", | 123 | LOG_ERROR(Audio, "Input is smaller than the header size, header_sz={}, input_sz={}", |
| 118 | sizeof(OpusHeader), input.size()); | 124 | sizeof(OpusPacketHeader), input.size()); |
| 119 | return false; | 125 | return false; |
| 120 | } | 126 | } |
| 121 | 127 | ||
| 122 | OpusHeader hdr{}; | 128 | OpusPacketHeader hdr{}; |
| 123 | std::memcpy(&hdr, input.data(), sizeof(OpusHeader)); | 129 | std::memcpy(&hdr, input.data(), sizeof(OpusPacketHeader)); |
| 124 | if (sizeof(OpusHeader) + static_cast<u32>(hdr.sz) > input.size()) { | 130 | if (sizeof(OpusPacketHeader) + static_cast<u32>(hdr.size) > input.size()) { |
| 125 | LOG_ERROR(Audio, "Input does not fit in the opus header size. data_sz={}, input_sz={}", | 131 | LOG_ERROR(Audio, "Input does not fit in the opus header size. data_sz={}, input_sz={}", |
| 126 | sizeof(OpusHeader) + static_cast<u32>(hdr.sz), input.size()); | 132 | sizeof(OpusPacketHeader) + static_cast<u32>(hdr.size), input.size()); |
| 127 | return false; | 133 | return false; |
| 128 | } | 134 | } |
| 129 | 135 | ||
| 130 | const auto frame = input.data() + sizeof(OpusHeader); | 136 | const auto frame = input.data() + sizeof(OpusPacketHeader); |
| 131 | const auto decoded_sample_count = opus_packet_get_nb_samples( | 137 | const auto decoded_sample_count = opus_packet_get_nb_samples( |
| 132 | frame, static_cast<opus_int32>(input.size() - sizeof(OpusHeader)), | 138 | frame, static_cast<opus_int32>(input.size() - sizeof(OpusPacketHeader)), |
| 133 | static_cast<opus_int32>(sample_rate)); | 139 | static_cast<opus_int32>(sample_rate)); |
| 134 | if (decoded_sample_count * channel_count * sizeof(u16) > raw_output_sz) { | 140 | if (decoded_sample_count * channel_count * sizeof(u16) > raw_output_sz) { |
| 135 | LOG_ERROR( | 141 | LOG_ERROR( |
| @@ -141,18 +147,18 @@ private: | |||
| 141 | 147 | ||
| 142 | const int frame_size = (static_cast<int>(raw_output_sz / sizeof(s16) / channel_count)); | 148 | const int frame_size = (static_cast<int>(raw_output_sz / sizeof(s16) / channel_count)); |
| 143 | const auto out_sample_count = | 149 | const auto out_sample_count = |
| 144 | opus_decode(decoder.get(), frame, hdr.sz, output.data(), frame_size, 0); | 150 | opus_decode(decoder.get(), frame, hdr.size, output.data(), frame_size, 0); |
| 145 | if (out_sample_count < 0) { | 151 | if (out_sample_count < 0) { |
| 146 | LOG_ERROR(Audio, | 152 | LOG_ERROR(Audio, |
| 147 | "Incorrect sample count received from opus_decode, " | 153 | "Incorrect sample count received from opus_decode, " |
| 148 | "output_sample_count={}, frame_size={}, data_sz_from_hdr={}", | 154 | "output_sample_count={}, frame_size={}, data_sz_from_hdr={}", |
| 149 | out_sample_count, frame_size, static_cast<u32>(hdr.sz)); | 155 | out_sample_count, frame_size, static_cast<u32>(hdr.size)); |
| 150 | return false; | 156 | return false; |
| 151 | } | 157 | } |
| 152 | 158 | ||
| 153 | const auto end_time = std::chrono::high_resolution_clock::now() - start_time; | 159 | const auto end_time = std::chrono::high_resolution_clock::now() - start_time; |
| 154 | sample_count = out_sample_count; | 160 | sample_count = out_sample_count; |
| 155 | consumed = static_cast<u32>(sizeof(OpusHeader) + hdr.sz); | 161 | consumed = static_cast<u32>(sizeof(OpusPacketHeader) + hdr.size); |
| 156 | if (out_performance_time != nullptr) { | 162 | if (out_performance_time != nullptr) { |
| 157 | *out_performance_time = | 163 | *out_performance_time = |
| 158 | std::chrono::duration_cast<std::chrono::milliseconds>(end_time).count(); | 164 | std::chrono::duration_cast<std::chrono::milliseconds>(end_time).count(); |
| @@ -167,12 +173,6 @@ private: | |||
| 167 | opus_decoder_ctl(decoder.get(), OPUS_RESET_STATE); | 173 | opus_decoder_ctl(decoder.get(), OPUS_RESET_STATE); |
| 168 | } | 174 | } |
| 169 | 175 | ||
| 170 | struct OpusHeader { | ||
| 171 | u32_be sz; // Needs to be BE for some odd reason | ||
| 172 | INSERT_PADDING_WORDS(1); | ||
| 173 | }; | ||
| 174 | static_assert(sizeof(OpusHeader) == 0x8, "OpusHeader is an invalid size"); | ||
| 175 | |||
| 176 | std::unique_ptr<OpusDecoder, OpusDeleter> decoder; | 176 | std::unique_ptr<OpusDecoder, OpusDeleter> decoder; |
| 177 | u32 sample_rate; | 177 | u32 sample_rate; |
| 178 | u32 channel_count; | 178 | u32 channel_count; |