summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Lioncash2019-03-07 05:52:25 -0500
committerGravatar Lioncash2019-03-07 07:47:09 -0500
commitd03ae881fd108dd41039af1ebecc197fc4fe27c7 (patch)
tree6c939ca28c9c7163f0f8eebe87b03767b60bf9ce /src
parentservice/audio/hwopus: Provide a name for the second word of OpusPacketHeader (diff)
downloadyuzu-d03ae881fd108dd41039af1ebecc197fc4fe27c7.tar.gz
yuzu-d03ae881fd108dd41039af1ebecc197fc4fe27c7.tar.xz
yuzu-d03ae881fd108dd41039af1ebecc197fc4fe27c7.zip
service/audio/hwopus: Move decoder state to its own class
Moves the non-multistream specific state to its own class. This will be necessary to support the multistream variants of opus decoding.
Diffstat (limited to '')
-rw-r--r--src/core/hle/service/audio/hwopus.cpp135
1 files changed, 85 insertions, 50 deletions
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp
index aeaa2623b..377e12cfa 100644
--- a/src/core/hle/service/audio/hwopus.cpp
+++ b/src/core/hle/service/audio/hwopus.cpp
@@ -23,6 +23,8 @@ struct OpusDeleter {
23 } 23 }
24}; 24};
25 25
26using OpusDecoderPtr = std::unique_ptr<OpusDecoder, OpusDeleter>;
27
26struct OpusPacketHeader { 28struct OpusPacketHeader {
27 // Packet size in bytes. 29 // Packet size in bytes.
28 u32_be size; 30 u32_be size;
@@ -31,29 +33,8 @@ struct OpusPacketHeader {
31}; 33};
32static_assert(sizeof(OpusPacketHeader) == 0x8, "OpusHeader is an invalid size"); 34static_assert(sizeof(OpusPacketHeader) == 0x8, "OpusHeader is an invalid size");
33 35
34class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> { 36class OpusDecoderStateBase {
35public: 37public:
36 IHardwareOpusDecoderManager(std::unique_ptr<OpusDecoder, OpusDeleter> decoder, u32 sample_rate,
37 u32 channel_count)
38 : ServiceFramework("IHardwareOpusDecoderManager"), decoder(std::move(decoder)),
39 sample_rate(sample_rate), channel_count(channel_count) {
40 // clang-format off
41 static const FunctionInfo functions[] = {
42 {0, &IHardwareOpusDecoderManager::DecodeInterleavedOld, "DecodeInterleavedOld"},
43 {1, nullptr, "SetContext"},
44 {2, nullptr, "DecodeInterleavedForMultiStreamOld"},
45 {3, nullptr, "SetContextForMultiStream"},
46 {4, &IHardwareOpusDecoderManager::DecodeInterleavedWithPerfOld, "DecodeInterleavedWithPerfOld"},
47 {5, nullptr, "DecodeInterleavedForMultiStreamWithPerfOld"},
48 {6, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"},
49 {7, nullptr, "DecodeInterleavedForMultiStream"},
50 };
51 // clang-format on
52
53 RegisterHandlers(functions);
54 }
55
56private:
57 /// Describes extra behavior that may be asked of the decoding context. 38 /// Describes extra behavior that may be asked of the decoding context.
58 enum class ExtraBehavior { 39 enum class ExtraBehavior {
59 /// No extra behavior. 40 /// No extra behavior.
@@ -63,30 +44,36 @@ private:
63 ResetContext, 44 ResetContext,
64 }; 45 };
65 46
66 void DecodeInterleavedOld(Kernel::HLERequestContext& ctx) { 47 enum class PerfTime {
67 LOG_DEBUG(Audio, "called"); 48 Disabled,
68 49 Enabled,
69 DecodeInterleavedHelper(ctx, nullptr, ExtraBehavior::None); 50 };
70 }
71
72 void DecodeInterleavedWithPerfOld(Kernel::HLERequestContext& ctx) {
73 LOG_DEBUG(Audio, "called");
74
75 u64 performance = 0;
76 DecodeInterleavedHelper(ctx, &performance, ExtraBehavior::None);
77 }
78 51
79 void DecodeInterleaved(Kernel::HLERequestContext& ctx) { 52 virtual ~OpusDecoderStateBase() = default;
80 LOG_DEBUG(Audio, "called");
81 53
82 IPC::RequestParser rp{ctx}; 54 // Decodes interleaved Opus packets. Optionally allows reporting time taken to
83 const auto extra_behavior = 55 // perform the decoding, as well as any relevant extra behavior.
84 rp.Pop<bool>() ? ExtraBehavior::ResetContext : ExtraBehavior::None; 56 virtual void DecodeInterleaved(Kernel::HLERequestContext& ctx, PerfTime perf_time,
57 ExtraBehavior extra_behavior) = 0;
58};
85 59
86 u64 performance = 0; 60// Represents the decoder state for a non-multistream decoder.
87 DecodeInterleavedHelper(ctx, &performance, extra_behavior); 61class OpusDecoderState final : public OpusDecoderStateBase {
62public:
63 explicit OpusDecoderState(OpusDecoderPtr decoder, u32 sample_rate, u32 channel_count)
64 : decoder{std::move(decoder)}, sample_rate{sample_rate}, channel_count{channel_count} {}
65
66 void DecodeInterleaved(Kernel::HLERequestContext& ctx, PerfTime perf_time,
67 ExtraBehavior extra_behavior) override {
68 if (perf_time == PerfTime::Disabled) {
69 DecodeInterleavedHelper(ctx, nullptr, extra_behavior);
70 } else {
71 u64 performance = 0;
72 DecodeInterleavedHelper(ctx, &performance, extra_behavior);
73 }
88 } 74 }
89 75
76private:
90 void DecodeInterleavedHelper(Kernel::HLERequestContext& ctx, u64* performance, 77 void DecodeInterleavedHelper(Kernel::HLERequestContext& ctx, u64* performance,
91 ExtraBehavior extra_behavior) { 78 ExtraBehavior extra_behavior) {
92 u32 consumed = 0; 79 u32 consumed = 0;
@@ -97,8 +84,7 @@ private:
97 ResetDecoderContext(); 84 ResetDecoderContext();
98 } 85 }
99 86
100 if (!Decoder_DecodeInterleaved(consumed, sample_count, ctx.ReadBuffer(), samples, 87 if (!DecodeOpusData(consumed, sample_count, ctx.ReadBuffer(), samples, performance)) {
101 performance)) {
102 LOG_ERROR(Audio, "Failed to decode opus data"); 88 LOG_ERROR(Audio, "Failed to decode opus data");
103 IPC::ResponseBuilder rb{ctx, 2}; 89 IPC::ResponseBuilder rb{ctx, 2};
104 // TODO(ogniK): Use correct error code 90 // TODO(ogniK): Use correct error code
@@ -117,8 +103,8 @@ private:
117 ctx.WriteBuffer(samples.data(), samples.size() * sizeof(s16)); 103 ctx.WriteBuffer(samples.data(), samples.size() * sizeof(s16));
118 } 104 }
119 105
120 bool Decoder_DecodeInterleaved(u32& consumed, u32& sample_count, const std::vector<u8>& input, 106 bool DecodeOpusData(u32& consumed, u32& sample_count, const std::vector<u8>& input,
121 std::vector<opus_int16>& output, u64* out_performance_time) { 107 std::vector<opus_int16>& output, u64* out_performance_time) const {
122 const auto start_time = std::chrono::high_resolution_clock::now(); 108 const auto start_time = std::chrono::high_resolution_clock::now();
123 const std::size_t raw_output_sz = output.size() * sizeof(opus_int16); 109 const std::size_t raw_output_sz = output.size() * sizeof(opus_int16);
124 if (sizeof(OpusPacketHeader) > input.size()) { 110 if (sizeof(OpusPacketHeader) > input.size()) {
@@ -175,11 +161,61 @@ private:
175 opus_decoder_ctl(decoder.get(), OPUS_RESET_STATE); 161 opus_decoder_ctl(decoder.get(), OPUS_RESET_STATE);
176 } 162 }
177 163
178 std::unique_ptr<OpusDecoder, OpusDeleter> decoder; 164 OpusDecoderPtr decoder;
179 u32 sample_rate; 165 u32 sample_rate;
180 u32 channel_count; 166 u32 channel_count;
181}; 167};
182 168
169class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> {
170public:
171 explicit IHardwareOpusDecoderManager(std::unique_ptr<OpusDecoderStateBase> decoder_state)
172 : ServiceFramework("IHardwareOpusDecoderManager"), decoder_state{std::move(decoder_state)} {
173 // clang-format off
174 static const FunctionInfo functions[] = {
175 {0, &IHardwareOpusDecoderManager::DecodeInterleavedOld, "DecodeInterleavedOld"},
176 {1, nullptr, "SetContext"},
177 {2, nullptr, "DecodeInterleavedForMultiStreamOld"},
178 {3, nullptr, "SetContextForMultiStream"},
179 {4, &IHardwareOpusDecoderManager::DecodeInterleavedWithPerfOld, "DecodeInterleavedWithPerfOld"},
180 {5, nullptr, "DecodeInterleavedForMultiStreamWithPerfOld"},
181 {6, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"},
182 {7, nullptr, "DecodeInterleavedForMultiStream"},
183 };
184 // clang-format on
185
186 RegisterHandlers(functions);
187 }
188
189private:
190 void DecodeInterleavedOld(Kernel::HLERequestContext& ctx) {
191 LOG_DEBUG(Audio, "called");
192
193 decoder_state->DecodeInterleaved(ctx, OpusDecoderStateBase::PerfTime::Disabled,
194 OpusDecoderStateBase::ExtraBehavior::None);
195 }
196
197 void DecodeInterleavedWithPerfOld(Kernel::HLERequestContext& ctx) {
198 LOG_DEBUG(Audio, "called");
199
200 decoder_state->DecodeInterleaved(ctx, OpusDecoderStateBase::PerfTime::Enabled,
201 OpusDecoderStateBase::ExtraBehavior::None);
202 }
203
204 void DecodeInterleaved(Kernel::HLERequestContext& ctx) {
205 LOG_DEBUG(Audio, "called");
206
207 IPC::RequestParser rp{ctx};
208 const auto extra_behavior = rp.Pop<bool>()
209 ? OpusDecoderStateBase::ExtraBehavior::ResetContext
210 : OpusDecoderStateBase::ExtraBehavior::None;
211
212 decoder_state->DecodeInterleaved(ctx, OpusDecoderStateBase::PerfTime::Enabled,
213 extra_behavior);
214 }
215
216 std::unique_ptr<OpusDecoderStateBase> decoder_state;
217};
218
183std::size_t WorkerBufferSize(u32 channel_count) { 219std::size_t WorkerBufferSize(u32 channel_count) {
184 ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count"); 220 ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count");
185 return opus_decoder_get_size(static_cast<int>(channel_count)); 221 return opus_decoder_get_size(static_cast<int>(channel_count));
@@ -223,8 +259,7 @@ void HwOpus::OpenOpusDecoder(Kernel::HLERequestContext& ctx) {
223 const std::size_t worker_sz = WorkerBufferSize(channel_count); 259 const std::size_t worker_sz = WorkerBufferSize(channel_count);
224 ASSERT_MSG(buffer_sz >= worker_sz, "Worker buffer too large"); 260 ASSERT_MSG(buffer_sz >= worker_sz, "Worker buffer too large");
225 261
226 std::unique_ptr<OpusDecoder, OpusDeleter> decoder{ 262 OpusDecoderPtr decoder{static_cast<OpusDecoder*>(operator new(worker_sz))};
227 static_cast<OpusDecoder*>(operator new(worker_sz))};
228 if (const int err = opus_decoder_init(decoder.get(), sample_rate, channel_count)) { 263 if (const int err = opus_decoder_init(decoder.get(), sample_rate, channel_count)) {
229 LOG_ERROR(Audio, "Failed to init opus decoder with error={}", err); 264 LOG_ERROR(Audio, "Failed to init opus decoder with error={}", err);
230 IPC::ResponseBuilder rb{ctx, 2}; 265 IPC::ResponseBuilder rb{ctx, 2};
@@ -235,8 +270,8 @@ void HwOpus::OpenOpusDecoder(Kernel::HLERequestContext& ctx) {
235 270
236 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 271 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
237 rb.Push(RESULT_SUCCESS); 272 rb.Push(RESULT_SUCCESS);
238 rb.PushIpcInterface<IHardwareOpusDecoderManager>(std::move(decoder), sample_rate, 273 rb.PushIpcInterface<IHardwareOpusDecoderManager>(
239 channel_count); 274 std::make_unique<OpusDecoderState>(std::move(decoder), sample_rate, channel_count));
240} 275}
241 276
242HwOpus::HwOpus() : ServiceFramework("hwopus") { 277HwOpus::HwOpus() : ServiceFramework("hwopus") {