From b5fe9e59c4408661ffbc254efb2b2bb43084251d Mon Sep 17 00:00:00 2001 From: Dmytro Bogovych Date: Tue, 24 Feb 2026 10:47:38 +0300 Subject: [PATCH] - fix AMR-WB decoder --- src/engine/media/MT_AmrCodec.cpp | 31 +++++++++++++-------------- src/engine/media/MT_AmrCodec.h | 4 ++-- src/engine/media/MT_AudioReceiver.cpp | 5 +++-- src/engine/media/MT_Codec.h | 14 ++++++------ 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/engine/media/MT_AmrCodec.cpp b/src/engine/media/MT_AmrCodec.cpp index 3a561df1..3c3fff27 100644 --- a/src/engine/media/MT_AmrCodec.cpp +++ b/src/engine/media/MT_AmrCodec.cpp @@ -535,16 +535,16 @@ Codec::EncodeResult AmrWbCodec::encode(std::span input, std::span #define L_FRAME 160 #define AMR_BITRATE_DTX 15 -int AmrWbCodec::decodeIuup(std::span input, std::span output) +Codec::DecodeResult AmrWbCodec::decodeIuup(std::span input, std::span output) { IuUP::Frame frame; if (!IuUP::parse2(input.data(), input.size(), frame)) - return 0; + return {.mDecoded = 0}; if (!frame.mHeaderCrcOk || !frame.mPayloadCrcOk) { ICELogInfo(<< "CRC check failed."); - return 0; + return {.mDecoded = 0}; } // Reserve space @@ -559,15 +559,15 @@ int AmrWbCodec::decodeIuup(std::span input, std::span ou frameType = ftIndex; if (frameType == 0xFF) - return 0; + return {.mDecoded = 0, .mIsCng = true}; dataToDecode.mutableData()[0] = (frameType << 3) | (1 << 2); D_IF_decode(mDecoderCtx, (const unsigned char*)dataToDecode.data(), (short*)output.data(), 0); - return pcmLength(); + return {.mDecoded = (size_t)pcmLength()}; } -int AmrWbCodec::decodePlain(std::span input, std::span output) +Codec::DecodeResult AmrWbCodec::decodePlain(std::span input, std::span output) { AmrPayloadInfo info; info.mCurrentTimestamp = mCurrentDecoderTimestamp; @@ -586,7 +586,7 @@ int AmrWbCodec::decodePlain(std::span input, std::span o { GAmrWbStatistics.mNonParsed++; ICELogDebug(<< "Failed to decode AMR payload"); - return 0; + return {.mDecoded = 0}; } // Save current timestamp mCurrentDecoderTimestamp = info.mCurrentTimestamp; @@ -595,22 +595,22 @@ int AmrWbCodec::decodePlain(std::span input, std::span o if (ap.mDiscardPacket) { GAmrWbStatistics.mDiscarded++; - return 0; + return {.mDecoded = 0}; } // Find the required output capacity size_t capacity = 0; for (AmrFrame& frame: ap.mFrames) - capacity += frame.mMode == 0xFF /* CNG */ ? pcmLength() * 8 : pcmLength(); + capacity += frame.mMode == 0xFF /* CNG */ ? pcmLength() : pcmLength(); if (output.size() < capacity) - return 0; + return {.mDecoded = 0}; short* dataOut = (short*)output.data(); size_t dataOutSizeInBytes = 0; for (AmrFrame& frame: ap.mFrames) { - size_t frameOutputSize = frame.mMode == 0xFF ? pcmLength() * 8 : pcmLength(); + size_t frameOutputSize = frame.mMode == 0xFF ? pcmLength() : pcmLength(); memset(dataOut, 0, frameOutputSize); if (frame.mData) @@ -624,17 +624,16 @@ int AmrWbCodec::decodePlain(std::span input, std::span o dataOutSizeInBytes += frameOutputSize; } } - return dataOutSizeInBytes; + return {.mDecoded = dataOutSizeInBytes, + .mIsCng = ap.mFrames.size() == 1 ? (ap.mFrames.front().mMode == 0xFF) : false}; } Codec::DecodeResult AmrWbCodec::decode(std::span input, std::span output) { if (mConfig.mIuUP) - return {.mDecoded = (size_t)decodeIuup(input, output)}; + return decodeIuup(input, output); else - return {.mDecoded = (size_t)decodePlain(input, output)}; - - return {.mDecoded = 0}; + return decodePlain(input, output); } size_t AmrWbCodec::plc(int lostFrames, std::span output) diff --git a/src/engine/media/MT_AmrCodec.h b/src/engine/media/MT_AmrCodec.h index 8eca3e12..c09b512e 100644 --- a/src/engine/media/MT_AmrCodec.h +++ b/src/engine/media/MT_AmrCodec.h @@ -85,8 +85,8 @@ protected: int mPreviousPacketLength; - int decodeIuup(std::span input, std::span output); - int decodePlain(std::span input, std::span output); + DecodeResult decodeIuup(std::span input, std::span output); + DecodeResult decodePlain(std::span input, std::span output); public: class CodecFactory: public Factory diff --git a/src/engine/media/MT_AudioReceiver.cpp b/src/engine/media/MT_AudioReceiver.cpp index e6eee304..a5f550c6 100644 --- a/src/engine/media/MT_AudioReceiver.cpp +++ b/src/engine/media/MT_AudioReceiver.cpp @@ -681,8 +681,9 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& out else { // Decode frame by frame - auto r = mCodec->decode({rtp.GetPayloadData() + i * mCodec->rtpLength(), (size_t)frameLength}, - {(uint8_t*)mDecodedFrame, sizeof mDecodedFrame}); + auto codecInput = std::span{rtp.GetPayloadData() + i * mCodec->rtpLength(), (size_t)frameLength}; + auto codecOutput = std::span{(uint8_t*)mDecodedFrame, sizeof mDecodedFrame}; + auto r = mCodec->decode(codecInput, codecOutput); mDecodedLength = r.mDecoded; if (mDecodedLength > 0) processDecoded(output, options); diff --git a/src/engine/media/MT_Codec.h b/src/engine/media/MT_Codec.h index 6972c9f5..6896dad9 100644 --- a/src/engine/media/MT_Codec.h +++ b/src/engine/media/MT_Codec.h @@ -52,17 +52,19 @@ public: int mPcmLength = 0; // In bytes int mFrameTime = 0; // In milliseconds int mRtpLength = 0; // In bytes + float mTimestampUnit = 0.0f; }; // Returns information about this codec instance virtual Info info() = 0; // Helper functions to return information - they are based on info() method - int pcmLength() { return info().mPcmLength; } - int rtpLength() { return info().mRtpLength; } - int channels() { return info().mChannels; } - int samplerate() { return info().mSamplerate; } - int frameTime() { return info().mFrameTime; } - std::string name() { return info().mName; } + int pcmLength() { return info().mPcmLength; } + int rtpLength() { return info().mRtpLength; } + int channels() { return info().mChannels; } + int samplerate() { return info().mSamplerate; } + int frameTime() { return info().mFrameTime; } + std::string name() { return info().mName; } + float timestampUnit() { return info().mTimestampUnit == 0.0f ? 1.0f / info().mSamplerate : info().mTimestampUnit; } Audio::Format getAudioFormat() { return Audio::Format(this->info().mSamplerate, this->info().mChannels);