hwopus: Implement DecodeInterleaved
This functions almost identically to DecodeInterleavedWithPerfOld, however this function also has the ability to reset the decoder context. This is documented as a potentially desirable thing in the libopus manual in some circumstances as it says for the OPUS_RESET_STATE ctl: "This should be called when switching streams in order to prevent the back to back decoding from giving different result from one at a time decoding."
This commit is contained in:
		@@ -37,7 +37,7 @@ public:
 | 
			
		||||
            {3, nullptr, "SetContextForMultiStream"},
 | 
			
		||||
            {4, &IHardwareOpusDecoderManager::DecodeInterleavedWithPerfOld, "DecodeInterleavedWithPerfOld"},
 | 
			
		||||
            {5, nullptr, "DecodeInterleavedForMultiStreamWithPerfOld"},
 | 
			
		||||
            {6, nullptr, "DecodeInterleaved"},
 | 
			
		||||
            {6, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"},
 | 
			
		||||
            {7, nullptr, "DecodeInterleavedForMultiStream"},
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
@@ -46,24 +46,49 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
        LOG_DEBUG(Audio, "called");
 | 
			
		||||
 | 
			
		||||
        DecodeInterleavedHelper(ctx, nullptr);
 | 
			
		||||
        DecodeInterleavedHelper(ctx, nullptr, ExtraBehavior::None);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void DecodeInterleavedWithPerfOld(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        LOG_DEBUG(Audio, "called");
 | 
			
		||||
 | 
			
		||||
        u64 performance = 0;
 | 
			
		||||
        DecodeInterleavedHelper(ctx, &performance);
 | 
			
		||||
        DecodeInterleavedHelper(ctx, &performance, ExtraBehavior::None);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void DecodeInterleavedHelper(Kernel::HLERequestContext& ctx, u64* performance) {
 | 
			
		||||
    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,
 | 
			
		||||
                                 ExtraBehavior extra_behavior) {
 | 
			
		||||
        u32 consumed = 0;
 | 
			
		||||
        u32 sample_count = 0;
 | 
			
		||||
        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,
 | 
			
		||||
                                       performance)) {
 | 
			
		||||
            LOG_ERROR(Audio, "Failed to decode opus data");
 | 
			
		||||
@@ -136,6 +161,12 @@ private:
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void ResetDecoderContext() {
 | 
			
		||||
        ASSERT(decoder != nullptr);
 | 
			
		||||
 | 
			
		||||
        opus_decoder_ctl(decoder.get(), OPUS_RESET_STATE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    struct OpusHeader {
 | 
			
		||||
        u32_be sz; // Needs to be BE for some odd reason
 | 
			
		||||
        INSERT_PADDING_WORDS(1);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user