- clang format + naming improved
This commit is contained in:
@@ -16,8 +16,9 @@
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#if !defined(TARGET_ANDROID) && !defined(TARGET_OPENWRT) && !defined(TARGET_WIN) && !defined(TARGET_RPI) && defined(USE_AMR_CODEC)
|
||||
# include "MT_AmrCodec.h"
|
||||
#if !defined(TARGET_ANDROID) && !defined(TARGET_OPENWRT) && !defined(TARGET_WIN) && !defined(TARGET_RPI) && \
|
||||
defined(USE_AMR_CODEC)
|
||||
#include "MT_AmrCodec.h"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
@@ -27,9 +28,11 @@
|
||||
using namespace MT;
|
||||
|
||||
// ----------------- RtpBuffer::Packet --------------
|
||||
RtpBuffer::Packet::Packet(const std::shared_ptr<RTPPacket>& packet, std::chrono::milliseconds timelength, int samplerate)
|
||||
:mRtp(packet), mTimelength(timelength), mSamplerate(samplerate)
|
||||
{}
|
||||
RtpBuffer::Packet::Packet(const std::shared_ptr<RTPPacket>& packet, std::chrono::milliseconds timelength,
|
||||
int samplerate)
|
||||
: mRtp(packet), mTimelength(timelength), mSamplerate(samplerate)
|
||||
{
|
||||
}
|
||||
|
||||
const std::shared_ptr<RTPPacket>& RtpBuffer::Packet::rtp() const
|
||||
{
|
||||
@@ -57,15 +60,13 @@ std::vector<short>& RtpBuffer::Packet::pcm()
|
||||
}
|
||||
|
||||
// ------------ RtpBuffer ----------------
|
||||
RtpBuffer::RtpBuffer(Statistics& stat)
|
||||
:mStat(stat)
|
||||
{
|
||||
}
|
||||
RtpBuffer::RtpBuffer(Statistics& stat) : mStat(stat) {}
|
||||
|
||||
RtpBuffer::~RtpBuffer()
|
||||
{
|
||||
if (mAddCounter)
|
||||
ICELogDebug(<< "Number of add packets: " << mAddCounter << ", number of retrieved packets " << mReturnedCounter);
|
||||
ICELogDebug(<< "Number of add packets: " << mAddCounter << ", number of retrieved packets "
|
||||
<< mReturnedCounter);
|
||||
}
|
||||
|
||||
void RtpBuffer::setHigh(std::chrono::milliseconds t)
|
||||
@@ -109,7 +110,8 @@ bool SequenceSort(const std::shared_ptr<RtpBuffer::Packet>& p1, const std::share
|
||||
return p1->rtp()->GetExtendedSequenceNumber() < p2->rtp()->GetExtendedSequenceNumber();
|
||||
}
|
||||
|
||||
std::shared_ptr<RtpBuffer::Packet> RtpBuffer::add(const std::shared_ptr<jrtplib::RTPPacket>& packet, std::chrono::milliseconds timelength, int rate)
|
||||
std::shared_ptr<RtpBuffer::Packet> RtpBuffer::add(const std::shared_ptr<jrtplib::RTPPacket>& packet,
|
||||
std::chrono::milliseconds timelength, int rate)
|
||||
{
|
||||
if (!packet)
|
||||
return std::shared_ptr<Packet>();
|
||||
@@ -137,7 +139,7 @@ std::shared_ptr<RtpBuffer::Packet> RtpBuffer::add(const std::shared_ptr<jrtplib:
|
||||
// New sequence number
|
||||
unsigned newSeqno = packet->GetExtendedSequenceNumber();
|
||||
|
||||
for (auto& p: mPacketList)
|
||||
for (auto& p : mPacketList)
|
||||
{
|
||||
unsigned seqno = p->rtp()->GetExtendedSequenceNumber();
|
||||
|
||||
@@ -196,16 +198,15 @@ void RtpBuffer::trimToHighWater(size_t maxPackets)
|
||||
// high-water mark (mHigh, when set) or, if maxPackets != 0, the packet-count
|
||||
// cap. Always keep at least one packet so loss/gap accounting has a reference.
|
||||
while (mPacketList.size() > 1 &&
|
||||
((0ms != mHigh && total > mHigh) ||
|
||||
(maxPackets != 0 && mPacketList.size() > maxPackets)))
|
||||
((0ms != mHigh && total > mHigh) || (maxPackets != 0 && mPacketList.size() > maxPackets)))
|
||||
{
|
||||
ICELogMedia( << "Dropping RTP packets from jitter buffer");
|
||||
ICELogMedia(<< "Dropping RTP packets from jitter buffer");
|
||||
total -= mPacketList.front()->timelength();
|
||||
|
||||
// Before advancing mLastSeqno over the dropped packet, record a loss event for any
|
||||
// sequence-number gap on the wire between the previous packet we saw and this one.
|
||||
// Without this, drops silently mask real packet loss that happened between them.
|
||||
auto droppingPacket = mPacketList.front();
|
||||
auto droppingPacket = mPacketList.front();
|
||||
uint32_t droppingSeq = droppingPacket->rtp()->GetExtendedSequenceNumber();
|
||||
if (mLastSeqno)
|
||||
{
|
||||
@@ -241,7 +242,7 @@ void RtpBuffer::trimToHighWater(size_t maxPackets)
|
||||
|
||||
RtpBuffer::FetchResult RtpBuffer::fetch()
|
||||
{
|
||||
Lock l(mGuard);
|
||||
Lock l(mGuard);
|
||||
|
||||
FetchResult result;
|
||||
|
||||
@@ -268,11 +269,11 @@ RtpBuffer::FetchResult RtpBuffer::fetch()
|
||||
else
|
||||
{
|
||||
// Current sequence number ?
|
||||
auto& packet = *mPacketList.front();
|
||||
auto& packet = *mPacketList.front();
|
||||
uint32_t seqno = packet.rtp()->GetExtendedSequenceNumber();
|
||||
|
||||
// Gap between new packet and previous on
|
||||
int gap = (int64_t)seqno - (int64_t)*mLastSeqno - 1;
|
||||
int gap = (int64_t)seqno - (int64_t)*mLastSeqno - 1;
|
||||
if (gap > 0)
|
||||
{
|
||||
// std::cout << "Increase the packet loss for SSRC " << std::hex << mSsrc << std::endl;
|
||||
@@ -290,8 +291,9 @@ RtpBuffer::FetchResult RtpBuffer::fetch()
|
||||
.mTimestampEnd = gapEnd});
|
||||
}
|
||||
|
||||
// ToDo: here we should decide smth - 2-packet gap shoud report Status::Gap two times at least; but current implementation gives only one.
|
||||
// It is not big problem - as gap is detected when we have smth to return usually
|
||||
// ToDo: here we should decide smth - 2-packet gap shoud report Status::Gap two times at least; but
|
||||
// current implementation gives only one. It is not big problem - as gap is detected when we have
|
||||
// smth to return usually
|
||||
mLastSeqno = seqno;
|
||||
mLastReceiveTime = packet.rtp()->GetReceiveTime();
|
||||
result = {FetchResult::Status::Gap};
|
||||
@@ -343,7 +345,7 @@ RtpBuffer::FetchResult RtpBuffer::fetch()
|
||||
std::chrono::milliseconds RtpBuffer::findTimelength()
|
||||
{
|
||||
std::chrono::milliseconds r = 0ms;
|
||||
for (const auto& p: mPacketList)
|
||||
for (const auto& p : mPacketList)
|
||||
r += p->timelength();
|
||||
return r;
|
||||
}
|
||||
@@ -356,9 +358,9 @@ std::shared_ptr<RtpBuffer::Packet> RtpBuffer::peekFront() const
|
||||
|
||||
std::chrono::milliseconds RtpBuffer::bufferedTime() const
|
||||
{
|
||||
Lock l(mGuard);
|
||||
Lock l(mGuard);
|
||||
std::chrono::milliseconds r = 0ms;
|
||||
for (const auto& p: mPacketList)
|
||||
for (const auto& p : mPacketList)
|
||||
r += p->timelength();
|
||||
return r;
|
||||
}
|
||||
@@ -374,16 +376,14 @@ int RtpBuffer::getNumberOfAddPackets() const
|
||||
}
|
||||
|
||||
//-------------- Receiver ---------------
|
||||
Receiver::Receiver(Statistics& stat)
|
||||
:mStat(stat)
|
||||
{}
|
||||
Receiver::Receiver(Statistics& stat) : mStat(stat) {}
|
||||
|
||||
Receiver::~Receiver()
|
||||
{}
|
||||
Receiver::~Receiver() {}
|
||||
|
||||
//-------------- AudioReceiver ----------------
|
||||
AudioReceiver::AudioReceiver(const CodecList::Settings& settings, MT::Statistics &stat)
|
||||
:Receiver(stat), mRtpBuffer(stat), mDtmfBuffer(stat), mCodecSettings(settings), mCodecList(settings), mDtmfReceiver(stat)
|
||||
AudioReceiver::AudioReceiver(const CodecList::Settings& settings, MT::Statistics& stat)
|
||||
: Receiver(stat), mRtpBuffer(stat), mDtmfBuffer(stat), mCodecSettings(settings), mCodecList(settings),
|
||||
mDtmfReceiver(stat)
|
||||
{
|
||||
// Init codecs
|
||||
mCodecList.setSettings(settings);
|
||||
@@ -449,7 +449,8 @@ void AudioReceiver::setCodecSettings(const CodecList::Settings& codecSettings)
|
||||
const bool lazy = mCodecSettings.mLazyCodecMap;
|
||||
mCodecSettings = codecSettings;
|
||||
mCodecSettings.mLazyCodecMap = lazy;
|
||||
mCodecList.setSettings(mCodecSettings); // This builds factory list with proper payload types according to payload types in settings
|
||||
mCodecList.setSettings(
|
||||
mCodecSettings); // This builds factory list with proper payload types according to payload types in settings
|
||||
|
||||
// Rebuild codec map from factory list
|
||||
mCodecList.fillCodecMap(mCodecMap);
|
||||
@@ -485,10 +486,7 @@ Codec* AudioReceiver::add(const std::shared_ptr<jrtplib::RTPPacket>& p)
|
||||
Codec* codec = nullptr;
|
||||
|
||||
// Estimate time length
|
||||
int time_length = 0,
|
||||
samplerate = 8000,
|
||||
payloadLength = p->GetPayloadLength(),
|
||||
ptype = p->GetPayloadType();
|
||||
int time_length = 0, samplerate = 8000, payloadLength = p->GetPayloadLength(), ptype = p->GetPayloadType();
|
||||
|
||||
// ICELogMedia(<< "Adding packet No " << p->GetSequenceNumber());
|
||||
|
||||
@@ -522,8 +520,7 @@ Codec* AudioReceiver::add(const std::shared_ptr<jrtplib::RTPPacket>& p)
|
||||
|
||||
if (!codec)
|
||||
time_length = 10;
|
||||
else
|
||||
if (!codec->rtpLength())
|
||||
else if (!codec->rtpLength())
|
||||
time_length = codec->frameTime();
|
||||
else
|
||||
time_length = lround(double(payloadLength) / codec->rtpLength() * codec->frameTime());
|
||||
@@ -543,14 +540,14 @@ Codec* AudioReceiver::add(const std::shared_ptr<jrtplib::RTPPacket>& p)
|
||||
if (payloadLength >= 1 && payloadLength <= 6 && (ptype == 0 || ptype == 8))
|
||||
time_length = mLastPacketTimeLength ? mLastPacketTimeLength : 20;
|
||||
else
|
||||
// Check if packet is too short from time length side - smth strange with found codec...
|
||||
if (time_length < 2)
|
||||
{
|
||||
// It will cause statistics to report about bad RTP packet
|
||||
// I have to replay last packet payload here to avoid report about lost packet
|
||||
mRtpBuffer.add(p, std::chrono::milliseconds(time_length), samplerate);
|
||||
return nullptr;
|
||||
}
|
||||
// Check if packet is too short from time length side - smth strange with found codec...
|
||||
if (time_length < 2)
|
||||
{
|
||||
// It will cause statistics to report about bad RTP packet
|
||||
// I have to replay last packet payload here to avoid report about lost packet
|
||||
mRtpBuffer.add(p, std::chrono::milliseconds(time_length), samplerate);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Queue packet to buffer
|
||||
mRtpBuffer.add(p, std::chrono::milliseconds(time_length), samplerate).get();
|
||||
@@ -618,7 +615,8 @@ void AudioReceiver::produceCNG(std::chrono::milliseconds length, Audio::DataWind
|
||||
if (options.mSkipDecode)
|
||||
mDecodedLength = 0;
|
||||
else
|
||||
mDecodedLength = cng().produce(mCodec->samplerate(), tail, reinterpret_cast<short*>(mDecodedFrame.data()), false);
|
||||
mDecodedLength =
|
||||
cng().produce(mCodec->samplerate(), tail, reinterpret_cast<short*>(mDecodedFrame.data()), false);
|
||||
|
||||
if (mDecodedLength)
|
||||
processDecoded(output, options);
|
||||
@@ -636,13 +634,13 @@ AudioReceiver::DecodeResult AudioReceiver::decodeGapTo(Audio::DataWindow& output
|
||||
{
|
||||
// Synthesize comfort noise. It will be done on AUDIO_SAMPLERATE rate directly to mResampledFrame buffer.
|
||||
// Do not forget to send this noise to analysis
|
||||
mDecodedLength = cng().produce(mCodec->samplerate(), mLastPacketTimeLength, reinterpret_cast<short*>(mDecodedFrame.data()), false);
|
||||
mDecodedLength = cng().produce(mCodec->samplerate(), mLastPacketTimeLength,
|
||||
reinterpret_cast<short*>(mDecodedFrame.data()), false);
|
||||
}
|
||||
else
|
||||
decodePacketTo(output, options, mCngPacket);
|
||||
}
|
||||
else
|
||||
if (mCodec && mFrameCount && !mCodecSettings.mSkipDecode)
|
||||
else if (mCodec && mFrameCount && !mCodecSettings.mSkipDecode)
|
||||
{
|
||||
// Conceal the gap into mDecodedFrame/mDecodedLength.
|
||||
if (options.mSkipDecode)
|
||||
@@ -662,8 +660,8 @@ AudioReceiver::DecodeResult AudioReceiver::decodeGapTo(Audio::DataWindow& output
|
||||
auto codecIter = mCodecMap.find(next->rtp()->GetPayloadType());
|
||||
if (codecIter != mCodecMap.end() && codecIter->second == mCodec)
|
||||
{
|
||||
mDecodedLength = mCodec->fec({next->rtp()->GetPayloadData(), (size_t)next->rtp()->GetPayloadLength()},
|
||||
concealBuffer);
|
||||
mDecodedLength = mCodec->fec(
|
||||
{next->rtp()->GetPayloadData(), (size_t)next->rtp()->GetPayloadLength()}, concealBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -675,8 +673,8 @@ AudioReceiver::DecodeResult AudioReceiver::decodeGapTo(Audio::DataWindow& output
|
||||
if (!mDecodedLength)
|
||||
{
|
||||
// PLC unsupported or failed - substitute one frame of silence.
|
||||
size_t frameBytes = (size_t)mCodec->frameTime() * mCodec->samplerate() / 1000
|
||||
* sizeof(short) * std::max(1, mCodec->channels());
|
||||
size_t frameBytes = (size_t)mCodec->frameTime() * mCodec->samplerate() / 1000 * sizeof(short) *
|
||||
std::max(1, mCodec->channels());
|
||||
frameBytes = std::min(frameBytes, concealBuffer.size_bytes());
|
||||
mDecodedLength = frameBytes;
|
||||
memset(mDecodedFrame.data(), 0, mDecodedLength);
|
||||
@@ -703,48 +701,51 @@ AudioReceiver::DecodeResult AudioReceiver::decodeGapTo(Audio::DataWindow& output
|
||||
if (mDecodedLength)
|
||||
{
|
||||
processDecoded(output, options);
|
||||
return {.mStatus = DecodeResult::Status::Ok, .mSamplerate = mCodec->samplerate(), .mChannels = mCodec->channels()};
|
||||
return {
|
||||
.mStatus = DecodeResult::Status::Ok, .mSamplerate = mCodec->samplerate(), .mChannels = mCodec->channels()};
|
||||
}
|
||||
else
|
||||
return {.mStatus = DecodeResult::Status::Skip};
|
||||
}
|
||||
|
||||
AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& output, DecodeOptions options, const std::shared_ptr<RtpBuffer::Packet>& packet)
|
||||
AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& output, DecodeOptions options,
|
||||
const std::shared_ptr<RtpBuffer::Packet>& packet)
|
||||
{
|
||||
if (!packet || !packet->rtp())
|
||||
return {DecodeResult::Status::Skip};
|
||||
|
||||
DecodeResult result = {.mStatus = DecodeResult::Status::Skip};
|
||||
auto& rtp = *packet->rtp(); // Syntax sugar
|
||||
auto& rtp = *packet->rtp(); // Syntax sugar
|
||||
|
||||
mFailedCount = 0;
|
||||
|
||||
// Check if we need to emit silence - it may happen in the case if next packet has RTP timestamp much beyond the previous one; maybe DTX was active.
|
||||
// Check if we need to emit silence - it may happen in the case if next packet has RTP timestamp much beyond the
|
||||
// previous one; maybe DTX was active.
|
||||
if (mLastPacketTimestamp && mLastPacketTimeLength && mCodec)
|
||||
{
|
||||
int units = rtp.GetTimestamp() - *mLastPacketTimestamp;
|
||||
int milliseconds = units / (mCodec->samplerate() / 1000);
|
||||
if (milliseconds > mLastPacketTimeLength)
|
||||
{
|
||||
auto silenceLength = std::chrono::milliseconds(milliseconds - mLastPacketTimeLength);
|
||||
ICELogDebug(<< "Emit " << silenceLength << " silence while requested " << options.mElapsed);
|
||||
silenceLength = std::min(silenceLength, options.mElapsed);
|
||||
if (mCngPacket && options.mFillGapByCNG)
|
||||
produceCNG(silenceLength, output, options);
|
||||
else
|
||||
produceSilence(silenceLength, output, options);
|
||||
}
|
||||
}
|
||||
int units = rtp.GetTimestamp() - *mLastPacketTimestamp;
|
||||
int milliseconds = units / (mCodec->samplerate() / 1000);
|
||||
if (milliseconds > mLastPacketTimeLength)
|
||||
{
|
||||
auto silenceLength = std::chrono::milliseconds(milliseconds - mLastPacketTimeLength);
|
||||
ICELogDebug(<< "Emit " << silenceLength << " silence while requested " << options.mElapsed);
|
||||
silenceLength = std::min(silenceLength, options.mElapsed);
|
||||
if (mCngPacket && options.mFillGapByCNG)
|
||||
produceCNG(silenceLength, output, options);
|
||||
else
|
||||
produceSilence(silenceLength, output, options);
|
||||
}
|
||||
}
|
||||
|
||||
mLastPacketTimestamp = rtp.GetTimestamp();
|
||||
|
||||
// Find codec by payload type
|
||||
int ptype = rtp.GetPayloadType();
|
||||
int ptype = rtp.GetPayloadType();
|
||||
|
||||
// Look into mCodecMap if exists
|
||||
auto codecIter = mCodecMap.find(ptype);
|
||||
if (codecIter == mCodecMap.end())
|
||||
return {};
|
||||
return {};
|
||||
|
||||
if (!codecIter->second)
|
||||
codecIter->second = mCodecList.createCodecByPayloadType(ptype);
|
||||
@@ -756,7 +757,8 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& out
|
||||
result.mSamplerate = mCodec->samplerate();
|
||||
|
||||
// Check if it is CNG packet
|
||||
if (((ptype == 0 || ptype == 8) && rtp.GetPayloadLength() >= 1 && rtp.GetPayloadLength() <= 6) || rtp.GetPayloadType() == 13)
|
||||
if (((ptype == 0 || ptype == 8) && rtp.GetPayloadLength() >= 1 && rtp.GetPayloadLength() <= 6) ||
|
||||
rtp.GetPayloadType() == 13)
|
||||
{
|
||||
if (options.mSkipDecode)
|
||||
mDecodedLength = 0;
|
||||
@@ -767,7 +769,8 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& out
|
||||
cng().decode3389(rtp.GetPayloadData(), rtp.GetPayloadLength());
|
||||
|
||||
// Emit CNG mLastPacketLength milliseconds
|
||||
mDecodedLength = cng().produce(mCodec->samplerate(), mLastPacketTimeLength, (short*)mDecodedFrame.data(), true);
|
||||
mDecodedLength =
|
||||
cng().produce(mCodec->samplerate(), mLastPacketTimeLength, (short*)mDecodedFrame.data(), true);
|
||||
if (mDecodedLength)
|
||||
processDecoded(output, options);
|
||||
}
|
||||
@@ -783,7 +786,7 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& out
|
||||
size_t payload_length = rtp.GetPayloadLength();
|
||||
size_t rtp_frame_length = mCodec->rtpLength();
|
||||
|
||||
int tail = rtp_frame_length ? payload_length % rtp_frame_length : 0;
|
||||
int tail = rtp_frame_length ? payload_length % rtp_frame_length : 0;
|
||||
|
||||
if (!tail)
|
||||
{
|
||||
@@ -795,15 +798,17 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& out
|
||||
mLastPacketTimeLength = mFrameCount * mCodec->frameTime();
|
||||
|
||||
// Decode
|
||||
for (int i=0; i<mFrameCount && !mCodecSettings.mSkipDecode; i++)
|
||||
for (int i = 0; i < mFrameCount && !mCodecSettings.mSkipDecode; i++)
|
||||
{
|
||||
if (options.mSkipDecode)
|
||||
mDecodedLength = 0;
|
||||
else
|
||||
{
|
||||
// Decode frame by frame
|
||||
auto codecInput = std::span{rtp.GetPayloadData() + i * mCodec->rtpLength(), (size_t)frameLength};
|
||||
auto codecOutput = std::span{(uint8_t*)mDecodedFrame.data(), mDecodedFrame.size() * sizeof(int16_t)};
|
||||
auto codecInput =
|
||||
std::span{rtp.GetPayloadData() + i * mCodec->rtpLength(), (size_t)frameLength};
|
||||
auto codecOutput =
|
||||
std::span{(uint8_t*)mDecodedFrame.data(), mDecodedFrame.size() * sizeof(int16_t)};
|
||||
auto r = mCodec->decode(codecInput, codecOutput);
|
||||
mDecodedLength = r.mDecoded;
|
||||
if (mDecodedLength > 0)
|
||||
@@ -832,8 +837,8 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& out
|
||||
AudioReceiver::DecodeResult AudioReceiver::decodeEmptyTo(Audio::DataWindow& output, DecodeOptions options)
|
||||
{
|
||||
// There are two cases
|
||||
// First is we have no ready time estimated how much audio should be emitted i.e. audio is decoded right after the next packet arrives.
|
||||
// In this case we just skip the analysis - we should not be called in this situation
|
||||
// First is we have no ready time estimated how much audio should be emitted i.e. audio is decoded right after the
|
||||
// next packet arrives. In this case we just skip the analysis - we should not be called in this situation
|
||||
if (options.mElapsed == 0ms || !mCodec)
|
||||
return {.mStatus = DecodeResult::Status::Skip};
|
||||
|
||||
@@ -851,7 +856,8 @@ AudioReceiver::DecodeResult AudioReceiver::decodeEmptyTo(Audio::DataWindow& outp
|
||||
// the CNG decoder writes straight into its buffer.
|
||||
size_t bytesPerMs = (size_t)fmt.rate() / 1000 * sizeof(short) * fmt.channels();
|
||||
size_t room = output.capacity() - output.filled();
|
||||
int ms = bytesPerMs ? (int)std::min<int64_t>(options.mElapsed.count(), (int64_t)(room / bytesPerMs)) : 0;
|
||||
int ms =
|
||||
bytesPerMs ? (int)std::min<int64_t>(options.mElapsed.count(), (int64_t)(room / bytesPerMs)) : 0;
|
||||
if (ms <= 0)
|
||||
return {.mStatus = DecodeResult::Status::Skip};
|
||||
auto produced = cng().produce(fmt.rate(), ms, (short*)(output.mutableData() + output.filled()), false);
|
||||
@@ -918,11 +924,8 @@ void MT::AudioReceiver::logReceiveHeartbeat()
|
||||
size_t dropDelta = mStat.mPacketDropped - mStatDropLast;
|
||||
|
||||
ICELogInfo(<< "[rx-heartbeat] buffered=" << mRtpBuffer.bufferedTime().count() << "ms"
|
||||
<< " packets=" << mRtpBuffer.getCount()
|
||||
<< " underruns/5s=" << mUnderrunCount
|
||||
<< " gaps/5s=" << mGapCount
|
||||
<< " loss/5s=" << lossDelta
|
||||
<< " dropped/5s=" << dropDelta);
|
||||
<< " packets=" << mRtpBuffer.getCount() << " underruns/5s=" << mUnderrunCount << " gaps/5s=" << mGapCount
|
||||
<< " loss/5s=" << lossDelta << " dropped/5s=" << dropDelta);
|
||||
|
||||
mStatLogLast = t;
|
||||
mUnderrunCount = 0;
|
||||
@@ -938,7 +941,8 @@ void MT::AudioReceiver::updateDecodingTimeStatistics()
|
||||
else
|
||||
{
|
||||
auto t = std::chrono::steady_clock::now();
|
||||
mStat.mDecodingInterval.process(std::chrono::duration_cast<std::chrono::milliseconds>(t - *mDecodeTimestamp).count());
|
||||
mStat.mDecodingInterval.process(
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(t - *mDecodeTimestamp).count());
|
||||
mDecodeTimestamp = t;
|
||||
}
|
||||
}
|
||||
@@ -946,7 +950,7 @@ void MT::AudioReceiver::updateDecodingTimeStatistics()
|
||||
AudioReceiver::DecodeResult AudioReceiver::getAudioTo(Audio::DataWindow& output, DecodeOptions options)
|
||||
{
|
||||
// ICELogDebug(<< "getAudioTo() for " << options.mElapsed);
|
||||
assert (options.mElapsed != 0ms);
|
||||
assert(options.mElapsed != 0ms);
|
||||
|
||||
// First decode on this receiver: allocate the scratch buffers. Network-MOS-only
|
||||
// streams never reach this point, so they never pay for them.
|
||||
@@ -961,7 +965,7 @@ AudioReceiver::DecodeResult AudioReceiver::getAudioTo(Audio::DataWindow& output,
|
||||
processDtmf();
|
||||
|
||||
// How much time length audio we produced here
|
||||
auto produced = 0ms;
|
||||
auto produced = 0ms;
|
||||
Audio::Format fmt;
|
||||
|
||||
// Have we anything from the previous decode attempts ?
|
||||
@@ -993,9 +997,17 @@ AudioReceiver::DecodeResult AudioReceiver::getAudioTo(Audio::DataWindow& output,
|
||||
// Decode to mAvailable buffer
|
||||
switch (fr.mStatus)
|
||||
{
|
||||
case RtpBuffer::FetchResult::Status::Gap: mGapCount++; result = decodeGapTo(mAvailable, options.decreaseElapsedBy(produced)); break;
|
||||
case RtpBuffer::FetchResult::Status::NoPacket: result = decodeEmptyTo(mAvailable, options.decreaseElapsedBy(produced)); break;
|
||||
case RtpBuffer::FetchResult::Status::RegularPacket: result = decodePacketTo(mAvailable, options.decreaseElapsedBy(produced), fr.mPacket); updateDecodeIntervalStatistics(); break;
|
||||
case RtpBuffer::FetchResult::Status::Gap:
|
||||
mGapCount++;
|
||||
result = decodeGapTo(mAvailable, options.decreaseElapsedBy(produced));
|
||||
break;
|
||||
case RtpBuffer::FetchResult::Status::NoPacket:
|
||||
result = decodeEmptyTo(mAvailable, options.decreaseElapsedBy(produced));
|
||||
break;
|
||||
case RtpBuffer::FetchResult::Status::RegularPacket:
|
||||
result = decodePacketTo(mAvailable, options.decreaseElapsedBy(produced), fr.mPacket);
|
||||
updateDecodeIntervalStatistics();
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -1005,8 +1017,8 @@ AudioReceiver::DecodeResult AudioReceiver::getAudioTo(Audio::DataWindow& output,
|
||||
break; // No sense to continue - we have no information at all
|
||||
|
||||
fmt = options.mResampleToMainRate ? Audio::Format(AUDIO_SAMPLERATE, 1) : mCodec->getAudioFormat();
|
||||
result.mSamplerate = fmt.rate();
|
||||
result.mChannels = fmt.channels();
|
||||
result.mSamplerate = fmt.rate();
|
||||
result.mChannels = fmt.channels();
|
||||
|
||||
// How much milliseconds we have in audio buffer ?
|
||||
auto bufferAvailable = mAvailable.getTimeLength(fmt);
|
||||
@@ -1026,7 +1038,8 @@ AudioReceiver::DecodeResult AudioReceiver::getAudioTo(Audio::DataWindow& output,
|
||||
}
|
||||
|
||||
mProducedAudio += produced;
|
||||
// ICELogDebug(<< "Requested " << options.mElapsed << ", produced " << produced << ", remains " << mAvailable.getTimeLength(fmt) << ", packets " << getRtpBuffer().getCount());
|
||||
// ICELogDebug(<< "Requested " << options.mElapsed << ", produced " << produced << ", remains " <<
|
||||
// mAvailable.getTimeLength(fmt) << ", packets " << getRtpBuffer().getCount());
|
||||
|
||||
logReceiveHeartbeat();
|
||||
return result;
|
||||
@@ -1059,21 +1072,31 @@ void AudioReceiver::makeMonoAndResample(int rate, int channels)
|
||||
if (channels != AUDIO_CHANNELS)
|
||||
{
|
||||
if (channels == 1)
|
||||
mConvertedLength = Audio::ChannelConverter::monoToStereo(mDecodedFrame.data(), mDecodedLength, mConvertedFrame.data(), mDecodedLength * 2);
|
||||
mConvertedLength = Audio::ChannelConverter::monoToStereo(mDecodedFrame.data(), mDecodedLength,
|
||||
mConvertedFrame.data(), mDecodedLength * 2);
|
||||
else
|
||||
mDecodedLength = Audio::ChannelConverter::stereoToMono(mDecodedFrame.data(), mDecodedLength, mDecodedFrame.data(), mDecodedLength / 2);
|
||||
mDecodedLength = Audio::ChannelConverter::stereoToMono(mDecodedFrame.data(), mDecodedLength,
|
||||
mDecodedFrame.data(), mDecodedLength / 2);
|
||||
}
|
||||
|
||||
void* frames = mConvertedLength ? (void*)mConvertedFrame.data() : (void*)mDecodedFrame.data();
|
||||
unsigned length = mConvertedLength ? mConvertedLength : mDecodedLength;
|
||||
void* frames = mConvertedLength ? (void*)mConvertedFrame.data() : (void*)mDecodedFrame.data();
|
||||
unsigned length = mConvertedLength ? mConvertedLength : mDecodedLength;
|
||||
|
||||
Audio::Resampler* r = nullptr;
|
||||
switch (rate)
|
||||
{
|
||||
case 8000: r = &mResampler8; break;
|
||||
case 16000: r = &mResampler16; break;
|
||||
case 32000: r = &mResampler32; break;
|
||||
case 48000: r = &mResampler48; break;
|
||||
case 8000:
|
||||
r = &mResampler8;
|
||||
break;
|
||||
case 16000:
|
||||
r = &mResampler16;
|
||||
break;
|
||||
case 32000:
|
||||
r = &mResampler32;
|
||||
break;
|
||||
case 48000:
|
||||
r = &mResampler48;
|
||||
break;
|
||||
default:
|
||||
memcpy(mResampledFrame.data(), frames, length);
|
||||
mResampledLength = length;
|
||||
@@ -1081,7 +1104,8 @@ void AudioReceiver::makeMonoAndResample(int rate, int channels)
|
||||
}
|
||||
|
||||
size_t processedInput = 0;
|
||||
mResampledLength = r->processBuffer(frames, length, processedInput, mResampledFrame.data(), r->getDestLength(length));
|
||||
mResampledLength =
|
||||
r->processBuffer(frames, length, processedInput, mResampledFrame.data(), r->getDestLength(length));
|
||||
// processedInput result value is ignored - it is always equal to length as internal sample rate is 8/16/32/48K
|
||||
}
|
||||
|
||||
@@ -1093,7 +1117,8 @@ Codec* AudioReceiver::findCodec(int payloadType)
|
||||
|
||||
void AudioReceiver::updateAmrCodecStats(Codec* c)
|
||||
{
|
||||
#if !defined(TARGET_ANDROID) && !defined(TARGET_OPENWRT) && !defined(TARGET_WIN) && !defined(TARGET_RPI) && defined(USE_AMR_CODEC)
|
||||
#if !defined(TARGET_ANDROID) && !defined(TARGET_OPENWRT) && !defined(TARGET_WIN) && !defined(TARGET_RPI) && \
|
||||
defined(USE_AMR_CODEC)
|
||||
AmrNbCodec* nb = dynamic_cast<AmrNbCodec*>(c);
|
||||
AmrWbCodec* wb = dynamic_cast<AmrWbCodec*>(c);
|
||||
|
||||
@@ -1102,8 +1127,7 @@ void AudioReceiver::updateAmrCodecStats(Codec* c)
|
||||
mStat.mBitrateSwitchCounter = nb->getSwitchCounter();
|
||||
mStat.mCng = nb->getCngCounter();
|
||||
}
|
||||
else
|
||||
if (wb != nullptr)
|
||||
else if (wb != nullptr)
|
||||
{
|
||||
mStat.mBitrateSwitchCounter = wb->getSwitchCounter();
|
||||
mStat.mCng = wb->getCngCounter();
|
||||
@@ -1114,7 +1138,8 @@ void AudioReceiver::updateAmrCodecStats(Codec* c)
|
||||
int AudioReceiver::getSize() const
|
||||
{
|
||||
int result = 0;
|
||||
result += sizeof(*this) + mResampler8.getSize() + mResampler16.getSize() + mResampler32.getSize() + mResampler48.getSize();
|
||||
result += sizeof(*this) + mResampler8.getSize() + mResampler16.getSize() + mResampler32.getSize() +
|
||||
mResampler48.getSize();
|
||||
|
||||
if (mCodec)
|
||||
; // ToDo: need the way to calculate size of codec instances
|
||||
@@ -1133,18 +1158,17 @@ AudioReceiver::MediaInfo AudioReceiver::infoFor(jrtplib::RTPPacket& p)
|
||||
if (codec->rtpLength() != 0)
|
||||
{
|
||||
int frameCount = static_cast<int>(p.GetPayloadLength() / codec->rtpLength());
|
||||
if (p.GetPayloadType() == 9/*G729A silence*/ && p.GetPayloadLength() % codec->rtpLength())
|
||||
if (p.GetPayloadType() == 9 /*G729A silence*/ && p.GetPayloadLength() % codec->rtpLength())
|
||||
frameCount++;
|
||||
|
||||
packetTime = std::chrono::milliseconds(frameCount * codec->frameTime());
|
||||
}
|
||||
else
|
||||
if (typeid(*codec) == typeid(OpusCodec))
|
||||
else if (typeid(*codec) == typeid(OpusCodec))
|
||||
{
|
||||
OpusCodec* oc = dynamic_cast<OpusCodec*>(codec);
|
||||
assert(oc);
|
||||
size_t samplesCount = oc->getNumberOfSamples({p.GetPayloadData(), p.GetPayloadLength()});
|
||||
int sampleratePerMs = codec->samplerate() / 1000;
|
||||
int sampleratePerMs = codec->samplerate() / 1000;
|
||||
packetTime = std::chrono::milliseconds(samplesCount / sampleratePerMs);
|
||||
}
|
||||
else
|
||||
@@ -1161,18 +1185,15 @@ void AudioReceiver::updateDecodeIntervalStatistics()
|
||||
if (mLastDecodeTimestamp)
|
||||
{
|
||||
mIntervalBetweenDecode += std::chrono::duration_cast<std::chrono::microseconds>(now - *mLastDecodeTimestamp);
|
||||
mDecodeCount ++;
|
||||
mDecodeCount++;
|
||||
}
|
||||
mLastDecodeTimestamp = now;
|
||||
}
|
||||
|
||||
// ----------------------- DtmfReceiver -------------------
|
||||
DtmfReceiver::DtmfReceiver(Statistics& stat)
|
||||
:Receiver(stat)
|
||||
{}
|
||||
DtmfReceiver::DtmfReceiver(Statistics& stat) : Receiver(stat) {}
|
||||
|
||||
DtmfReceiver::~DtmfReceiver()
|
||||
{}
|
||||
DtmfReceiver::~DtmfReceiver() {}
|
||||
|
||||
void DtmfReceiver::add(const std::shared_ptr<RTPPacket>& p)
|
||||
{
|
||||
@@ -1192,8 +1213,8 @@ void DtmfReceiver::add(const std::shared_ptr<RTPPacket>& p)
|
||||
mCallback(ev.mTone);
|
||||
|
||||
// Queue statistics item
|
||||
mStat.mDtmf2833Timeline.emplace_back(Dtmf2833Event{.mTone = ev.mTone,
|
||||
.mTimestamp = RtpHelper::toMicroseconds(p->GetReceiveTime())});
|
||||
mStat.mDtmf2833Timeline.emplace_back(
|
||||
Dtmf2833Event{.mTone = ev.mTone, .mTimestamp = RtpHelper::toMicroseconds(p->GetReceiveTime())});
|
||||
}
|
||||
|
||||
mEvent = ev.mTone;
|
||||
|
||||
Reference in New Issue
Block a user