|
@@ -37,7 +37,7 @@ public:
|
|
|
{3, nullptr, "SetContextForMultiStream"},
|
|
{3, nullptr, "SetContextForMultiStream"},
|
|
|
{4, &IHardwareOpusDecoderManager::DecodeInterleavedWithPerfOld, "DecodeInterleavedWithPerfOld"},
|
|
{4, &IHardwareOpusDecoderManager::DecodeInterleavedWithPerfOld, "DecodeInterleavedWithPerfOld"},
|
|
|
{5, nullptr, "DecodeInterleavedForMultiStreamWithPerfOld"},
|
|
{5, nullptr, "DecodeInterleavedForMultiStreamWithPerfOld"},
|
|
|
- {6, nullptr, "DecodeInterleaved"},
|
|
|
|
|
|
|
+ {6, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"},
|
|
|
{7, nullptr, "DecodeInterleavedForMultiStream"},
|
|
{7, nullptr, "DecodeInterleavedForMultiStream"},
|
|
|
};
|
|
};
|
|
|
// clang-format on
|
|
// clang-format on
|
|
@@ -46,24 +46,49 @@ public:
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
private:
|
|
|
|
|
+ /// Describes extra behavior that may be asked of the decoding context.
|
|
|
|
|
+ enum class ExtraBehavior {
|
|
|
|
|
+ /// No extra behavior.
|
|
|
|
|
+ None,
|
|
|
|
|
+
|
|
|
|
|
+ /// Resets the decoder context back to a freshly initialized state.
|
|
|
|
|
+ ResetContext,
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
void DecodeInterleavedOld(Kernel::HLERequestContext& ctx) {
|
|
void DecodeInterleavedOld(Kernel::HLERequestContext& ctx) {
|
|
|
LOG_DEBUG(Audio, "called");
|
|
LOG_DEBUG(Audio, "called");
|
|
|
|
|
|
|
|
- DecodeInterleavedHelper(ctx, nullptr);
|
|
|
|
|
|
|
+ DecodeInterleavedHelper(ctx, nullptr, ExtraBehavior::None);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void DecodeInterleavedWithPerfOld(Kernel::HLERequestContext& ctx) {
|
|
void DecodeInterleavedWithPerfOld(Kernel::HLERequestContext& ctx) {
|
|
|
LOG_DEBUG(Audio, "called");
|
|
LOG_DEBUG(Audio, "called");
|
|
|
|
|
|
|
|
u64 performance = 0;
|
|
u64 performance = 0;
|
|
|
- DecodeInterleavedHelper(ctx, &performance);
|
|
|
|
|
|
|
+ DecodeInterleavedHelper(ctx, &performance, ExtraBehavior::None);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void DecodeInterleaved(Kernel::HLERequestContext& ctx) {
|
|
|
|
|
+ LOG_DEBUG(Audio, "called");
|
|
|
|
|
+
|
|
|
|
|
+ IPC::RequestParser rp{ctx};
|
|
|
|
|
+ const auto extra_behavior =
|
|
|
|
|
+ rp.Pop<bool>() ? ExtraBehavior::ResetContext : ExtraBehavior::None;
|
|
|
|
|
+
|
|
|
|
|
+ u64 performance = 0;
|
|
|
|
|
+ DecodeInterleavedHelper(ctx, &performance, extra_behavior);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void DecodeInterleavedHelper(Kernel::HLERequestContext& ctx, u64* performance) {
|
|
|
|
|
|
|
+ void DecodeInterleavedHelper(Kernel::HLERequestContext& ctx, u64* performance,
|
|
|
|
|
+ ExtraBehavior extra_behavior) {
|
|
|
u32 consumed = 0;
|
|
u32 consumed = 0;
|
|
|
u32 sample_count = 0;
|
|
u32 sample_count = 0;
|
|
|
std::vector<opus_int16> samples(ctx.GetWriteBufferSize() / sizeof(opus_int16));
|
|
std::vector<opus_int16> samples(ctx.GetWriteBufferSize() / sizeof(opus_int16));
|
|
|
|
|
|
|
|
|
|
+ if (extra_behavior == ExtraBehavior::ResetContext) {
|
|
|
|
|
+ ResetDecoderContext();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (!Decoder_DecodeInterleaved(consumed, sample_count, ctx.ReadBuffer(), samples,
|
|
if (!Decoder_DecodeInterleaved(consumed, sample_count, ctx.ReadBuffer(), samples,
|
|
|
performance)) {
|
|
performance)) {
|
|
|
LOG_ERROR(Audio, "Failed to decode opus data");
|
|
LOG_ERROR(Audio, "Failed to decode opus data");
|
|
@@ -136,6 +161,12 @@ private:
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ void ResetDecoderContext() {
|
|
|
|
|
+ ASSERT(decoder != nullptr);
|
|
|
|
|
+
|
|
|
|
|
+ opus_decoder_ctl(decoder.get(), OPUS_RESET_STATE);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
struct OpusHeader {
|
|
struct OpusHeader {
|
|
|
u32_be sz; // Needs to be BE for some odd reason
|
|
u32_be sz; // Needs to be BE for some odd reason
|
|
|
INSERT_PADDING_WORDS(1);
|
|
INSERT_PADDING_WORDS(1);
|