- minor cleanups

This commit is contained in:
Dmytro Bogovych 2025-02-16 14:03:04 +03:00
parent caa2239da1
commit a7176fefeb
4 changed files with 57 additions and 122 deletions

View File

@ -10,80 +10,22 @@
using namespace MT; using namespace MT;
static const uint8_t amr_block_size[16]={ 13, 14, 16, 18, 20, 21, 27, 32, // Constant of AMR-NB frame lengths in bytes.
6 , 0 , 0 , 0 , 0 , 0 , 0 , 1 }; const uint8_t amrnb_framelen[9] =
{12, 13, 15, 17, 19, 20, 26, 31, 5};
/**
* Constant of AMR-NB frame lengths in bytes.
*/
const uint8_t amrnb_framelen[16] =
{12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0};
/**
* Constant of AMR-NB frame lengths in bits.
*/
const uint16_t amrnb_framelenbits[9] = const uint16_t amrnb_framelenbits[9] =
{95, 103, 118, 134, 148, 159, 204, 244, 39}; {95, 103, 118, 134, 148, 159, 204, 244, 39};
/**
* Constant of AMR-NB bitrates.
*/
const uint16_t amrnb_bitrates[8] =
{4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200};
/** // Constant of AMR-WB frame lengths in bytes.
* Constant of AMR-WB frame lengths in bytes. const uint8_t amrwb_framelen[10] =
*/ {17, 23, 32, 37, 40, 46, 50, 58, 60, 5 /* SID packet */};
const uint8_t amrwb_framelen[16] =
{17, 23, 32, 37, 40, 46, 50, 58, 60, 5, 0, 0, 0, 0, 0, 0};
/**
* Constant of AMR-WB frame lengths in bits.
*/
const uint16_t amrwb_framelenbits[10] = const uint16_t amrwb_framelenbits[10] =
{132, 177, 253, 285, 317, 365, 397, 461, 477, 40}; {132, 177, 253, 285, 317, 365, 397, 461, 477, 40 /* SID packet */};
/**
* Constant of AMR-WB bitrates.
*/
const uint16_t amrwb_bitrates[9] =
{6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850};
// Helper routines // Helper routines
/*static int8_t bitrateToMode(uint16_t bitrate)
{
int8_t mode = -1;
switch (bitrate)
{
// AMR NB
case 4750: mode = 0; break;
case 5150: mode = 1; break;
case 5900: mode = 2; break;
case 6700: mode = 3; break;
case 7400: mode = 4; break;
case 7950: mode = 5; break;
case 10200: mode = 6; break;
case 12200: mode = 7; break;
// AMRWB
case 6600: mode = 0; break;
case 8850: mode = 1; break;
case 12650: mode = 2; break;
case 14250: mode = 3; break;
case 15850: mode = 4; break;
case 18250: mode = 5; break;
case 19850: mode = 6; break;
case 23050: mode = 7; break;
case 23850: mode = 8; break;
}
return mode;
}*/
struct AmrPayloadInfo struct AmrPayloadInfo
{ {
const uint8_t* mPayload; const uint8_t* mPayload;
@ -124,8 +66,8 @@ static AmrPayload parseAmrPayload(AmrPayloadInfo& input)
result.mDiscardPacket = false; result.mDiscardPacket = false;
// Wrap incoming data with ByteArray to make bit dequeuing easy // Wrap incoming data with ByteArray to make bit dequeuing easy
ByteBuffer dataIn(input.mPayload, static_cast<size_t>(input.mPayloadLength)); ByteBuffer byte_reader(input.mPayload, static_cast<size_t>(input.mPayloadLength));
BitReader br(input.mPayload, static_cast<size_t>(input.mPayloadLength)); BitReader bit_reader (input.mPayload, static_cast<size_t>(input.mPayloadLength));
// In bandwidth-efficient mode, the payload header simply consists of a // In bandwidth-efficient mode, the payload header simply consists of a
// 4-bit codec mode request: // 4-bit codec mode request:
@ -136,16 +78,15 @@ static AmrPayload parseAmrPayload(AmrPayloadInfo& input)
// AMR, as defined in Table 1a in [2], or 0-8 for AMR-WB, as defined // AMR, as defined in Table 1a in [2], or 0-8 for AMR-WB, as defined
// in Table 1a in [4]. CMR value 15 indicates that no mode request // in Table 1a in [4]. CMR value 15 indicates that no mode request
// is present, and other values are for future use. // is present, and other values are for future use.
result.mCodeModeRequest = static_cast<uint8_t>(br.readBits(4)); result.mCodeModeRequest = static_cast<uint8_t>(bit_reader.readBits(4));
// ICELogMedia(<< "CMR: " << result.mCodeModeRequest);
// Consume extra 4 bits for octet aligned profile // Consume extra 4 bits for octet aligned profile
if (input.mOctetAligned) if (input.mOctetAligned)
br.readBits(4); bit_reader.readBits(4);
// Skip interleaving flags for now for octet aligned mode // Skip interleaving flags for now for octet aligned mode
if (input.mInterleaving && input.mOctetAligned) if (input.mInterleaving && input.mOctetAligned)
br.readBits(8); bit_reader.readBits(8);
// Silence codec mode constant (it differs for wideband and narrowband codecs) // Silence codec mode constant (it differs for wideband and narrowband codecs)
uint8_t SID_FT = input.mWideband ? 9 : 8; uint8_t SID_FT = input.mWideband ? 9 : 8;
@ -159,35 +100,22 @@ static AmrPayload parseAmrPayload(AmrPayloadInfo& input)
// F (1 bit): If set to 1, indicates that this frame is followed by // F (1 bit): If set to 1, indicates that this frame is followed by
// another speech frame in this payload; if set to 0, indicates that // another speech frame in this payload; if set to 0, indicates that
// this frame is the last frame in this payload. // this frame is the last frame in this payload.
F = br.readBit(); F = bit_reader.readBit();
// FT (4 bits): Frame type index, indicating either the AMR or AMR-WB // FT (4 bits): Frame type index, indicating either the AMR or AMR-WB
// speech coding mode or comfort noise (SID) mode of the // speech coding mode or comfort noise (SID) mode of the
// corresponding frame carried in this payload. // corresponding frame carried in this payload.
FT = static_cast<uint8_t>(br.readBits(4)); FT = static_cast<uint8_t>(bit_reader.readBits(4));
// Q (1 bit): Frame quality indicator. If set to 0, indicates the // Q (1 bit): Frame quality indicator. If set to 0, indicates the
// corresponding frame is severely damaged, and the receiver should // corresponding frame is severely damaged, and the receiver should
// set the RX_TYPE (see [6]) to either SPEECH_BAD or SID_BAD // set the RX_TYPE (see [6]) to either SPEECH_BAD or SID_BAD
// depending on the frame type (FT). // depending on the frame type (FT).
Q = br.readBit(); Q = bit_reader.readBit();
// If receiving a ToC entry with a FT value in the range 9-14 for AMR or
// 10-13 for AMR-WB, the whole packet SHOULD be discarded. This is to
// avoid the loss of data synchronization in the depacketization
// process, which can result in a huge degradation in speech quality.
if ((input.mWideband && (FT >= 10 && FT <= 13)) ||
(!input.mWideband && (FT >= 9 && FT <= 14)))
{
ICELogMedia(<< "Discard corrupted packet");
// Discard bad packet
result.mDiscardPacket = true;
return result;
}
// Handle padding for octet alignment // Handle padding for octet alignment
if (input.mOctetAligned) if (input.mOctetAligned)
br.readBits(2); bit_reader.readBits(2);
AmrFrame frame; AmrFrame frame;
frame.mFrameType = FT; frame.mFrameType = FT;
@ -195,17 +123,19 @@ static AmrPayload parseAmrPayload(AmrPayloadInfo& input)
frame.mMode = FT < SID_FT ? FT : 0xFF; frame.mMode = FT < SID_FT ? FT : 0xFF;
frame.mGoodQuality = Q == 1; frame.mGoodQuality = Q == 1;
frame.mTimestamp = input.mCurrentTimestamp; frame.mTimestamp = input.mCurrentTimestamp;
result.mFrames.push_back(frame); result.mFrames.push_back(frame);
input.mCurrentTimestamp += input.mWideband ? 320 : 160; input.mCurrentTimestamp += input.mWideband ? 320 : 160;
} }
while (F != 0); while (F != 0);
for (size_t frameIndex=0; frameIndex < result.mFrames.size(); frameIndex++) for (size_t frameIndex=0; frameIndex < result.mFrames.size() && !result.mDiscardPacket; frameIndex++)
{ {
AmrFrame& f = result.mFrames[frameIndex]; AmrFrame& f = result.mFrames[frameIndex];
// If receiving a ToC entry with a FT value in the range 9-14 for AMR or
// 10-13 for AMR-WB, the whole packet SHOULD be discarded. This is to
// avoid the loss of data synchronization in the depacketization
// process, which can result in a huge degradation in speech quality.
bool discard = input.mWideband ? (f.mFrameType >= 10 && f.mFrameType <= 13) : (f.mFrameType >= 9 && f.mFrameType <= 14); bool discard = input.mWideband ? (f.mFrameType >= 10 && f.mFrameType <= 13) : (f.mFrameType >= 9 && f.mFrameType <= 14);
discard |= input.mWideband ? f.mFrameType >= 14 : f.mFrameType >= 15; discard |= input.mWideband ? f.mFrameType >= 14 : f.mFrameType >= 15;
if (discard) if (discard)
@ -214,28 +144,35 @@ static AmrPayload parseAmrPayload(AmrPayloadInfo& input)
continue; continue;
} }
/*std::cout << "New AMR speech frame: frame type = " << int(FT)
<< ", mode = " << int(f.mMode)
<< ", octet-aligned = " << input.mOctetAligned
<< ", timestamp = " << static_cast<int>(f.mTimestamp) << std::endl;*/
size_t bitsLength = input.mWideband ? amrwb_framelenbits[f.mFrameType] : amrnb_framelenbits[f.mFrameType]; size_t bitsLength = input.mWideband ? amrwb_framelenbits[f.mFrameType] : amrnb_framelenbits[f.mFrameType];
size_t byteLength = input.mWideband ? amrwb_framelen[f.mFrameType] : amrnb_framelen[f.mFrameType]; size_t byteLength = input.mWideband ? amrwb_framelen[f.mFrameType] : amrnb_framelen[f.mFrameType];
std::cout << "New AMR speech frame: frame type = " << FT <<
", mode = " << f.mMode <<
", timestamp = " << static_cast<int>(f.mTimestamp) <<
", bits length = " << static_cast<int>(bitsLength) <<
", byte length =" << static_cast<int>(byteLength) <<
", remaining packet length = " << static_cast<int>(dataIn.size()) << std::endl;;
if (bitsLength > 0) if (bitsLength > 0)
{ {
if (input.mOctetAligned) if (input.mOctetAligned)
{ {
if (dataIn.size() < byteLength) if (byte_reader.size() < byteLength)
f.mGoodQuality = false; f.mGoodQuality = false;
else else
{ {
// It is octet aligned scheme, so we are on byte boundary now // It is octet aligned scheme, so we are on byte boundary now
size_t byteOffset = br.count() / 8; size_t byteOffset = bit_reader.count() / 8;
// Copy data of AMR frame // Copy data of AMR frame
if (byteOffset + byteLength <= input.mPayloadLength)
f.mData = std::make_shared<ByteBuffer>(input.mPayload + byteOffset, byteLength); f.mData = std::make_shared<ByteBuffer>(input.mPayload + byteOffset, byteLength);
else
{
std::cerr << "Problem parsing AMR header: octet-aligned is set, available " << input.mPayloadLength - byteOffset
<< " bytes but requested " << byteLength << std::endl;
result.mDiscardPacket = true;
continue;
}
} }
} }
else else
@ -248,17 +185,13 @@ static AmrPayload parseAmrPayload(AmrPayloadInfo& input)
f.mData->mutableData()[0] = (f.mFrameType << 3) | (1 << 2); f.mData->mutableData()[0] = (f.mFrameType << 3) | (1 << 2);
// Read bits // Read bits
if (br.readBits(f.mData->mutableData() + 1, bitsLength /*+ bitsLength*/ ) < (size_t)bitsLength) if (bit_reader.readBits(f.mData->mutableData() + 1, bitsLength /*+ bitsLength*/ ) < (size_t)bitsLength)
f.mGoodQuality = false; f.mGoodQuality = false;
} }
} }
} }
// Padding bits are skipped // Padding bits are skipped
/*if (br.count() / 8 != br.position() / 8 &&
br.count() / 8 != br.position() / 8 + 1)
throw std::runtime_error("Failed to parse AMR frame");*/
return result; return result;
} }
@ -388,6 +321,9 @@ int AmrNbCodec::encode(const void* input, int inputBytes, void* output, int outp
#define AMR_BITRATE_DTX 15 #define AMR_BITRATE_DTX 15
int AmrNbCodec::decode(const void* input, int inputBytes, void* output, int outputCapacity) int AmrNbCodec::decode(const void* input, int inputBytes, void* output, int outputCapacity)
{ {
if (mConfig.mOctetAligned)
return 0;
if (mConfig.mIuUP) if (mConfig.mIuUP)
{ {
// Try to parse IuUP frame // Try to parse IuUP frame
@ -532,9 +468,7 @@ int AmrWbCodec::CodecFactory::payloadType()
#ifdef USE_RESIP_INTEGRATION #ifdef USE_RESIP_INTEGRATION
void AmrWbCodec::CodecFactory::updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) void AmrWbCodec::CodecFactory::updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
{ {}
}
int AmrWbCodec::CodecFactory::processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) int AmrWbCodec::CodecFactory::processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
{ {
@ -632,6 +566,9 @@ int AmrWbCodec::encode(const void* input, int inputBytes, void* output, int outp
#define AMR_BITRATE_DTX 15 #define AMR_BITRATE_DTX 15
int AmrWbCodec::decode(const void* input, int inputBytes, void* output, int outputCapacity) int AmrWbCodec::decode(const void* input, int inputBytes, void* output, int outputCapacity)
{ {
if (mConfig.mOctetAligned)
return 0;
if (mConfig.mIuUP) if (mConfig.mIuUP)
{ {
IuUP::Frame frame; IuUP::Frame frame;

View File

@ -16,9 +16,9 @@ namespace MT
{ {
struct AmrCodecConfig struct AmrCodecConfig
{ {
bool mIuUP; bool mIuUP = false;
bool mOctetAligned; bool mOctetAligned = false;
int mPayloadType; int mPayloadType = -1;
}; };
class AmrNbCodec : public Codec class AmrNbCodec : public Codec

View File

@ -117,7 +117,6 @@ std::shared_ptr<RtpBuffer::Packet> RtpBuffer::add(std::shared_ptr<jrtplib::RTPPa
Lock l(mGuard); Lock l(mGuard);
// Update statistics // Update statistics
if (mLastAddTime == 0.0) if (mLastAddTime == 0.0)
mLastAddTime = now_ms(); mLastAddTime = now_ms();
@ -406,7 +405,9 @@ size_t decode_packet(Codec& codec, RTPPacket& p, void* output_buffer, size_t out
bool AudioReceiver::add(const std::shared_ptr<jrtplib::RTPPacket>& p, Codec** codec) bool AudioReceiver::add(const std::shared_ptr<jrtplib::RTPPacket>& p, Codec** codec)
{ {
// Estimate time length // Estimate time length
int time_length = 0, payloadLength = p->GetPayloadLength(), ptype = p->GetPayloadType(); int time_length = 0,
payloadLength = p->GetPayloadLength(),
ptype = p->GetPayloadType();
// ICELogInfo(<< "Adding packet No " << p->GetSequenceNumber()); // ICELogInfo(<< "Adding packet No " << p->GetSequenceNumber());
// Increase codec counter // Increase codec counter

View File

@ -340,7 +340,8 @@ void CodecList::init(const Settings& settings)
#if !defined(TARGET_ANDROID) && !defined(TARGET_OPENWRT) && !defined(TARGET_RPI) #if !defined(TARGET_ANDROID) && !defined(TARGET_OPENWRT) && !defined(TARGET_RPI)
#if defined(USE_AMR_CODEC) #if defined(USE_AMR_CODEC)
for (int pt: mSettings.mAmrWbPayloadType) for (int pt: mSettings.mAmrWbPayloadType)
mFactoryList.push_back(std::make_shared<AmrWbCodec::CodecFactory>(AmrCodecConfig{mSettings.mWrapIuUP, false, pt})); mFactoryList.push_back(std::make_shared<AmrWbCodec::CodecFactory>(
AmrCodecConfig{mSettings.mWrapIuUP, false, pt}));
for (int pt: mSettings.mAmrWbOctetPayloadType) for (int pt: mSettings.mAmrWbOctetPayloadType)
mFactoryList.push_back(std::make_shared<AmrWbCodec::CodecFactory>(AmrCodecConfig{mSettings.mWrapIuUP, true, pt})); mFactoryList.push_back(std::make_shared<AmrWbCodec::CodecFactory>(AmrCodecConfig{mSettings.mWrapIuUP, true, pt}));
@ -426,14 +427,10 @@ PCodec CodecList::createCodecByPayloadType(int payloadType)
} }
CodecListPriority::CodecListPriority() CodecListPriority::CodecListPriority()
{ {}
}
CodecListPriority::~CodecListPriority() CodecListPriority::~CodecListPriority()
{ {}
}
bool CodecListPriority::isNegativePriority(const CodecListPriority::Item& item) bool CodecListPriority::isNegativePriority(const CodecListPriority::Item& item)
{ {