#ifndef MT_AMRCODEC_H #define MT_AMRCODEC_H #include "../engine_config.h" #include #include #include "MT_Codec.h" #include "../helper/HL_Pointer.h" # include "opencore-amr/amrnb/interf_enc.h" # include "opencore-amr/amrnb/interf_dec.h" # include "opencore-amr/amrwb/if_rom.h" # include "opencore-amr/amrwb/dec_if.h" namespace MT { struct AmrCodecConfig { bool mIuUP = false; bool mOctetAligned = false; int mPayloadType = -1; }; class AmrNbCodec : public Codec { protected: void* mEncoderCtx = nullptr; void* mDecoderCtx = nullptr; AmrCodecConfig mConfig; unsigned mCurrentDecoderTimestamp = 0; int mPreviousPacketLength = 0; size_t mCngCounter = 0; size_t mSwitchCounter = 0; // opencore-amr encoder/decoder state is allocated lazily on first encode/decode. // Network-MOS-only streams resolve codec metadata (name/samplerate/frame timing) // but never decode, so they must not pay for a context they never use - at scale // this is ~a decoder state (several KB) saved per network-only stream. void ensureEncoder(); void ensureDecoder(); public: class CodecFactory: public Factory { public: CodecFactory(const AmrCodecConfig& config); const char* name() override; int samplerate() override; int payloadType() override; void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; void create(CodecMap& codecs) override; PCodec create() override; protected: AmrCodecConfig mConfig; }; AmrNbCodec(const AmrCodecConfig& config); ~AmrNbCodec(); Info info() override; EncodeResult encode(std::span input, std::span output) override; DecodeResult decode(std::span input, std::span output) override; size_t plc(int lostFrames, std::span output) override; int getSwitchCounter() const; int getCngCounter() const; }; struct AmrWbStatistics { int mDiscarded = 0; int mNonParsed = 0; }; extern AmrWbStatistics GAmrWbStatistics; class AmrWbCodec : public Codec { protected: void* mEncoderCtx = nullptr; void* mDecoderCtx = nullptr; AmrCodecConfig mConfig; uint64_t mCurrentDecoderTimestamp = 0; size_t mSwitchCounter = 0; size_t mCngCounter = 0; int mPreviousPacketLength; // Decoder state is allocated lazily on first decode/plc (see AmrNbCodec) so // network-MOS-only streams never instantiate the AMR-WB decoder. void ensureDecoder(); DecodeResult decodeIuup(std::span input, std::span output); DecodeResult decodePlain(std::span input, std::span output); public: class CodecFactory: public Factory { public: CodecFactory(const AmrCodecConfig& config); const char* name() override; int samplerate() override; int payloadType() override; void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; void create(CodecMap& codecs) override; PCodec create() override; protected: AmrCodecConfig mConfig; }; AmrWbCodec(const AmrCodecConfig& config); virtual ~AmrWbCodec(); Info info() override; EncodeResult encode(std::span input, std::span output) override; DecodeResult decode(std::span input, std::span output) override; size_t plc(int lostFrames, std::span output) override; int getSwitchCounter() const; int getCngCounter() const; }; class GsmEfrCodec : public Codec { protected: void* mEncoderCtx = nullptr; void* mDecoderCtx = nullptr; bool mIuUP = false; public: class GsmEfrFactory: public Factory { public: GsmEfrFactory(bool iuup, int ptype); const char* name() override; int samplerate() override; int payloadType() override; void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override; void create(CodecMap& codecs) override; PCodec create() override; protected: bool mIuUP; int mPayloadType; }; GsmEfrCodec(bool iuup = false); ~GsmEfrCodec(); Info info() override; EncodeResult encode(std::span input, std::span output) override; DecodeResult decode(std::span input, std::span output) override; size_t plc(int lostFrames, std::span output) override; }; } // End of MT namespace #endif // MT_AMRCODEC_H