From dd21bc8c35b7f86fb7b22ce5e5e222b51b3bd5b6 Mon Sep 17 00:00:00 2001 From: Dmytro Bogovych Date: Fri, 22 May 2026 13:36:28 +0300 Subject: [PATCH] - fix packet time calculation for Opus codec --- src/engine/media/MT_AudioCodec.cpp | 6 ++++++ src/engine/media/MT_AudioCodec.h | 7 ++++++- src/engine/media/MT_AudioReceiver.cpp | 25 +++++++++++++++++++------ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/engine/media/MT_AudioCodec.cpp b/src/engine/media/MT_AudioCodec.cpp index 9cae22ad..92b2958e 100644 --- a/src/engine/media/MT_AudioCodec.cpp +++ b/src/engine/media/MT_AudioCodec.cpp @@ -549,6 +549,12 @@ size_t OpusCodec::plc(int lostPackets, std::span output) return ((uint8_t*)data_output - output.data()); } +size_t OpusCodec::getNumberOfSamples(std::span payload) +{ + int r = opus_packet_get_nb_samples(payload.data(), payload.size(), mSamplerate); + return r >= 0 ? r : 0; +} + // -------------- ILBC ------------------- #define ILBC_CODEC_NAME "ILBC" diff --git a/src/engine/media/MT_AudioCodec.h b/src/engine/media/MT_AudioCodec.h index d6a564a7..ffd22b25 100644 --- a/src/engine/media/MT_AudioCodec.h +++ b/src/engine/media/MT_AudioCodec.h @@ -64,8 +64,11 @@ class OpusCodec: public Codec protected: OpusEncoder *mEncoderCtx = nullptr; OpusDecoder *mDecoderCtx = nullptr; - int mPTime = 0, mSamplerate = 0, mChannels = 0; + int mPTime = 0, + mSamplerate = 0, + mChannels = 0; int mDecoderChannels = 0; + public: struct Params { @@ -110,6 +113,8 @@ public: 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; + + size_t getNumberOfSamples(std::span payload); }; diff --git a/src/engine/media/MT_AudioReceiver.cpp b/src/engine/media/MT_AudioReceiver.cpp index eb19aa8b..6c7c3ce0 100644 --- a/src/engine/media/MT_AudioReceiver.cpp +++ b/src/engine/media/MT_AudioReceiver.cpp @@ -936,18 +936,31 @@ AudioReceiver::MediaInfo AudioReceiver::infoFor(jrtplib::RTPPacket& p) if (!codec) return {}; - int frame_count = 0; + std::chrono::milliseconds packetTime = 0ms; + if (codec->rtpLength() != 0) { - frame_count = static_cast(p.GetPayloadLength() / codec->rtpLength()); + int frameCount = static_cast(p.GetPayloadLength() / codec->rtpLength()); if (p.GetPayloadType() == 9/*G729A silence*/ && p.GetPayloadLength() % codec->rtpLength()) - frame_count++; + frameCount++; + + packetTime = std::chrono::milliseconds(frameCount * codec->frameTime()); } else - frame_count = 1; + if (typeid(*codec) == typeid(OpusCodec)) + { + OpusCodec* oc = dynamic_cast(codec.get()); + assert(oc); + size_t samplesCount = oc->getNumberOfSamples({p.GetPayloadData(), p.GetPayloadLength()}); + int sampleratePerMs = codec->samplerate() / 1000; + packetTime = std::chrono::milliseconds(samplesCount / sampleratePerMs); + } + else + { + packetTime = std::chrono::milliseconds(codec->frameTime()); + } - - return {std::chrono::milliseconds(frame_count * codec->frameTime()), codec->samplerate()}; + return {packetTime, codec->samplerate()}; } // int AudioReceiver::timelengthFor(jrtplib::RTPPacket& p)