- fix clang build (build_linux.py) + fix problems reported by Kimi LLM
This commit is contained in:
@@ -17,18 +17,19 @@ def make_build() -> Path:
|
|||||||
if Path(DIR_BUILD).exists():
|
if Path(DIR_BUILD).exists():
|
||||||
shutil.rmtree(DIR_BUILD)
|
shutil.rmtree(DIR_BUILD)
|
||||||
os.mkdir(DIR_BUILD)
|
os.mkdir(DIR_BUILD)
|
||||||
os.chdir(DIR_BUILD)
|
os.chdir(DIR_BUILD)
|
||||||
|
|
||||||
cmd = f'cmake ../src -G Ninja'
|
# OPUS_X86_MAY_HAVE_SSE4_1 is for clang builds
|
||||||
|
cmd = f'cmake ../src -G Ninja -D OPUS_X86_MAY_HAVE_SSE4_1=ON'
|
||||||
retcode = os.system(cmd)
|
retcode = os.system(cmd)
|
||||||
if retcode != 0:
|
if retcode != 0:
|
||||||
raise RuntimeError('Problem when configuring the project')
|
raise RuntimeError('Problem when configuring the project')
|
||||||
|
|
||||||
cmd = f'cmake --build . -j {multiprocessing.cpu_count()}'
|
cmd = f'cmake --build . -j {multiprocessing.cpu_count()}'
|
||||||
retcode = os.system(cmd)
|
retcode = os.system(cmd)
|
||||||
if retcode != 0:
|
if retcode != 0:
|
||||||
raise RuntimeError('Problem when building the project')
|
raise RuntimeError('Problem when building the project')
|
||||||
|
|
||||||
os.chdir('..')
|
os.chdir('..')
|
||||||
return Path(DIR_BUILD) / 'librtphone.a'
|
return Path(DIR_BUILD) / 'librtphone.a'
|
||||||
|
|
||||||
|
|||||||
@@ -687,7 +687,7 @@ void AgentImpl::processUseStreamForSession(JsonCpp::Value& request, JsonCpp::Val
|
|||||||
answer["status"] = Status_Ok;
|
answer["status"] = Status_Ok;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
answer["status"] = Status_AccountNotFound;
|
answer["status"] = Status_NoCommand;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
answer["status"] = Status_NoMediaAction;
|
answer["status"] = Status_NoMediaAction;
|
||||||
@@ -709,11 +709,13 @@ void AgentImpl::onMedia(const void* data, int length, MT::Stream::MediaDirection
|
|||||||
|
|
||||||
PDataProvider AgentImpl::onProviderNeeded(const std::string& name)
|
PDataProvider AgentImpl::onProviderNeeded(const std::string& name)
|
||||||
{
|
{
|
||||||
|
assert(mTerminal);
|
||||||
|
|
||||||
EVENT_WITH_NAME("provider_needed");
|
EVENT_WITH_NAME("provider_needed");
|
||||||
v["provider_name"] = name;
|
v["provider_name"] = name;
|
||||||
addEvent(v);
|
addEvent(v);
|
||||||
|
|
||||||
return PDataProvider(new AudioProvider(*this, *mTerminal));
|
return std::make_shared<AudioProvider>(*this, *mTerminal);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called on new session offer
|
// Called on new session offer
|
||||||
|
|||||||
@@ -883,7 +883,7 @@ void Session::refreshMediaPath()
|
|||||||
|
|
||||||
// Bring new socket to provider and stream
|
// Bring new socket to provider and stream
|
||||||
RtpPair<PDatagramSocket> s4 = SocketHeap::instance().allocSocketPair(AF_INET, this, IS_MULTIPLEX() ),
|
RtpPair<PDatagramSocket> s4 = SocketHeap::instance().allocSocketPair(AF_INET, this, IS_MULTIPLEX() ),
|
||||||
s6 = SocketHeap::instance().allocSocketPair(AF_INET, this, IS_MULTIPLEX());
|
s6 = SocketHeap::instance().allocSocketPair(AF_INET6, this, IS_MULTIPLEX());
|
||||||
|
|
||||||
p->setSocket(s4, s6);
|
p->setSocket(s4, s6);
|
||||||
s.setSocket4(s4);
|
s.setSocket4(s4);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -65,6 +65,7 @@ void thread_pool::run_worker()
|
|||||||
tasks.pop();
|
tasks.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t(); // function<void()> type
|
if (t)
|
||||||
|
t(); // function<void()> type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ int64_t Variant::asInt64() const
|
|||||||
if (mType != VTYPE_INT64)
|
if (mType != VTYPE_INT64)
|
||||||
throw Exception(ERR_BAD_VARIANT_TYPE);
|
throw Exception(ERR_BAD_VARIANT_TYPE);
|
||||||
|
|
||||||
return mInt;
|
return mInt64;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Variant::asBool() const
|
bool Variant::asBool() const
|
||||||
|
|||||||
@@ -3,11 +3,8 @@
|
|||||||
|
|
||||||
#include "MT_AmrCodec.h"
|
#include "MT_AmrCodec.h"
|
||||||
#include "../helper/HL_ByteBuffer.h"
|
#include "../helper/HL_ByteBuffer.h"
|
||||||
#include "../helper/HL_Log.h"
|
|
||||||
#include "../helper/HL_IuUP.h"
|
#include "../helper/HL_IuUP.h"
|
||||||
#include "../helper/HL_Exception.h"
|
#include "../helper/HL_Log.h"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#define LOG_SUBSYSTEM "AmrCodec"
|
#define LOG_SUBSYSTEM "AmrCodec"
|
||||||
using namespace MT;
|
using namespace MT;
|
||||||
@@ -287,44 +284,31 @@ AmrNbCodec::~AmrNbCodec()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* AmrNbCodec::name()
|
Codec::Info AmrNbCodec::info()
|
||||||
{
|
{
|
||||||
return MT_AMRNB_CODECNAME;
|
return {
|
||||||
|
.mName = MT_AMRNB_CODECNAME,
|
||||||
|
.mSamplerate = 8000,
|
||||||
|
.mChannels = 1,
|
||||||
|
.mPcmLength = 20 * 16,
|
||||||
|
.mFrameTime = 20,
|
||||||
|
.mRtpLength = 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int AmrNbCodec::pcmLength()
|
Codec::EncodeResult AmrNbCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
return 20 * 16;
|
if (input.size_bytes() % pcmLength())
|
||||||
}
|
return {.mEncoded = 0};
|
||||||
|
|
||||||
int AmrNbCodec::rtpLength()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AmrNbCodec::frameTime()
|
|
||||||
{
|
|
||||||
return 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AmrNbCodec::samplerate()
|
|
||||||
{
|
|
||||||
return 8000;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AmrNbCodec::encode(const void* input, int inputBytes, void* output, int outputCapacity)
|
|
||||||
{
|
|
||||||
if (inputBytes % pcmLength())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Declare the data input pointer
|
// Declare the data input pointer
|
||||||
auto *dataIn = (const short *)input;
|
auto *dataIn = (const short *)input.data();
|
||||||
|
|
||||||
// Declare the data output pointer
|
// Declare the data output pointer
|
||||||
auto *dataOut = (unsigned char *)output;
|
auto *dataOut = (unsigned char *)output.data();
|
||||||
|
|
||||||
// Find how much RTP frames will be generated
|
// Find how much RTP frames will be generated
|
||||||
unsigned int frames = inputBytes / pcmLength();
|
unsigned int frames = input.size_bytes() / pcmLength();
|
||||||
|
|
||||||
// Generate frames
|
// Generate frames
|
||||||
for (unsigned int i = 0; i < frames; i++)
|
for (unsigned int i = 0; i < frames; i++)
|
||||||
@@ -333,28 +317,28 @@ int AmrNbCodec::encode(const void* input, int inputBytes, void* output, int outp
|
|||||||
dataIn += pcmLength() / 2;
|
dataIn += pcmLength() / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dataOut - (unsigned char*)output;
|
return {.mEncoded = (size_t)(dataOut - (unsigned char*)output.data())};
|
||||||
}
|
}
|
||||||
|
|
||||||
#define L_FRAME 160
|
#define L_FRAME 160
|
||||||
#define AMR_BITRATE_DTX 15
|
#define AMR_BITRATE_DTX 15
|
||||||
int AmrNbCodec::decode(const void* input, int inputBytes, void* output, int outputCapacity)
|
Codec::DecodeResult AmrNbCodec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
if (mConfig.mOctetAligned)
|
if (mConfig.mOctetAligned)
|
||||||
return 0;
|
return {.mDecoded = 0};
|
||||||
|
|
||||||
if (mConfig.mIuUP)
|
if (mConfig.mIuUP)
|
||||||
{
|
{
|
||||||
// Try to parse IuUP frame
|
// Try to parse IuUP frame
|
||||||
IuUP::Frame frame;
|
IuUP::Frame frame;
|
||||||
if (!IuUP::parse2((const uint8_t*)input, inputBytes, frame))
|
if (!IuUP::parse2((const uint8_t*)input.data(), input.size_bytes(), frame))
|
||||||
return 0;
|
return {0};
|
||||||
|
|
||||||
// Check if CRC failed - it is check from IuUP data
|
// Check if CRC failed - it is check from IuUP data
|
||||||
if (!frame.mHeaderCrcOk || !frame.mPayloadCrcOk)
|
if (!frame.mHeaderCrcOk || !frame.mPayloadCrcOk)
|
||||||
{
|
{
|
||||||
ICELogInfo(<< "CRC check failed.");
|
ICELogInfo(<< "CRC check failed.");
|
||||||
return 0;
|
return {0};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build NB frame to decode
|
// Build NB frame to decode
|
||||||
@@ -371,31 +355,31 @@ int AmrNbCodec::decode(const void* input, int inputBytes, void* output, int outp
|
|||||||
|
|
||||||
// Check if frameType comparing is correct
|
// Check if frameType comparing is correct
|
||||||
if (frameType == 0xFF)
|
if (frameType == 0xFF)
|
||||||
return 0;
|
return {0};
|
||||||
|
|
||||||
dataToDecode.mutableData()[0] = (frameType << 3) | (1 << 2);
|
dataToDecode.mutableData()[0] = (frameType << 3) | (1 << 2);
|
||||||
|
|
||||||
Decoder_Interface_Decode(mDecoderCtx, (const unsigned char*)dataToDecode.data(), (short*)output, 0);
|
Decoder_Interface_Decode(mDecoderCtx, (const unsigned char*)dataToDecode.data(), (short*)output.data(), 0);
|
||||||
return pcmLength();
|
return {.mDecoded = (size_t)pcmLength()};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (outputCapacity < pcmLength())
|
if (output.size_bytes() < pcmLength())
|
||||||
return 0;
|
return {.mDecoded = 0};
|
||||||
|
|
||||||
if (inputBytes == 0)
|
if (input.size_bytes() == 0)
|
||||||
{ // PLC part
|
{ // PLC part
|
||||||
unsigned char buffer[32];
|
unsigned char buffer[32];
|
||||||
buffer[0] = (AMR_BITRATE_DTX << 3)|4;
|
buffer[0] = (AMR_BITRATE_DTX << 3)|4;
|
||||||
Decoder_Interface_Decode(mDecoderCtx, buffer, (short*)output, 0); // Handle missing data
|
Decoder_Interface_Decode(mDecoderCtx, buffer, (short*)output.data(), 0); // Handle missing data
|
||||||
return pcmLength();
|
return {.mDecoded = (size_t)pcmLength()};
|
||||||
}
|
}
|
||||||
|
|
||||||
AmrPayloadInfo info;
|
AmrPayloadInfo info;
|
||||||
info.mCurrentTimestamp = mCurrentDecoderTimestamp;
|
info.mCurrentTimestamp = mCurrentDecoderTimestamp;
|
||||||
info.mOctetAligned = mConfig.mOctetAligned;
|
info.mOctetAligned = mConfig.mOctetAligned;
|
||||||
info.mPayload = (const uint8_t*)input;
|
info.mPayload = input.data();
|
||||||
info.mPayloadLength = inputBytes;
|
info.mPayloadLength = input.size_bytes();
|
||||||
info.mWideband = false;
|
info.mWideband = false;
|
||||||
info.mInterleaving = false;
|
info.mInterleaving = false;
|
||||||
|
|
||||||
@@ -407,25 +391,25 @@ int AmrNbCodec::decode(const void* input, int inputBytes, void* output, int outp
|
|||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
ICELogDebug(<< "Failed to decode AMR payload.");
|
ICELogDebug(<< "Failed to decode AMR payload.");
|
||||||
return 0;
|
return {.mDecoded = 0};
|
||||||
}
|
}
|
||||||
// Save current timestamp
|
// Save current timestamp
|
||||||
mCurrentDecoderTimestamp = info.mCurrentTimestamp;
|
mCurrentDecoderTimestamp = info.mCurrentTimestamp;
|
||||||
|
|
||||||
// Check if packet is corrupted
|
// Check if packet is corrupted
|
||||||
if (ap.mDiscardPacket)
|
if (ap.mDiscardPacket)
|
||||||
return 0;
|
return {.mDecoded = 0};
|
||||||
|
|
||||||
|
|
||||||
// Check for output buffer capacity
|
// Check for output buffer capacity
|
||||||
if (outputCapacity < (int)ap.mFrames.size() * pcmLength())
|
if (output.size_bytes() < (int)ap.mFrames.size() * pcmLength())
|
||||||
return 0;
|
return {.mDecoded = 0};
|
||||||
|
|
||||||
if (ap.mFrames.empty())
|
if (ap.mFrames.empty())
|
||||||
{
|
{
|
||||||
ICELogError(<< "No AMR frames");
|
ICELogError(<< "No AMR frames");
|
||||||
}
|
}
|
||||||
short* dataOut = (short*)output;
|
short* dataOut = (short*)output.data();
|
||||||
for (AmrFrame& frame: ap.mFrames)
|
for (AmrFrame& frame: ap.mFrames)
|
||||||
{
|
{
|
||||||
if (frame.mData)
|
if (frame.mData)
|
||||||
@@ -435,18 +419,18 @@ int AmrNbCodec::decode(const void* input, int inputBytes, void* output, int outp
|
|||||||
dataOut += pcmLength() / 2;
|
dataOut += pcmLength() / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pcmLength() * ap.mFrames.size();
|
return {.mDecoded = pcmLength() * ap.mFrames.size()};
|
||||||
}
|
}
|
||||||
|
|
||||||
return pcmLength();
|
return {.mDecoded = (size_t)pcmLength()};
|
||||||
}
|
}
|
||||||
|
|
||||||
int AmrNbCodec::plc(int lostFrames, void* output, int outputCapacity)
|
size_t AmrNbCodec::plc(int lostFrames, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
if (outputCapacity < lostFrames * pcmLength())
|
if (output.size_bytes() < lostFrames * pcmLength())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
short* dataOut = (short*)output;
|
short* dataOut = (short*)output.data();
|
||||||
|
|
||||||
for (int i=0; i < lostFrames; i++)
|
for (int i=0; i < lostFrames; i++)
|
||||||
{
|
{
|
||||||
@@ -510,11 +494,9 @@ PCodec AmrWbCodec::CodecFactory::create()
|
|||||||
AmrWbStatistics MT::GAmrWbStatistics;
|
AmrWbStatistics MT::GAmrWbStatistics;
|
||||||
|
|
||||||
AmrWbCodec::AmrWbCodec(const AmrCodecConfig& config)
|
AmrWbCodec::AmrWbCodec(const AmrCodecConfig& config)
|
||||||
:mEncoderCtx(nullptr), mDecoderCtx(nullptr), mConfig(config),
|
:mConfig(config)
|
||||||
mSwitchCounter(0), mPreviousPacketLength(0)
|
|
||||||
{
|
{
|
||||||
mDecoderCtx = D_IF_init();
|
mDecoderCtx = D_IF_init();
|
||||||
mCurrentDecoderTimestamp = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AmrWbCodec::~AmrWbCodec()
|
AmrWbCodec::~AmrWbCodec()
|
||||||
@@ -532,34 +514,22 @@ AmrWbCodec::~AmrWbCodec()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* AmrWbCodec::name()
|
Codec::Info AmrWbCodec::info() {
|
||||||
{
|
return {
|
||||||
return MT_AMRWB_CODECNAME;
|
.mName = MT_AMRWB_CODECNAME,
|
||||||
|
.mSamplerate = 16000,
|
||||||
|
.mChannels = 1,
|
||||||
|
.mPcmLength = 20 * 16 * 2,
|
||||||
|
.mFrameTime = 20,
|
||||||
|
.mRtpLength = 0 /* There is complex structure inside AMR packet which may include multilple frames with various length. */
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int AmrWbCodec::pcmLength()
|
|
||||||
{
|
|
||||||
return 20 * 16 * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AmrWbCodec::rtpLength()
|
Codec::EncodeResult AmrWbCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
return 0; // VBR
|
// Still no support for encoding - emit silence instead
|
||||||
}
|
return {.mEncoded = 0};
|
||||||
|
|
||||||
int AmrWbCodec::frameTime()
|
|
||||||
{
|
|
||||||
return 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AmrWbCodec::samplerate()
|
|
||||||
{
|
|
||||||
return 16000;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AmrWbCodec::encode(const void* input, int inputBytes, void* output, int outputCapacity)
|
|
||||||
{
|
|
||||||
throw Exception(ERR_NOT_IMPLEMENTED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define L_FRAME 160
|
#define L_FRAME 160
|
||||||
@@ -657,35 +627,36 @@ int AmrWbCodec::decodePlain(std::span<const uint8_t> input, std::span<uint8_t> o
|
|||||||
return dataOutSizeInBytes;
|
return dataOutSizeInBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AmrWbCodec::decode(const void* input, int inputBytes, void* output, int outputCapacity)
|
Codec::DecodeResult AmrWbCodec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
auto inputBuffer = std::span<const uint8_t>((uint8_t*)input, (size_t)inputBytes);
|
|
||||||
auto outputBuffer = std::span<uint8_t>((uint8_t*)output, (size_t)outputCapacity);
|
|
||||||
|
|
||||||
if (mConfig.mIuUP)
|
if (mConfig.mIuUP)
|
||||||
return decodeIuup(inputBuffer, outputBuffer);
|
return {.mDecoded = (size_t)decodeIuup(input, output)};
|
||||||
else
|
else
|
||||||
return decodePlain(inputBuffer, outputBuffer);
|
return {.mDecoded = (size_t)decodePlain(input, output)};
|
||||||
|
|
||||||
return 0;
|
return {.mDecoded = 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
int AmrWbCodec::plc(int lostFrames, void* output, int outputCapacity)
|
size_t AmrWbCodec::plc(int lostFrames, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
/* if (outputCapacity < lostFrames * pcmLength())
|
// ToDo: Check again if PLC works for AMR-WB
|
||||||
return 0;
|
// For now return the silence
|
||||||
|
memset(output.data(), 0, output.size_bytes());
|
||||||
short* dataOut = (short*)output;
|
|
||||||
|
|
||||||
for (int i=0; i < lostFrames; i++)
|
|
||||||
{
|
|
||||||
unsigned char buffer[32];
|
|
||||||
buffer[0] = (AMR_BITRATE_DTX << 3)|4;
|
|
||||||
Decoder_Interface_Decode(mDecoderCtx, buffer, dataOut, 0); // Handle missing data
|
|
||||||
dataOut += L_FRAME;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return lostFrames * pcmLength();
|
return lostFrames * pcmLength();
|
||||||
|
/*
|
||||||
|
if (outputCapacity < lostFrames * pcmLength())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
short* dataOut = (short*)output;
|
||||||
|
|
||||||
|
for (int i=0; i < lostFrames; i++)
|
||||||
|
{
|
||||||
|
unsigned char buffer[32];
|
||||||
|
buffer[0] = (AMR_BITRATE_DTX << 3)|4;
|
||||||
|
Decoder_Interface_Decode(mDecoderCtx, buffer, dataOut, 0); // Handle missing data
|
||||||
|
dataOut += L_FRAME;
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
int AmrWbCodec::getSwitchCounter() const
|
int AmrWbCodec::getSwitchCounter() const
|
||||||
@@ -702,9 +673,7 @@ int AmrWbCodec::getCngCounter() const
|
|||||||
|
|
||||||
GsmEfrCodec::GsmEfrFactory::GsmEfrFactory(bool iuup, int ptype)
|
GsmEfrCodec::GsmEfrFactory::GsmEfrFactory(bool iuup, int ptype)
|
||||||
:mIuUP(iuup), mPayloadType(ptype)
|
:mIuUP(iuup), mPayloadType(ptype)
|
||||||
{
|
{}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* GsmEfrCodec::GsmEfrFactory::name()
|
const char* GsmEfrCodec::GsmEfrFactory::name()
|
||||||
{
|
{
|
||||||
@@ -722,9 +691,7 @@ int GsmEfrCodec::GsmEfrFactory::payloadType()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GsmEfrCodec::GsmEfrFactory::updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
|
void GsmEfrCodec::GsmEfrFactory::updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
|
||||||
{
|
{}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int GsmEfrCodec::GsmEfrFactory::processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
|
int GsmEfrCodec::GsmEfrFactory::processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
|
||||||
{
|
{
|
||||||
@@ -742,7 +709,7 @@ PCodec GsmEfrCodec::GsmEfrFactory::create()
|
|||||||
}
|
}
|
||||||
|
|
||||||
GsmEfrCodec::GsmEfrCodec(bool iuup)
|
GsmEfrCodec::GsmEfrCodec(bool iuup)
|
||||||
:mEncoderCtx(nullptr), mDecoderCtx(nullptr), mIuUP(iuup)
|
:mIuUP(iuup)
|
||||||
{
|
{
|
||||||
mEncoderCtx = Encoder_Interface_init(1);
|
mEncoderCtx = Encoder_Interface_init(1);
|
||||||
mDecoderCtx = Decoder_Interface_init();
|
mDecoderCtx = Decoder_Interface_init();
|
||||||
@@ -763,44 +730,31 @@ GsmEfrCodec::~GsmEfrCodec()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GsmEfrCodec::name()
|
Codec::Info GsmEfrCodec::info()
|
||||||
{
|
{
|
||||||
return MT_GSMEFR_CODECNAME;
|
return {
|
||||||
|
.mName = MT_GSMEFR_CODECNAME,
|
||||||
|
.mSamplerate = 8000,
|
||||||
|
.mChannels = 1,
|
||||||
|
.mPcmLength = 20 * 16,
|
||||||
|
.mFrameTime = 20,
|
||||||
|
.mRtpLength = 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int GsmEfrCodec::pcmLength()
|
Codec::EncodeResult GsmEfrCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
return 20 * 16;
|
if (input.size_bytes() % pcmLength())
|
||||||
}
|
return {.mEncoded = 0};
|
||||||
|
|
||||||
int GsmEfrCodec::rtpLength()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GsmEfrCodec::frameTime()
|
|
||||||
{
|
|
||||||
return 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GsmEfrCodec::samplerate()
|
|
||||||
{
|
|
||||||
return 8000;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GsmEfrCodec::encode(const void* input, int inputBytes, void* output, int outputCapacity)
|
|
||||||
{
|
|
||||||
if (inputBytes % pcmLength())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Declare the data input pointer
|
// Declare the data input pointer
|
||||||
const short *dataIn = (const short *)input;
|
const short *dataIn = (const short *)input.data();
|
||||||
|
|
||||||
// Declare the data output pointer
|
// Declare the data output pointer
|
||||||
unsigned char *dataOut = (unsigned char *)output;
|
unsigned char *dataOut = (unsigned char *)output.data();
|
||||||
|
|
||||||
// Find how much RTP frames will be generated
|
// Find how much RTP frames will be generated
|
||||||
unsigned int frames = inputBytes / pcmLength();
|
unsigned int frames = input.size_bytes() / pcmLength();
|
||||||
|
|
||||||
// Generate frames
|
// Generate frames
|
||||||
for (unsigned int i = 0; i < frames; i++)
|
for (unsigned int i = 0; i < frames; i++)
|
||||||
@@ -809,7 +763,7 @@ int GsmEfrCodec::encode(const void* input, int inputBytes, void* output, int out
|
|||||||
dataIn += pcmLength() / 2;
|
dataIn += pcmLength() / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return frames * rtpLength();
|
return {.mEncoded = frames * rtpLength()};
|
||||||
}
|
}
|
||||||
|
|
||||||
#define L_FRAME 160
|
#define L_FRAME 160
|
||||||
@@ -866,100 +820,61 @@ const uint16_t gsm690_12_2_bitorder[244] = {
|
|||||||
237, 236, 96, 199,
|
237, 236, 96, 199,
|
||||||
};
|
};
|
||||||
|
|
||||||
int GsmEfrCodec::decode(const void* input, int inputBytes, void* output, int outputCapacity)
|
Codec::DecodeResult GsmEfrCodec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
/* if (mIuUP)
|
if (output.size_bytes() < pcmLength())
|
||||||
{
|
return {.mDecoded = 0};
|
||||||
// Try to parse IuUP frame
|
|
||||||
IuUP::Frame frame;
|
|
||||||
if (!IuUP::parse2((const uint8_t*)input, inputBytes, frame))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Check if CRC failed - it is check from IuUP data
|
if (input.size_bytes() == 0)
|
||||||
if (!frame.mHeaderCrcOk || !frame.mPayloadCrcOk)
|
{ // PLC part
|
||||||
{
|
unsigned char buffer[32];
|
||||||
ICELogInfo(<< "CRC check failed.");
|
buffer[0] = (AMR_BITRATE_DTX << 3)|4;
|
||||||
return 0;
|
Decoder_Interface_Decode(mDecoderCtx, buffer, (short*)output.data(), 0); // Handle missing data
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Build NB frame to decode
|
|
||||||
ByteBuffer dataToDecode;
|
|
||||||
dataToDecode.resize(1 + frame.mPayloadSize); // Reserve place
|
|
||||||
|
|
||||||
// Copy AMR data
|
|
||||||
memmove(dataToDecode.mutableData() + 1, frame.mPayload, frame.mPayloadSize);
|
|
||||||
|
|
||||||
uint8_t frameType = 0xFF;
|
|
||||||
for (uint8_t ftIndex = 0; ftIndex <= 9 && frameType == 0xFF; ftIndex++)
|
|
||||||
if (amrnb_framelen[ftIndex] == frame.mPayloadSize)
|
|
||||||
frameType = ftIndex;
|
|
||||||
|
|
||||||
// Check if frameType comparing is correct
|
|
||||||
if (frameType == 0xFF)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
dataToDecode.mutableData()[0] = (frameType << 3) | (1 << 2);
|
|
||||||
|
|
||||||
Decoder_Interface_Decode(mDecoderCtx, (const unsigned char*)dataToDecode.data(), (short*)output, 0);
|
|
||||||
return pcmLength();
|
|
||||||
}
|
|
||||||
else */
|
|
||||||
{
|
{
|
||||||
if (outputCapacity < pcmLength())
|
// Reorder bytes from input to dst
|
||||||
return 0;
|
uint8_t dst[GSM_EFR_FRAME_LEN];
|
||||||
|
const uint8_t* src = input.data();
|
||||||
|
for (int i=0; i<(GSM_EFR_FRAME_LEN-1); i++)
|
||||||
|
dst[i] = (src[i] << 4) | (src[i+1] >> 4);
|
||||||
|
dst[GSM_EFR_FRAME_LEN-1] = src[GSM_EFR_FRAME_LEN-1] << 4;
|
||||||
|
|
||||||
if (inputBytes == 0)
|
unsigned char in[GSM_EFR_FRAME_LEN + 1];
|
||||||
{ // PLC part
|
|
||||||
unsigned char buffer[32];
|
// Reorder bits
|
||||||
buffer[0] = (AMR_BITRATE_DTX << 3)|4;
|
in[0] = 0x3c; /* AMR mode 7 = GSM-EFR, Quality bit is set */
|
||||||
Decoder_Interface_Decode(mDecoderCtx, buffer, (short*)output, 0); // Handle missing data
|
in[GSM_EFR_FRAME_LEN] = 0x0;
|
||||||
}
|
|
||||||
else
|
for (int i=0; i<244; i++)
|
||||||
{
|
{
|
||||||
// Reorder bytes from input to dst
|
int si = gsm690_12_2_bitorder[i];
|
||||||
uint8_t dst[GSM_EFR_FRAME_LEN];
|
int di = i;
|
||||||
const uint8_t* src = (const uint8_t*)input;
|
msb_put_bit(in + 1, di, msb_get_bit(dst, si));
|
||||||
for (int i=0; i<(GSM_EFR_FRAME_LEN-1); i++)
|
}
|
||||||
dst[i] = (src[i] << 4) | (src[i+1] >> 4);
|
|
||||||
dst[GSM_EFR_FRAME_LEN-1] = src[GSM_EFR_FRAME_LEN-1] << 4;
|
|
||||||
|
|
||||||
unsigned char in[GSM_EFR_FRAME_LEN + 1];
|
// Decode
|
||||||
|
memset(output.data(), 0, pcmLength());
|
||||||
|
Decoder_Interface_Decode(mDecoderCtx, in, (short*)output.data(), 0);
|
||||||
|
|
||||||
// Reorder bits
|
uint8_t* pcm = (uint8_t*)output.data();
|
||||||
in[0] = 0x3c; /* AMR mode 7 = GSM-EFR, Quality bit is set */
|
for (int i=0; i<160; i++)
|
||||||
in[GSM_EFR_FRAME_LEN] = 0x0;
|
{
|
||||||
|
uint16_t w = ((uint16_t*)output.data())[i];
|
||||||
for (int i=0; i<244; i++)
|
pcm[(i<<1) ] = w & 0xff;
|
||||||
{
|
pcm[(i<<1)+1] = (w >> 8) & 0xff;
|
||||||
int si = gsm690_12_2_bitorder[i];
|
|
||||||
int di = i;
|
|
||||||
msb_put_bit(in + 1, di, msb_get_bit(dst, si));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode
|
|
||||||
memset(output, 0, pcmLength());
|
|
||||||
Decoder_Interface_Decode(mDecoderCtx, in, (short*)output, 0);
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t* pcm = (uint8_t*)output;
|
|
||||||
for (int i=0; i<160; i++)
|
|
||||||
{
|
|
||||||
uint16_t w = ((uint16_t*)output)[i];
|
|
||||||
pcm[(i<<1) ] = w & 0xff;
|
|
||||||
pcm[(i<<1)+1] = (w >> 8) & 0xff;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pcmLength();
|
return {.mDecoded = (size_t)pcmLength()};
|
||||||
}
|
}
|
||||||
|
|
||||||
int GsmEfrCodec::plc(int lostFrames, void* output, int outputCapacity)
|
size_t GsmEfrCodec::plc(int lostFrames, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
if (outputCapacity < lostFrames * pcmLength())
|
if (output.size_bytes() < lostFrames * pcmLength())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
short* dataOut = (short*)output;
|
short* dataOut = (short*)output.data();
|
||||||
|
|
||||||
for (int i=0; i < lostFrames; i++)
|
for (int i=0; i < lostFrames; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -54,16 +54,14 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
AmrNbCodec(const AmrCodecConfig& config);
|
AmrNbCodec(const AmrCodecConfig& config);
|
||||||
|
~AmrNbCodec();
|
||||||
|
|
||||||
|
Info info() override;
|
||||||
|
|
||||||
|
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
|
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
|
size_t plc(int lostFrames, std::span<uint8_t> output) override;
|
||||||
|
|
||||||
virtual ~AmrNbCodec();
|
|
||||||
const char* name() override;
|
|
||||||
int pcmLength() override;
|
|
||||||
int rtpLength() override;
|
|
||||||
int frameTime() override;
|
|
||||||
int samplerate() override;
|
|
||||||
int encode(const void* input, int inputBytes, void* output, int outputCapacity) override;
|
|
||||||
int decode(const void* input, int inputBytes, void* output, int outputCapacity) override;
|
|
||||||
int plc(int lostFrames, void* output, int outputCapacity) override;
|
|
||||||
int getSwitchCounter() const;
|
int getSwitchCounter() const;
|
||||||
int getCngCounter() const;
|
int getCngCounter() const;
|
||||||
};
|
};
|
||||||
@@ -113,14 +111,11 @@ public:
|
|||||||
AmrWbCodec(const AmrCodecConfig& config);
|
AmrWbCodec(const AmrCodecConfig& config);
|
||||||
virtual ~AmrWbCodec();
|
virtual ~AmrWbCodec();
|
||||||
|
|
||||||
const char* name() override;
|
Info info() override;
|
||||||
int pcmLength() override;
|
|
||||||
int rtpLength() override;
|
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
int frameTime() override;
|
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
int samplerate() override;
|
size_t plc(int lostFrames, std::span<uint8_t> output) override;
|
||||||
int encode(const void* input, int inputBytes, void* output, int outputCapacity) override;
|
|
||||||
int decode(const void* input, int inputBytes, void* output, int outputCapacity) override;
|
|
||||||
int plc(int lostFrames, void* output, int outputCapacity) override;
|
|
||||||
int getSwitchCounter() const;
|
int getSwitchCounter() const;
|
||||||
int getCngCounter() const;
|
int getCngCounter() const;
|
||||||
};
|
};
|
||||||
@@ -147,23 +142,19 @@ public:
|
|||||||
void create(CodecMap& codecs) override;
|
void create(CodecMap& codecs) override;
|
||||||
|
|
||||||
PCodec create() override;
|
PCodec create() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool mIuUP;
|
bool mIuUP;
|
||||||
int mPayloadType;
|
int mPayloadType;
|
||||||
};
|
};
|
||||||
|
|
||||||
GsmEfrCodec(bool iuup = false);
|
GsmEfrCodec(bool iuup = false);
|
||||||
|
~GsmEfrCodec();
|
||||||
|
|
||||||
virtual ~GsmEfrCodec();
|
Info info() override;
|
||||||
const char* name() override;
|
|
||||||
int pcmLength() override;
|
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
int rtpLength() override;
|
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
int frameTime() override;
|
size_t plc(int lostFrames, std::span<uint8_t> output) override;
|
||||||
int samplerate() override;
|
|
||||||
int encode(const void* input, int inputBytes, void* output, int outputCapacity) override;
|
|
||||||
int decode(const void* input, int inputBytes, void* output, int outputCapacity) override;
|
|
||||||
int plc(int lostFrames, void* output, int outputCapacity) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of MT namespace
|
} // End of MT namespace
|
||||||
|
|||||||
@@ -91,38 +91,20 @@ G729Codec::~G729Codec()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* G729Codec::name()
|
Codec::Info G729Codec::info()
|
||||||
{
|
{
|
||||||
return "G729";
|
return {
|
||||||
}
|
.mName = "G729",
|
||||||
|
.mSamplerate = 8000,
|
||||||
int G729Codec::pcmLength()
|
.mChannels = 1,
|
||||||
{
|
.mPcmLength = 10 * 8 * 2,
|
||||||
return 10 * 8 * 2;
|
.mFrameTime = 10,
|
||||||
}
|
.mRtpLength = 10
|
||||||
|
};
|
||||||
int G729Codec::rtpLength()
|
|
||||||
{
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
int G729Codec::frameTime()
|
|
||||||
{
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
int G729Codec::samplerate()
|
|
||||||
{
|
|
||||||
return 8000;
|
|
||||||
}
|
|
||||||
|
|
||||||
int G729Codec::channels()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// static const int SamplesPerFrame = 80;
|
// static const int SamplesPerFrame = 80;
|
||||||
int G729Codec::encode(const void* input, int inputBytes, void* output, int outputCapacity)
|
Codec::EncodeResult G729Codec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
// Create encoder if it is not done yet
|
// Create encoder if it is not done yet
|
||||||
if (!mEncoder)
|
if (!mEncoder)
|
||||||
@@ -131,24 +113,24 @@ int G729Codec::encode(const void* input, int inputBytes, void* output, int outpu
|
|||||||
if (mEncoder)
|
if (mEncoder)
|
||||||
Init_Pre_Process(mEncoder);
|
Init_Pre_Process(mEncoder);
|
||||||
}
|
}
|
||||||
int result = 0;
|
size_t result = 0;
|
||||||
if (mEncoder)
|
if (mEncoder)
|
||||||
{
|
{
|
||||||
int nrOfFrames = inputBytes / 160; // 10ms frames
|
int nrOfFrames = input.size_bytes() / 160; // 10ms frames
|
||||||
Word16 parm[PRM_SIZE]; // ITU's service buffer
|
Word16 parm[PRM_SIZE]; // ITU's service buffer
|
||||||
for (int frameIndex = 0; frameIndex < nrOfFrames; frameIndex++)
|
for (int frameIndex = 0; frameIndex < nrOfFrames; frameIndex++)
|
||||||
{
|
{
|
||||||
Copy((int16_t*)input + frameIndex * pcmLength() / 2, mEncoder->new_speech, pcmLength() / 2);
|
Copy((int16_t*)input.data() + frameIndex * info().mPcmLength / 2, mEncoder->new_speech, info().mPcmLength / 2);
|
||||||
Pre_Process(mEncoder, mEncoder->new_speech, pcmLength() / 2);
|
Pre_Process(mEncoder, mEncoder->new_speech, info().mPcmLength / 2);
|
||||||
Coder_ld8a(mEncoder, parm);
|
Coder_ld8a(mEncoder, parm);
|
||||||
Store_Params(parm, (uint8_t*)output + frameIndex * rtpLength());
|
Store_Params(parm, output.data() + frameIndex * info().mRtpLength);
|
||||||
result += rtpLength();
|
result += info().mRtpLength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return {result};
|
||||||
}
|
}
|
||||||
|
|
||||||
int G729Codec::decode(const void* input, int inputBytes, void* output, int outputCapacity)
|
Codec::DecodeResult G729Codec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
if (!mDecoder)
|
if (!mDecoder)
|
||||||
{
|
{
|
||||||
@@ -160,29 +142,29 @@ int G729Codec::decode(const void* input, int inputBytes, void* output, int outpu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = 0;
|
size_t result = 0;
|
||||||
if (mDecoder)
|
if (mDecoder)
|
||||||
{
|
{
|
||||||
// See if there are silence bytes in the end
|
// See if there are silence bytes in the end
|
||||||
bool isSilence = (inputBytes % rtpLength()) / 2 != 0;
|
bool isSilence = (input.size_bytes() % info().mRtpLength) / 2 != 0;
|
||||||
|
|
||||||
// Find number of frames
|
// Find number of frames
|
||||||
int nrOfFrames = inputBytes / rtpLength();
|
int nrOfFrames = input.size_bytes() / info().mRtpLength;
|
||||||
nrOfFrames = std::min(outputCapacity / pcmLength(), nrOfFrames);
|
nrOfFrames = std::min(output.size_bytes() / info().mPcmLength, (size_t)nrOfFrames);
|
||||||
|
|
||||||
for (int frameIndex = 0; frameIndex < nrOfFrames; frameIndex++)
|
for (int frameIndex = 0; frameIndex < nrOfFrames; frameIndex++)
|
||||||
decodeFrame((const uint8_t*)input + frameIndex * rtpLength(), (int16_t*)output + frameIndex * pcmLength());
|
decodeFrame(input.data() + frameIndex * info().mRtpLength, (int16_t*)output.data() + frameIndex * info().mPcmLength);
|
||||||
|
|
||||||
result += nrOfFrames * pcmLength();
|
result += nrOfFrames * info().mPcmLength;
|
||||||
|
|
||||||
if (isSilence && nrOfFrames < outputCapacity / pcmLength())
|
if (isSilence && nrOfFrames < output.size_bytes() / info().mPcmLength)
|
||||||
{
|
{
|
||||||
memset((uint8_t*)output + nrOfFrames * pcmLength(), 0, pcmLength());
|
memset(output.data() + nrOfFrames * info().mPcmLength, 0, info().mPcmLength);
|
||||||
result += pcmLength();
|
result += info().mPcmLength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return {.mDecoded = result, .mIsCng = false};
|
||||||
}
|
}
|
||||||
|
|
||||||
void G729Codec::decodeFrame(const uint8_t* rtp, int16_t* pcm)
|
void G729Codec::decodeFrame(const uint8_t* rtp, int16_t* pcm)
|
||||||
@@ -217,7 +199,7 @@ void G729Codec::decodeFrame(const uint8_t* rtp, int16_t* pcm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int G729Codec::plc(int lostFrames, void* output, int outputCapacity)
|
size_t G729Codec::plc(int lostFrames, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -390,7 +372,7 @@ int OpusCodec::OpusFactory::processSdp(const resip::SdpContents::Session::Medium
|
|||||||
|
|
||||||
PCodec OpusCodec::OpusFactory::create()
|
PCodec OpusCodec::OpusFactory::create()
|
||||||
{
|
{
|
||||||
OpusCodec* result = new OpusCodec(mSamplerate, mChannels, mParams.mPtime);
|
OpusCodec* result = new OpusCodec(Audio::Format(mSamplerate, mChannels), mParams.mPtime);
|
||||||
result->applyParams(mParams);
|
result->applyParams(mParams);
|
||||||
PCodec c(result);
|
PCodec c(result);
|
||||||
mCodecList.push_back(c);
|
mCodecList.push_back(c);
|
||||||
@@ -398,8 +380,8 @@ PCodec OpusCodec::OpusFactory::create()
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpusCodec::OpusCodec(int samplerate, int channels, int ptime)
|
OpusCodec::OpusCodec(Audio::Format fmt, int ptime)
|
||||||
:mEncoderCtx(nullptr), mDecoderCtx(nullptr), mChannels(channels), mPTime(ptime), mSamplerate(samplerate), mDecoderChannels(0)
|
:mEncoderCtx(nullptr), mDecoderCtx(nullptr), mChannels(fmt.channels()), mPTime(ptime), mSamplerate(fmt.rate()), mDecoderChannels(0)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
mEncoderCtx = opus_encoder_create(mSamplerate, mChannels, OPUS_APPLICATION_VOIP, &status);
|
mEncoderCtx = opus_encoder_create(mSamplerate, mChannels, OPUS_APPLICATION_VOIP, &status);
|
||||||
@@ -441,52 +423,34 @@ OpusCodec::~OpusCodec()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* OpusCodec::name()
|
Codec::Info OpusCodec::info() {
|
||||||
{
|
return {
|
||||||
return OPUS_CODEC_NAME;
|
.mName = OPUS_CODEC_NAME,
|
||||||
|
.mSamplerate = mSamplerate,
|
||||||
|
.mChannels = mChannels,
|
||||||
|
.mPcmLength = (int)(mSamplerate / 1000 * sizeof(short) * mChannels * mPTime),
|
||||||
|
.mFrameTime = mPTime,
|
||||||
|
.mRtpLength = 0 /* VBR */
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int OpusCodec::pcmLength()
|
Codec::EncodeResult OpusCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
|
||||||
return (samplerate() / 1000 ) * frameTime() * sizeof(short) * channels();
|
|
||||||
}
|
|
||||||
|
|
||||||
int OpusCodec::channels()
|
|
||||||
{
|
|
||||||
return mChannels;
|
|
||||||
}
|
|
||||||
|
|
||||||
int OpusCodec::rtpLength()
|
|
||||||
{
|
|
||||||
return 0; // VBR
|
|
||||||
}
|
|
||||||
|
|
||||||
int OpusCodec::frameTime()
|
|
||||||
{
|
|
||||||
return mPTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
int OpusCodec::samplerate()
|
|
||||||
{
|
|
||||||
return mSamplerate;
|
|
||||||
}
|
|
||||||
|
|
||||||
int OpusCodec::encode(const void* input, int inputBytes, void* output, int outputCapacity)
|
|
||||||
{
|
{
|
||||||
// Send number of samples for input and number of bytes for output
|
// Send number of samples for input and number of bytes for output
|
||||||
int written = opus_encode(mEncoderCtx, (const opus_int16*)input, inputBytes / (sizeof(short) * channels()), (unsigned char*)output, outputCapacity / (sizeof(short) * channels()));
|
int written = opus_encode(mEncoderCtx, (const opus_int16*)input.data(), input.size_bytes() / (sizeof(short) * channels()),
|
||||||
|
output.data(), output.size_bytes() / (sizeof(short) * channels()));
|
||||||
if (written < 0)
|
if (written < 0)
|
||||||
return 0;
|
return {.mEncoded = 0};
|
||||||
else
|
else
|
||||||
return written;
|
return {.mEncoded = (size_t)written};
|
||||||
}
|
}
|
||||||
|
|
||||||
int OpusCodec::decode(const void* input, int inputBytes, void* output, int outputCapacity)
|
Codec::DecodeResult OpusCodec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
// Examine the number of channels available in incoming packet
|
// Examine the number of channels available in incoming packet
|
||||||
int nr_of_channels = opus_packet_get_nb_channels((const unsigned char *) input);
|
int nr_of_channels = opus_packet_get_nb_channels(input.data());
|
||||||
|
|
||||||
// Recreate decoder if needed
|
// Recreate decoder if needed
|
||||||
if (mDecoderChannels != nr_of_channels)
|
if (mDecoderChannels != nr_of_channels)
|
||||||
@@ -504,24 +468,22 @@ int OpusCodec::decode(const void* input, int inputBytes, void* output, int outpu
|
|||||||
int status = 0;
|
int status = 0;
|
||||||
mDecoderCtx = opus_decoder_create(mSamplerate, mDecoderChannels, &status);
|
mDecoderCtx = opus_decoder_create(mSamplerate, mDecoderChannels, &status);
|
||||||
if (status)
|
if (status)
|
||||||
return 0;
|
return {0};
|
||||||
}
|
}
|
||||||
|
|
||||||
int nr_of_frames = opus_decoder_get_nb_samples(mDecoderCtx, (const unsigned char *) input,
|
int nr_of_frames = opus_decoder_get_nb_samples(mDecoderCtx, input.data(), input.size_bytes());
|
||||||
inputBytes);
|
|
||||||
if (nr_of_frames <= 0)
|
if (nr_of_frames <= 0)
|
||||||
return 0;
|
return {0};
|
||||||
|
|
||||||
// We support stereo and mono here.
|
// We support stereo and mono here.
|
||||||
int buffer_capacity = nr_of_frames * sizeof(opus_int16) * nr_of_channels;
|
int buffer_capacity = nr_of_frames * sizeof(opus_int16) * nr_of_channels;
|
||||||
opus_int16 *buffer_decode = (opus_int16 *)alloca(buffer_capacity);
|
opus_int16 *buffer_decode = (opus_int16 *)alloca(buffer_capacity);
|
||||||
int decoded = opus_decode(mDecoderCtx,
|
int decoded = opus_decode(mDecoderCtx, input.data(), input.size_bytes(),
|
||||||
reinterpret_cast<const unsigned char *>(input), inputBytes,
|
|
||||||
buffer_decode, nr_of_frames, 0);
|
buffer_decode, nr_of_frames, 0);
|
||||||
if (decoded < 0)
|
if (decoded < 0)
|
||||||
{
|
{
|
||||||
ICELogCritical(<< "opus_decode() returned " << decoded);
|
ICELogCritical(<< "opus_decode() returned " << decoded);
|
||||||
return 0;
|
return {0};
|
||||||
}
|
}
|
||||||
|
|
||||||
opus_int16 *buffer_stereo = nullptr;
|
opus_int16 *buffer_stereo = nullptr;
|
||||||
@@ -535,14 +497,14 @@ int OpusCodec::decode(const void* input, int inputBytes, void* output, int outpu
|
|||||||
buffer_stereo[i * 2 + 1] = buffer_decode[i];
|
buffer_stereo[i * 2 + 1] = buffer_decode[i];
|
||||||
buffer_stereo[i * 2] = buffer_decode[i];
|
buffer_stereo[i * 2] = buffer_decode[i];
|
||||||
}
|
}
|
||||||
assert(buffer_stereo_capacity <= outputCapacity);
|
assert(buffer_stereo_capacity <= output.size_bytes());
|
||||||
memcpy(output, buffer_stereo, buffer_stereo_capacity);
|
memcpy(output.data(), buffer_stereo, buffer_stereo_capacity);
|
||||||
result = buffer_stereo_capacity;
|
result = buffer_stereo_capacity;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
assert(buffer_capacity <= outputCapacity);
|
assert(buffer_capacity <= output.size_bytes());
|
||||||
memcpy(output, buffer_decode, buffer_capacity);
|
memcpy(output.data(), buffer_decode, buffer_capacity);
|
||||||
result = buffer_capacity;
|
result = buffer_capacity;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -550,17 +512,17 @@ int OpusCodec::decode(const void* input, int inputBytes, void* output, int outpu
|
|||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return {.mDecoded = (size_t)result};
|
||||||
}
|
}
|
||||||
|
|
||||||
int OpusCodec::plc(int lostPackets, void* output, int outputCapacity)
|
size_t OpusCodec::plc(int lostPackets, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
// Find how much frames do we need to produce and prefill it with silence
|
// Find how much frames do we need to produce and prefill it with silence
|
||||||
int frames_per_packet = (int)pcmLength() / (sizeof(opus_int16) * channels());
|
int frames_per_packet = (int)pcmLength() / (sizeof(opus_int16) * channels());
|
||||||
memset(output, 0, outputCapacity);
|
memset(output.data(), 0, output.size_bytes());
|
||||||
|
|
||||||
// Use this pointer as output
|
// Use this pointer as output
|
||||||
opus_int16* data_output = reinterpret_cast<opus_int16*>(output);
|
opus_int16* data_output = reinterpret_cast<opus_int16*>(output.data());
|
||||||
|
|
||||||
int nr_of_decoded_frames = 0;
|
int nr_of_decoded_frames = 0;
|
||||||
|
|
||||||
@@ -575,10 +537,7 @@ int OpusCodec::plc(int lostPackets, void* output, int outputCapacity)
|
|||||||
case 1:
|
case 1:
|
||||||
// Convert mono to stereo
|
// Convert mono to stereo
|
||||||
for (int i=0; i < nr_of_decoded_frames; i++)
|
for (int i=0; i < nr_of_decoded_frames; i++)
|
||||||
{
|
data_output[i * 2] = data_output[i * 2 + 1] = buffer_plc[i];
|
||||||
data_output[i * 2] = buffer_plc[i];
|
|
||||||
data_output[i * 2 + 1] = buffer_plc[i+1];
|
|
||||||
}
|
|
||||||
data_output += frames_per_packet * mChannels;
|
data_output += frames_per_packet * mChannels;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -589,14 +548,14 @@ int OpusCodec::plc(int lostPackets, void* output, int outputCapacity)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ((char*)data_output - (char*)output) * sizeof(opus_int16);
|
return ((uint8_t*)data_output - output.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------- ILBC -------------------
|
// -------------- ILBC -------------------
|
||||||
#define ILBC_CODEC_NAME "ILBC"
|
#define ILBC_CODEC_NAME "ILBC"
|
||||||
|
|
||||||
IlbcCodec::IlbcCodec(int packetTime)
|
IlbcCodec::IlbcCodec(int packetTime)
|
||||||
:mPacketTime(packetTime), mEncoderCtx(nullptr), mDecoderCtx(nullptr)
|
:mPacketTime(packetTime)
|
||||||
{
|
{
|
||||||
WebRtcIlbcfix_EncoderCreate(&mEncoderCtx);
|
WebRtcIlbcfix_EncoderCreate(&mEncoderCtx);
|
||||||
WebRtcIlbcfix_DecoderCreate(&mDecoderCtx);
|
WebRtcIlbcfix_DecoderCreate(&mDecoderCtx);
|
||||||
@@ -610,44 +569,31 @@ IlbcCodec::~IlbcCodec()
|
|||||||
WebRtcIlbcfix_EncoderFree(mEncoderCtx);
|
WebRtcIlbcfix_EncoderFree(mEncoderCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* IlbcCodec::name()
|
Codec::Info IlbcCodec::info()
|
||||||
{
|
{
|
||||||
return "ilbc";
|
return {
|
||||||
|
.mName = ILBC_CODEC_NAME,
|
||||||
|
.mSamplerate = 8000,
|
||||||
|
.mChannels = 1,
|
||||||
|
.mPcmLength = mPacketTime * 8 * (int)sizeof(short),
|
||||||
|
.mFrameTime = mPacketTime,
|
||||||
|
.mRtpLength = (mPacketTime == 20) ? 38 : 50
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int IlbcCodec::rtpLength()
|
Codec::EncodeResult IlbcCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
return (mPacketTime == 20 ) ? 38 : 50;
|
if (input.size_bytes() % pcmLength())
|
||||||
}
|
|
||||||
|
|
||||||
int IlbcCodec::pcmLength()
|
|
||||||
{
|
|
||||||
return mPacketTime * 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
int IlbcCodec::frameTime()
|
|
||||||
{
|
|
||||||
return mPacketTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
int IlbcCodec::samplerate()
|
|
||||||
{
|
|
||||||
return 8000;
|
|
||||||
}
|
|
||||||
|
|
||||||
Codec::EncodeResult IlbcCodec::encode(const void *input, int inputBytes, void* outputBuffer, int outputCapacity)
|
|
||||||
{
|
|
||||||
if (inputBytes % pcmLength())
|
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
// Declare the data input pointer
|
// Declare the data input pointer
|
||||||
short *dataIn = (short *)input;
|
short *dataIn = (short *)input.data();
|
||||||
|
|
||||||
// Declare the data output pointer
|
// Declare the data output pointer
|
||||||
char *dataOut = (char *)outputBuffer;
|
char *dataOut = (char *)output.data();
|
||||||
|
|
||||||
// Find how much RTP frames will be generated
|
// Find how much RTP frames will be generated
|
||||||
unsigned int frames = inputBytes / pcmLength();
|
unsigned int frames = input.size_bytes() / pcmLength();
|
||||||
|
|
||||||
// Generate frames
|
// Generate frames
|
||||||
for (unsigned int i=0; i<frames; i++)
|
for (unsigned int i=0; i<frames; i++)
|
||||||
@@ -660,12 +606,12 @@ Codec::EncodeResult IlbcCodec::encode(const void *input, int inputBytes, void* o
|
|||||||
return {frames * rtpLength()};
|
return {frames * rtpLength()};
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::DecodeResult IlbcCodec::decode(const void* input, int inputBytes, void* output, int outputCapacity)
|
Codec::DecodeResult IlbcCodec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
unsigned frames = inputBytes / rtpLength();
|
unsigned frames = input.size_bytes() / rtpLength();
|
||||||
|
|
||||||
char* dataIn = (char*)input;
|
char* dataIn = (char*)input.data();
|
||||||
short* dataOut = (short*)output;
|
short* dataOut = (short*)output.data();
|
||||||
|
|
||||||
for (unsigned i=0; i < frames; ++i)
|
for (unsigned i=0; i < frames; ++i)
|
||||||
{
|
{
|
||||||
@@ -678,7 +624,7 @@ Codec::DecodeResult IlbcCodec::decode(const void* input, int inputBytes, void* o
|
|||||||
return {frames * pcmLength()};
|
return {frames * pcmLength()};
|
||||||
}
|
}
|
||||||
|
|
||||||
int IlbcCodec::plc(int lostFrames, std::span<uint8_t> output)
|
size_t IlbcCodec::plc(int lostFrames, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
return sizeof(short) * WebRtcIlbcfix_DecodePlc(mDecoderCtx, (WebRtc_Word16*)output.data(), lostFrames);
|
return sizeof(short) * WebRtcIlbcfix_DecodePlc(mDecoderCtx, (WebRtc_Word16*)output.data(), lostFrames);
|
||||||
}
|
}
|
||||||
@@ -795,38 +741,24 @@ IsacCodec::~IsacCodec()
|
|||||||
WebRtcIsacfix_Free(mDecoderCtx); mDecoderCtx = NULL;
|
WebRtcIsacfix_Free(mDecoderCtx); mDecoderCtx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* IsacCodec::name()
|
Codec::Info IsacCodec::info() {
|
||||||
{
|
return {
|
||||||
return "isac";
|
.mName = "isac",
|
||||||
|
.mSamplerate = mSamplerate,
|
||||||
|
.mChannels = 1,
|
||||||
|
.mPcmLength = 60 * mSamplerate / 1000 * 2,
|
||||||
|
.mFrameTime = 60,
|
||||||
|
.mRtpLength = 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int IsacCodec::frameTime()
|
Codec::EncodeResult IsacCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
return 60;
|
unsigned nrOfSamples = input.size_bytes() / 2;
|
||||||
}
|
|
||||||
|
|
||||||
int IsacCodec::samplerate()
|
|
||||||
{
|
|
||||||
return mSamplerate;
|
|
||||||
}
|
|
||||||
|
|
||||||
int IsacCodec::pcmLength()
|
|
||||||
{
|
|
||||||
return frameTime() * samplerate() / 1000 * sizeof(short);
|
|
||||||
}
|
|
||||||
|
|
||||||
int IsacCodec::rtpLength()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int IsacCodec::encode(const void* input, int inputBytes, void* output, int outputCapacity)
|
|
||||||
{
|
|
||||||
unsigned nrOfSamples = inputBytes / 2;
|
|
||||||
unsigned timeLength = nrOfSamples / (mSamplerate / 1000);
|
unsigned timeLength = nrOfSamples / (mSamplerate / 1000);
|
||||||
int encoded = 0;
|
int encoded = 0;
|
||||||
char* dataOut = (char*)output;
|
char* dataOut = (char*)output.data();
|
||||||
const WebRtc_Word16* dataIn = (const WebRtc_Word16*)input;
|
const WebRtc_Word16* dataIn = (const WebRtc_Word16*)input.data();
|
||||||
|
|
||||||
// Iterate 10 milliseconds chunks
|
// Iterate 10 milliseconds chunks
|
||||||
for (unsigned i=0; i<timeLength/10; i++)
|
for (unsigned i=0; i<timeLength/10; i++)
|
||||||
@@ -835,25 +767,25 @@ int IsacCodec::encode(const void* input, int inputBytes, void* output, int outpu
|
|||||||
if (encoded > 0)
|
if (encoded > 0)
|
||||||
dataOut += encoded;
|
dataOut += encoded;
|
||||||
}
|
}
|
||||||
return dataOut - (char*)output;
|
return {.mEncoded = (size_t)(dataOut - (char*)output.data())};
|
||||||
}
|
}
|
||||||
|
|
||||||
int IsacCodec::decode(const void* input, int inputBytes, void* output, int outputCapacity)
|
Codec::DecodeResult IsacCodec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
WebRtc_Word16 speechType = 0;
|
WebRtc_Word16 speechType = 0;
|
||||||
unsigned produced = WebRtcIsacfix_Decode(mDecoderCtx, (const WebRtc_UWord16*)input, inputBytes, (WebRtc_Word16*)output, &speechType);
|
unsigned produced = WebRtcIsacfix_Decode(mDecoderCtx, (const WebRtc_UWord16*)input.data(), input.size_bytes(), (WebRtc_Word16*)output.data(), &speechType);
|
||||||
if (produced == (unsigned)-1)
|
if (produced == (unsigned)-1)
|
||||||
return 0;
|
return {.mDecoded = 0};
|
||||||
|
|
||||||
return produced * 2;
|
return {.mDecoded = produced * 2};
|
||||||
}
|
}
|
||||||
|
|
||||||
int IsacCodec::plc(int lostFrames, void* output, int outputCapacity)
|
size_t IsacCodec::plc(int lostFrames, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
// lostFrames are 30-milliseconds frames; but used encoding mode is 60 milliseconds.
|
// lostFrames are 30-milliseconds frames; but used encoding mode is 60 milliseconds.
|
||||||
// So lostFrames * 2
|
// So lostFrames * 2
|
||||||
lostFrames *=2 ;
|
lostFrames *=2 ;
|
||||||
if (-1 == WebRtcIsacfix_DecodePlc(mDecoderCtx, (WebRtc_Word16*)output, lostFrames ))
|
if (-1 == WebRtcIsacfix_DecodePlc(mDecoderCtx, (WebRtc_Word16*)output.data(), lostFrames ))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return lostFrames * 30 * (samplerate()/1000 * sizeof(short));
|
return lostFrames * 30 * (samplerate()/1000 * sizeof(short));
|
||||||
@@ -916,71 +848,55 @@ PCodec IsacCodec::IsacFactory32K::create()
|
|||||||
|
|
||||||
G711Codec::G711Codec(int type)
|
G711Codec::G711Codec(int type)
|
||||||
:mType(type)
|
:mType(type)
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
G711Codec::~G711Codec()
|
G711Codec::~G711Codec()
|
||||||
{
|
{}
|
||||||
|
|
||||||
|
Codec::Info G711Codec::info() {
|
||||||
|
return {
|
||||||
|
.mName = mType == ALaw ? "PCMA" : "PCMU",
|
||||||
|
.mSamplerate = 8000,
|
||||||
|
.mChannels = 1,
|
||||||
|
.mPcmLength = 10 * 16,
|
||||||
|
.mFrameTime = 10,
|
||||||
|
.mRtpLength = 10 * 8
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* G711Codec::name()
|
Codec::EncodeResult G711Codec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
|
||||||
return "g711";
|
|
||||||
}
|
|
||||||
|
|
||||||
int G711Codec::pcmLength()
|
|
||||||
{
|
|
||||||
return frameTime() * 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
int G711Codec::rtpLength()
|
|
||||||
{
|
|
||||||
return frameTime() * 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
int G711Codec::frameTime()
|
|
||||||
{
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
int G711Codec::samplerate()
|
|
||||||
{
|
|
||||||
return 8000;
|
|
||||||
}
|
|
||||||
|
|
||||||
int G711Codec::encode(const void* input, int inputBytes, void* output, int outputCapacity)
|
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
if (mType == ALaw)
|
if (mType == ALaw)
|
||||||
result = WebRtcG711_EncodeA(NULL, (WebRtc_Word16*)input, inputBytes/2, (WebRtc_Word16*)output);
|
result = WebRtcG711_EncodeA(nullptr, (WebRtc_Word16*)input.data(), input.size_bytes() / 2, (WebRtc_Word16*)output.data());
|
||||||
else
|
else
|
||||||
result = WebRtcG711_EncodeU(NULL, (WebRtc_Word16*)input, inputBytes/2, (WebRtc_Word16*)output);
|
result = WebRtcG711_EncodeU(nullptr, (WebRtc_Word16*)input.data(), input.size_bytes() / 2, (WebRtc_Word16*)output.data());
|
||||||
|
|
||||||
if (result == -1)
|
if (result < 0)
|
||||||
throw Exception(ERR_WEBRTC, -1);
|
return {.mEncoded = 0};
|
||||||
|
|
||||||
return result;
|
return {.mEncoded = (size_t) result};
|
||||||
}
|
}
|
||||||
|
|
||||||
int G711Codec::decode(const void* input, int inputBytes, void* output, int outputCapacity)
|
Codec::DecodeResult G711Codec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
assert(outputCapacity >= inputBytes * 2);
|
assert(output.size_bytes() >= input.size_bytes() * 2);
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
WebRtc_Word16 speechType;
|
WebRtc_Word16 speechType;
|
||||||
|
|
||||||
if (mType == ALaw)
|
if (mType == ALaw)
|
||||||
result = WebRtcG711_DecodeA(NULL, (WebRtc_Word16*)input, inputBytes, (WebRtc_Word16*)output, &speechType);
|
result = WebRtcG711_DecodeA(nullptr, (WebRtc_Word16*)input.data(), input.size_bytes(), (WebRtc_Word16*)output.data(), &speechType);
|
||||||
else
|
else
|
||||||
result = WebRtcG711_DecodeU(NULL, (WebRtc_Word16*)input, inputBytes, (WebRtc_Word16*)output, &speechType);
|
result = WebRtcG711_DecodeU(nullptr, (WebRtc_Word16*)input.data(), input.size_bytes(), (WebRtc_Word16*)output.data(), &speechType);
|
||||||
|
|
||||||
if (result == -1)
|
if (result < 0)
|
||||||
throw Exception(ERR_WEBRTC, -1);
|
return {.mDecoded = 0};
|
||||||
|
|
||||||
return result * 2;
|
return {.mDecoded = (size_t)result * 2};
|
||||||
}
|
}
|
||||||
|
|
||||||
int G711Codec::plc(int lostSamples, void* output, int outputCapacity)
|
size_t G711Codec::plc(int lostSamples, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1060,86 +976,64 @@ GsmCodec::GsmCodec(Type codecType)
|
|||||||
|
|
||||||
GsmCodec::~GsmCodec()
|
GsmCodec::~GsmCodec()
|
||||||
{
|
{
|
||||||
gsm_destroy(mGSM);
|
gsm_destroy(mGSM); mGSM = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GsmCodec::name()
|
Codec::Info GsmCodec::info() {
|
||||||
{
|
int rtpLength = 0;
|
||||||
return "GSM-06.10";
|
|
||||||
}
|
|
||||||
|
|
||||||
int GsmCodec::rtpLength()
|
|
||||||
{
|
|
||||||
switch (mCodecType)
|
switch (mCodecType)
|
||||||
{
|
{
|
||||||
case Type::Bytes_31:
|
case Type::Bytes_31: rtpLength = GSM_RTPFRAME_SIZE_31; break;
|
||||||
return GSM_RTPFRAME_SIZE_31;
|
case Type::Bytes_32: rtpLength = GSM_RTPFRAME_SIZE_32; break;
|
||||||
break;
|
case Type::Bytes_33: rtpLength = GSM_RTPFRAME_SIZE_33; break;
|
||||||
|
case Type::Bytes_65: rtpLength = GSM_RTPFRAME_SIZE_32 + GSM_RTPFRAME_SIZE_33; break;
|
||||||
case Type::Bytes_32:
|
default: rtpLength = GSM_RTPFRAME_SIZE_33;
|
||||||
return GSM_RTPFRAME_SIZE_32;
|
|
||||||
|
|
||||||
case Type::Bytes_33:
|
|
||||||
return GSM_RTPFRAME_SIZE_33;
|
|
||||||
|
|
||||||
case Type::Bytes_65:
|
|
||||||
return GSM_RTPFRAME_SIZE_32 + GSM_RTPFRAME_SIZE_33;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GSM_RTPFRAME_SIZE_33;
|
return {
|
||||||
|
.mName = "GSM-06.10",
|
||||||
|
.mSamplerate = 8000,
|
||||||
|
.mChannels = 1,
|
||||||
|
.mPcmLength = GSM_AUDIOFRAME_TIME * 16,
|
||||||
|
.mFrameTime = GSM_AUDIOFRAME_TIME,
|
||||||
|
.mRtpLength = rtpLength
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int GsmCodec::pcmLength()
|
Codec::EncodeResult GsmCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
|
||||||
return GSM_AUDIOFRAME_TIME * 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GsmCodec::frameTime()
|
|
||||||
{
|
|
||||||
return GSM_AUDIOFRAME_TIME;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GsmCodec::samplerate()
|
|
||||||
{
|
|
||||||
return 8000;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GsmCodec::encode(const void* input, int inputBytes, void* output, int outputCapacity)
|
|
||||||
{
|
{
|
||||||
int outputBytes = 0;
|
int outputBytes = 0;
|
||||||
|
char* outputBuffer = (char*)output.data();
|
||||||
|
|
||||||
char* outputBuffer = (char*)output;
|
for (int i = 0; i < input.size_bytes() / pcmLength(); i++)
|
||||||
|
|
||||||
for (int i = 0; i < inputBytes/pcmLength(); i++)
|
|
||||||
{
|
{
|
||||||
gsm_encode(mGSM, (gsm_signal *)input+160*i, (gsm_byte*)outputBuffer);
|
gsm_encode(mGSM, (gsm_signal *)input.data()+160*i, (gsm_byte*)outputBuffer);
|
||||||
outputBuffer += rtpLength();
|
outputBuffer += rtpLength();
|
||||||
outputBytes += rtpLength();
|
outputBytes += rtpLength();
|
||||||
}
|
}
|
||||||
return outputBytes;
|
return {.mEncoded = (size_t)outputBytes};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int GsmCodec::decode(const void* input, int inputBytes, void* output, int outputCapacity)
|
Codec::DecodeResult GsmCodec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
if (inputBytes % rtpLength() != 0)
|
if (input.size_bytes() % rtpLength() != 0)
|
||||||
return 0;
|
return {.mDecoded = 0};
|
||||||
|
|
||||||
int i=0;
|
int i=0;
|
||||||
for (i = 0; i < inputBytes/rtpLength(); i++)
|
for (i = 0; i < input.size_bytes() / rtpLength(); i++)
|
||||||
gsm_decode(mGSM, (gsm_byte *)input + 33 * i, (gsm_signal *)output + 160 * i);
|
gsm_decode(mGSM, (gsm_byte *)input.data() + 33 * i, (gsm_signal *)output.data() + 160 * i);
|
||||||
|
|
||||||
return i * 320;
|
return {.mDecoded = (size_t)i * 320};
|
||||||
}
|
}
|
||||||
|
|
||||||
int GsmCodec::plc(int lostFrames, void* output, int outputCapacity)
|
size_t GsmCodec::plc(int lostFrames, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
if (outputCapacity < lostFrames * pcmLength())
|
if (output.size_bytes() < lostFrames * pcmLength())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Return silence frames
|
// Return silence frames
|
||||||
memset(output, 0, lostFrames * pcmLength());
|
memset(output.data(), 0, lostFrames * pcmLength());
|
||||||
return lostFrames * pcmLength();
|
return lostFrames * pcmLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1155,58 +1049,52 @@ G722Codec::G722Codec()
|
|||||||
|
|
||||||
G722Codec::~G722Codec()
|
G722Codec::~G722Codec()
|
||||||
{
|
{
|
||||||
g722_decode_release((g722_decode_state_t*)mDecoder);
|
g722_decode_release((g722_decode_state_t*)mDecoder); mDecoder = nullptr;
|
||||||
g722_encode_release((g722_encode_state_t*)mEncoder);
|
g722_encode_release((g722_encode_state_t*)mEncoder); mEncoder = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* G722Codec::name()
|
Codec::Info G722Codec::info() {
|
||||||
{
|
// ToDo: double check the G722 calls - remember RFC has bug about samplerate
|
||||||
return G722_MIME_NAME;
|
return {
|
||||||
|
.mName = G722_MIME_NAME,
|
||||||
|
.mSamplerate = 8000,
|
||||||
|
.mChannels = 1,
|
||||||
|
.mPcmLength = 640,
|
||||||
|
.mFrameTime = 20,
|
||||||
|
.mRtpLength = 160
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int G722Codec::pcmLength()
|
Codec::EncodeResult G722Codec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
return 640;
|
if (output.size_bytes() < input.size_bytes() / 4)
|
||||||
|
return {.mEncoded = 0}; // Destination buffer not big enough
|
||||||
|
|
||||||
|
int r = g722_encode((g722_encode_state_t *)mEncoder, (unsigned char*)output.data(), ( short*)input.data(), input.size_bytes() / 2);
|
||||||
|
if (r < 0)
|
||||||
|
return {.mEncoded = 0};
|
||||||
|
|
||||||
|
return {.mEncoded = (size_t)r};
|
||||||
}
|
}
|
||||||
|
|
||||||
int G722Codec::frameTime()
|
Codec::DecodeResult G722Codec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
return 20;
|
if (output.size_bytes() < input.size_bytes() * 4)
|
||||||
|
return {.mDecoded = 0}; // Destination buffer not big enough
|
||||||
|
|
||||||
|
int r = g722_decode((g722_decode_state_t *)mDecoder, (short*)output.data(), (unsigned char*)input.data(), input.size_bytes()) * 2;
|
||||||
|
if (r < 0)
|
||||||
|
return {.mDecoded = 0};
|
||||||
|
return {.mDecoded = (size_t)r};
|
||||||
}
|
}
|
||||||
|
|
||||||
int G722Codec::rtpLength()
|
size_t G722Codec::plc(int lostFrames, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
return 160;
|
if (output.size_bytes() < lostFrames * pcmLength())
|
||||||
}
|
|
||||||
|
|
||||||
int G722Codec::samplerate()
|
|
||||||
{
|
|
||||||
return 8000;
|
|
||||||
}
|
|
||||||
|
|
||||||
int G722Codec::encode(const void* input, int inputBytes, void* output, int outputCapacity)
|
|
||||||
{
|
|
||||||
if (outputCapacity < inputBytes / 4)
|
|
||||||
return 0; // Destination buffer not big enough
|
|
||||||
|
|
||||||
return g722_encode((g722_encode_state_t *)mEncoder, (unsigned char*)output, ( short*)input, inputBytes / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
int G722Codec::decode(const void* input, int inputBytes, void* output, int outputCapacity)
|
|
||||||
{
|
|
||||||
if (outputCapacity < inputBytes * 4)
|
|
||||||
return 0; // Destination buffer not big enough
|
|
||||||
|
|
||||||
return g722_decode((g722_decode_state_t *)mDecoder, ( short*)output, (unsigned char*)input, inputBytes) * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
int G722Codec::plc(int lostFrames, void* output, int outputCapacity)
|
|
||||||
{
|
|
||||||
if (outputCapacity < lostFrames * pcmLength())
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Return silence frames
|
// Return silence frames
|
||||||
memset(output, 0, lostFrames * pcmLength());
|
memset(output.data(), 0, lostFrames * pcmLength());
|
||||||
return lostFrames * pcmLength();
|
return lostFrames * pcmLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1318,7 +1206,6 @@ static bool repackHalfRate(BitReader& br, uint16_t frame[22], bool& lastItem)
|
|||||||
}
|
}
|
||||||
|
|
||||||
GsmHrCodec::GsmHrCodec()
|
GsmHrCodec::GsmHrCodec()
|
||||||
:mDecoder(nullptr)
|
|
||||||
{
|
{
|
||||||
mDecoder = new GsmHr::Codec();
|
mDecoder = new GsmHr::Codec();
|
||||||
}
|
}
|
||||||
@@ -1329,34 +1216,21 @@ GsmHrCodec::~GsmHrCodec()
|
|||||||
mDecoder = nullptr;
|
mDecoder = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GsmHrCodec::name()
|
Codec::Info GsmHrCodec::info() {
|
||||||
{
|
return {
|
||||||
return "GSM-HR-08";
|
.mName = "GSM-HR-08",
|
||||||
|
.mSamplerate = 8000,
|
||||||
|
.mChannels = 1,
|
||||||
|
.mPcmLength = 20 * 8 * 2,
|
||||||
|
.mFrameTime = 20,
|
||||||
|
.mRtpLength = 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int GsmHrCodec::pcmLength()
|
Codec::EncodeResult GsmHrCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
return frameTime() * 8 * 2;
|
// Not supported yet
|
||||||
}
|
return {.mEncoded = 0};
|
||||||
|
|
||||||
int GsmHrCodec::rtpLength()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GsmHrCodec::frameTime()
|
|
||||||
{
|
|
||||||
return 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GsmHrCodec::samplerate()
|
|
||||||
{
|
|
||||||
return 8000;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GsmHrCodec::encode(const void* input, int inputBytes, void* output, int outputCapacity)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const int params_unvoiced[] = {
|
static const int params_unvoiced[] = {
|
||||||
@@ -1447,23 +1321,23 @@ hr_ref_from_canon(uint16_t *hr_ref, const uint8_t *canon)
|
|||||||
[+] PQ: Adding conversion from canon to rawpcm-s16le (for codec pcm)
|
[+] PQ: Adding conversion from canon to rawpcm-s16le (for codec pcm)
|
||||||
[+] PQ: Adding file output (blk_len=320)
|
[+] PQ: Adding file output (blk_len=320)
|
||||||
*/
|
*/
|
||||||
int GsmHrCodec::decode(const void* input, int inputBytes, void* output, int outputCapacity)
|
Codec::DecodeResult GsmHrCodec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
ByteBuffer bb(input, inputBytes, ByteBuffer::CopyBehavior::UseExternal);
|
ByteBuffer bb(input, ByteBuffer::CopyBehavior::UseExternal);
|
||||||
BitReader br(bb);
|
BitReader br(bb);
|
||||||
uint16_t hr_ref[22];
|
uint16_t hr_ref[22];
|
||||||
|
|
||||||
hr_ref_from_canon(hr_ref, (const uint8_t*)input + 1);
|
hr_ref_from_canon(hr_ref, input.data() + 1);
|
||||||
hr_ref[18] = 0; /* BFI : 1 bit */
|
hr_ref[18] = 0; /* BFI : 1 bit */
|
||||||
hr_ref[19] = 0; /* UFI : 1 bit */
|
hr_ref[19] = 0; /* UFI : 1 bit */
|
||||||
hr_ref[20] = 0; /* SID : 2 bit */
|
hr_ref[20] = 0; /* SID : 2 bit */
|
||||||
hr_ref[21] = 0; /* TAF : 1 bit */
|
hr_ref[21] = 0; /* TAF : 1 bit */
|
||||||
|
|
||||||
reinterpret_cast<GsmHr::Codec*>(mDecoder)->speechDecoder((int16_t*)hr_ref, (int16_t*)output);
|
reinterpret_cast<GsmHr::Codec*>(mDecoder)->speechDecoder((int16_t*)hr_ref, (int16_t*)output.data());
|
||||||
return 320;
|
return {.mDecoded = 320};
|
||||||
}
|
}
|
||||||
|
|
||||||
int GsmHrCodec::plc(int lostFrames, void* output, int outputCapacity)
|
size_t GsmHrCodec::plc(int lostFrames, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,24 +40,19 @@ public:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const char* name() override;
|
const char* name() override;
|
||||||
int channels() override;
|
int channels() override;
|
||||||
int samplerate() override;
|
int samplerate() override;
|
||||||
int payloadType() override;
|
int payloadType() override;
|
||||||
|
|
||||||
void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
||||||
int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
||||||
|
|
||||||
PCodec create() override;
|
PCodec create() override;
|
||||||
};
|
};
|
||||||
G729Codec();
|
G729Codec();
|
||||||
~G729Codec() override;
|
~G729Codec() override;
|
||||||
|
|
||||||
const char* name() override;
|
Info info() override;
|
||||||
int pcmLength() override;
|
|
||||||
int rtpLength() override;
|
|
||||||
int frameTime() override;
|
|
||||||
int samplerate() override;
|
|
||||||
int channels() override;
|
|
||||||
|
|
||||||
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
@@ -67,16 +62,19 @@ public:
|
|||||||
class OpusCodec: public Codec
|
class OpusCodec: public Codec
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
OpusEncoder *mEncoderCtx;
|
OpusEncoder *mEncoderCtx = nullptr;
|
||||||
OpusDecoder *mDecoderCtx;
|
OpusDecoder *mDecoderCtx = nullptr;
|
||||||
int mPTime, mSamplerate, mChannels;
|
int mPTime = 0, mSamplerate = 0, mChannels = 0;
|
||||||
// Audio::SpeexResampler mDecodeResampler;
|
int mDecoderChannels = 0;
|
||||||
int mDecoderChannels;
|
|
||||||
public:
|
public:
|
||||||
struct Params
|
struct Params
|
||||||
{
|
{
|
||||||
bool mUseDtx, mUseInbandFec, mStereo;
|
bool mUseDtx = false,
|
||||||
int mPtime, mTargetBitrate, mExpectedPacketLoss;
|
mUseInbandFec = false,
|
||||||
|
mStereo = false;
|
||||||
|
int mPtime = 0,
|
||||||
|
mTargetBitrate = 0,
|
||||||
|
mExpectedPacketLoss = 0;
|
||||||
|
|
||||||
Params();
|
Params();
|
||||||
resip::Data toString() const;
|
resip::Data toString() const;
|
||||||
@@ -103,29 +101,24 @@ public:
|
|||||||
PCodec create() override;
|
PCodec create() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
OpusCodec(int samplerate, int channels, int ptime);
|
OpusCodec(Audio::Format fmt, int ptime);
|
||||||
~OpusCodec();
|
~OpusCodec();
|
||||||
void applyParams(const Params& params);
|
void applyParams(const Params& params);
|
||||||
|
|
||||||
const char* name();
|
Info info() override;
|
||||||
int pcmLength();
|
|
||||||
int rtpLength();
|
|
||||||
int frameTime();
|
|
||||||
int samplerate();
|
|
||||||
int channels();
|
|
||||||
|
|
||||||
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output);
|
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output);
|
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
size_t plc(int lostFrames, std::span<uint8_t> output);
|
size_t plc(int lostFrames, std::span<uint8_t> output) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class IlbcCodec: public Codec
|
class IlbcCodec: public Codec
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
int mPacketTime; /// Single frame time (20 or 30 ms)
|
int mPacketTime = 0; /// Single frame time (20 or 30 ms)
|
||||||
iLBC_encinst_t* mEncoderCtx;
|
iLBC_encinst_t* mEncoderCtx = nullptr;
|
||||||
iLBC_decinst_t* mDecoderCtx;
|
iLBC_decinst_t* mDecoderCtx = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class IlbcFactory: public Factory
|
class IlbcFactory: public Factory
|
||||||
@@ -148,11 +141,7 @@ public:
|
|||||||
|
|
||||||
IlbcCodec(int packetTime);
|
IlbcCodec(int packetTime);
|
||||||
virtual ~IlbcCodec();
|
virtual ~IlbcCodec();
|
||||||
const char* name() override;
|
Info info() override;
|
||||||
int pcmLength() override;
|
|
||||||
int rtpLength() override;
|
|
||||||
int frameTime() override;
|
|
||||||
int samplerate() override;
|
|
||||||
|
|
||||||
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
@@ -189,11 +178,7 @@ public:
|
|||||||
G711Codec(int type);
|
G711Codec(int type);
|
||||||
~G711Codec();
|
~G711Codec();
|
||||||
|
|
||||||
const char* name() override;
|
Info info() override;
|
||||||
int pcmLength() override;
|
|
||||||
int frameTime() override;
|
|
||||||
int rtpLength() override;
|
|
||||||
int samplerate() override;
|
|
||||||
|
|
||||||
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
@@ -206,9 +191,9 @@ protected:
|
|||||||
class IsacCodec: public Codec
|
class IsacCodec: public Codec
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
int mSamplerate;
|
int mSamplerate = 0;
|
||||||
ISACFIX_MainStruct* mEncoderCtx;
|
ISACFIX_MainStruct* mEncoderCtx = nullptr;
|
||||||
ISACFIX_MainStruct* mDecoderCtx;
|
ISACFIX_MainStruct* mDecoderCtx = nullptr;
|
||||||
public:
|
public:
|
||||||
class IsacFactory16K: public Factory
|
class IsacFactory16K: public Factory
|
||||||
{
|
{
|
||||||
@@ -240,11 +225,7 @@ public:
|
|||||||
IsacCodec(int sampleRate);
|
IsacCodec(int sampleRate);
|
||||||
~IsacCodec();
|
~IsacCodec();
|
||||||
|
|
||||||
const char* name() override;
|
Info info() override;
|
||||||
int pcmLength() override;
|
|
||||||
int rtpLength() override;
|
|
||||||
int frameTime() override;
|
|
||||||
int samplerate() override;
|
|
||||||
|
|
||||||
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
@@ -312,17 +293,13 @@ public:
|
|||||||
GsmCodec(Type codecType);
|
GsmCodec(Type codecType);
|
||||||
|
|
||||||
/*! Destructor. */
|
/*! Destructor. */
|
||||||
virtual ~GsmCodec();
|
~GsmCodec();
|
||||||
|
|
||||||
const char* name() override;
|
Info info() override;
|
||||||
int pcmLength() override;
|
|
||||||
int rtpLength() override;
|
|
||||||
int frameTime() override;
|
|
||||||
int samplerate() override;
|
|
||||||
|
|
||||||
int encode(const void* input, int inputBytes, void* output, int outputCapacity);
|
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
int decode(const void* input, int inputBytes, void* output, int outputCapacity);
|
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
int plc(int lostFrames, void* output, int outputCapacity);
|
size_t plc(int lostFrames, std::span<uint8_t> output) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// GSM MIME name
|
/// GSM MIME name
|
||||||
@@ -361,25 +338,19 @@ public:
|
|||||||
PCodec create();
|
PCodec create();
|
||||||
};
|
};
|
||||||
G722Codec();
|
G722Codec();
|
||||||
virtual ~G722Codec();
|
~G722Codec();
|
||||||
|
|
||||||
const char* name();
|
Info info() override;
|
||||||
int pcmLength();
|
|
||||||
int rtpLength();
|
|
||||||
int frameTime();
|
|
||||||
int samplerate();
|
|
||||||
|
|
||||||
int encode(const void* input, int inputBytes, void* output, int outputCapacity);
|
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
int decode(const void* input, int inputBytes, void* output, int outputCapacity);
|
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
int plc(int lostFrames, void* output, int outputCapacity);
|
size_t plc(int lostFrames, std::span<uint8_t> output) override;
|
||||||
|
|
||||||
//unsigned GetSamplerate() { return 16000; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GsmHrCodec: public Codec
|
class GsmHrCodec: public Codec
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
void* mDecoder;
|
void* mDecoder = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class GsmHrFactory: public Factory
|
class GsmHrFactory: public Factory
|
||||||
@@ -399,15 +370,11 @@ public:
|
|||||||
GsmHrCodec();
|
GsmHrCodec();
|
||||||
~GsmHrCodec() override;
|
~GsmHrCodec() override;
|
||||||
|
|
||||||
const char* name() override;
|
Info info() override;
|
||||||
int pcmLength() override;
|
|
||||||
int rtpLength() override;
|
|
||||||
int frameTime() override;
|
|
||||||
int samplerate() override;
|
|
||||||
|
|
||||||
int encode(const void* input, int inputBytes, void* output, int outputCapacity) override;
|
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
int decode(const void* input, int inputBytes, void* output, int outputCapacity) override;
|
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
int plc(int lostFrames, void* output, int outputCapacity) override;
|
size_t plc(int lostFrames, std::span<uint8_t> output) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -396,12 +396,10 @@ size_t decode_packet(Codec& codec, RTPPacket& p, void* output_buffer, size_t out
|
|||||||
|
|
||||||
for (int i=0; i < frame_count; i++)
|
for (int i=0; i < frame_count; i++)
|
||||||
{
|
{
|
||||||
auto decoded_length = codec.decode(p.GetPayloadData() + i * codec.rtpLength(),
|
auto r = codec.decode({p.GetPayloadData() + i * codec.rtpLength(), (size_t)frame_length},
|
||||||
frame_length,
|
{(uint8_t*)output_buffer, output_capacity});
|
||||||
output_buffer,
|
|
||||||
output_capacity);
|
|
||||||
|
|
||||||
result += decoded_length;
|
result += r.mDecoded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -572,7 +570,7 @@ AudioReceiver::DecodeResult AudioReceiver::decodeGapTo(Audio::DataWindow& output
|
|||||||
mDecodedLength = 0;
|
mDecodedLength = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mDecodedLength = mCodec->plc(mFrameCount, mDecodedFrame, sizeof mDecodedFrame);
|
mDecodedLength = mCodec->plc(mFrameCount, {(uint8_t*)mDecodedFrame, sizeof mDecodedFrame});
|
||||||
if (!mDecodedLength)
|
if (!mDecodedLength)
|
||||||
{
|
{
|
||||||
// PLC is not support or failed
|
// PLC is not support or failed
|
||||||
@@ -587,7 +585,7 @@ AudioReceiver::DecodeResult AudioReceiver::decodeGapTo(Audio::DataWindow& output
|
|||||||
if (mDecodedLength)
|
if (mDecodedLength)
|
||||||
{
|
{
|
||||||
processDecoded(output, options);
|
processDecoded(output, options);
|
||||||
return {.mStatus = DecodeResult::Status::Ok,.mChannels = mCodec->channels(), .mSamplerate = mCodec->samplerate()};
|
return {.mStatus = DecodeResult::Status::Ok, .mSamplerate = mCodec->samplerate(), .mChannels = mCodec->channels()};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return {.mStatus = DecodeResult::Status::Skip};
|
return {.mStatus = DecodeResult::Status::Skip};
|
||||||
@@ -683,9 +681,15 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& out
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Decode frame by frame
|
// Decode frame by frame
|
||||||
mDecodedLength = mCodec->decode(rtp.GetPayloadData() + i * mCodec->rtpLength(), frameLength, mDecodedFrame, sizeof mDecodedFrame);
|
auto r = mCodec->decode({rtp.GetPayloadData() + i * mCodec->rtpLength(), (size_t)frameLength},
|
||||||
|
{(uint8_t*)mDecodedFrame, sizeof mDecodedFrame});
|
||||||
|
mDecodedLength = r.mDecoded;
|
||||||
if (mDecodedLength > 0)
|
if (mDecodedLength > 0)
|
||||||
processDecoded(output, options);
|
processDecoded(output, options);
|
||||||
|
|
||||||
|
// What is important - here we may have packet marked as CNG
|
||||||
|
if (r.mIsCng)
|
||||||
|
mCngPacket = packet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.mStatus = mFrameCount > 0 ? DecodeResult::Status::Ok : DecodeResult::Status::Skip;
|
result.mStatus = mFrameCount > 0 ? DecodeResult::Status::Ok : DecodeResult::Status::Skip;
|
||||||
@@ -705,14 +709,40 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& out
|
|||||||
|
|
||||||
AudioReceiver::DecodeResult AudioReceiver::decodeEmptyTo(Audio::DataWindow& output, DecodeOptions options)
|
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
|
||||||
|
if (options.mElapsed == 0ms || !mCodec)
|
||||||
|
return {.mStatus = DecodeResult::Status::Skip};
|
||||||
|
|
||||||
// No packet available at all (and no previous CNG packet) - so return the silence
|
// No packet available at all (and no previous CNG packet) - so return the silence
|
||||||
if (options.mElapsed != 0ms && mCodec)
|
if (options.mElapsed != 0ms && mCodec)
|
||||||
{
|
{
|
||||||
Audio::Format fmt = options.mResampleToMainRate ? Audio::Format(AUDIO_SAMPLERATE, 1) : mCodec->getAudioFormat();
|
Audio::Format fmt = options.mResampleToMainRate ? Audio::Format(AUDIO_SAMPLERATE, 1) : mCodec->getAudioFormat();
|
||||||
// Emit silence if codec information is available - it is to properly handle the gaps
|
if (mCngPacket)
|
||||||
auto avail = output.getTimeLength(fmt.rate(), fmt.channels());
|
{
|
||||||
if (options.mElapsed > avail)
|
// Try to decode it - replay previous audio decoded or use CNG decoder (if payload type is 13)
|
||||||
mAvailable.addZero(fmt.sizeFromTime(options.mElapsed - avail));
|
if (mCngPacket->rtp()->GetPayloadType() == 13)
|
||||||
|
{
|
||||||
|
// Using latest CNG packet to produce comfort noise
|
||||||
|
auto produced = mCngDecoder.produce(fmt.rate(), options.mElapsed.count(), (short*)(output.data() + output.filled()), false);
|
||||||
|
output.setFilled(output.filled() + produced);
|
||||||
|
return {.mStatus = DecodeResult::Status::Ok, .mSamplerate = fmt.rate(), .mChannels = fmt.channels()};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Here we have another packet marked as CNG - for another decoder
|
||||||
|
// Just decode it +1 time
|
||||||
|
return decodePacketTo(output, options, mCngPacket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Emit silence if codec information is available - it is to properly handle the gaps
|
||||||
|
auto avail = output.getTimeLength(fmt.rate(), fmt.channels());
|
||||||
|
if (options.mElapsed > avail)
|
||||||
|
output.addZero(fmt.sizeFromTime(options.mElapsed - avail));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mFailedCount++;
|
mFailedCount++;
|
||||||
@@ -871,11 +901,10 @@ void AudioReceiver::updateAmrCodecStats(Codec* c)
|
|||||||
int AudioReceiver::getSize() const
|
int AudioReceiver::getSize() const
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
result += sizeof(*this) + mResampler8.getSize() + mResampler16.getSize() + mResampler32.getSize()
|
result += sizeof(*this) + mResampler8.getSize() + mResampler16.getSize() + mResampler32.getSize() + mResampler48.getSize();
|
||||||
+ mResampler48.getSize();
|
|
||||||
|
|
||||||
if (mCodec)
|
if (mCodec)
|
||||||
result += mCodec->getSize();
|
; // ToDo: need the way to calculate size of codec instances
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,18 +210,17 @@ void AudioStream::addData(const void* buffer, int bytes)
|
|||||||
if (mSendingDump)
|
if (mSendingDump)
|
||||||
mSendingDump->write((const char*)mCapturedAudio.data() + codec->pcmLength() * i, codec->pcmLength());
|
mSendingDump->write((const char*)mCapturedAudio.data() + codec->pcmLength() * i, codec->pcmLength());
|
||||||
|
|
||||||
int produced;
|
auto r = codec->encode({(const uint8_t*)mCapturedAudio.data() + codec->pcmLength()*i, (size_t)codec->pcmLength()},
|
||||||
produced = codec->encode((const char*)mCapturedAudio.data() + codec->pcmLength()*i,
|
{(uint8_t*)mFrameBuffer, MT_MAXAUDIOFRAME});
|
||||||
codec->pcmLength(), mFrameBuffer, MT_MAXAUDIOFRAME);
|
|
||||||
|
|
||||||
// Counter of processed input bytes of raw pcm data from microphone
|
// Counter of processed input bytes of raw pcm data from microphone
|
||||||
processed += codec->pcmLength();
|
processed += codec->pcmLength();
|
||||||
encodedTime += codec->frameTime();
|
encodedTime += codec->frameTime();
|
||||||
mEncodedTime += codec->frameTime();
|
mEncodedTime += codec->frameTime();
|
||||||
|
|
||||||
if (produced)
|
if (r.mEncoded)
|
||||||
{
|
{
|
||||||
mEncodedAudio.appendBuffer(mFrameBuffer, produced);
|
mEncodedAudio.appendBuffer(mFrameBuffer, r.mEncoded);
|
||||||
if (packetTime <= encodedTime)
|
if (packetTime <= encodedTime)
|
||||||
{
|
{
|
||||||
// Time to send packet
|
// Time to send packet
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class CodecMap: public std::map<int, PCodec>
|
|||||||
class Codec
|
class Codec
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class Factory
|
class Factory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -41,21 +42,30 @@ public:
|
|||||||
resip::Codec resipCodec();
|
resip::Codec resipCodec();
|
||||||
};
|
};
|
||||||
virtual ~Codec() {}
|
virtual ~Codec() {}
|
||||||
virtual const char* name() = 0;
|
|
||||||
virtual int samplerate() = 0;
|
|
||||||
virtual float timestampUnit() { return float(1.0 / samplerate()); }
|
|
||||||
|
|
||||||
// Size of decoded audio frame in bytes
|
struct Info
|
||||||
virtual int pcmLength() = 0;
|
{
|
||||||
|
std::string mName;
|
||||||
|
int mSamplerate = 0; // Hz
|
||||||
|
int mChannels = 0;
|
||||||
|
int mPcmLength = 0; // In bytes
|
||||||
|
int mFrameTime = 0; // In milliseconds
|
||||||
|
int mRtpLength = 0; // In bytes
|
||||||
|
};
|
||||||
|
// Returns information about this codec instance
|
||||||
|
virtual Info info() = 0;
|
||||||
|
|
||||||
// Time length of single audio frame
|
// Helper functions to return information - they are based on info() method
|
||||||
virtual int frameTime() = 0;
|
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; }
|
||||||
|
|
||||||
// Size of RTP frame in bytes. Can be zero for variable sized codecs.
|
Audio::Format getAudioFormat() {
|
||||||
virtual int rtpLength() = 0;
|
return Audio::Format(this->info().mSamplerate, this->info().mChannels);
|
||||||
|
}
|
||||||
// Number of audio channels
|
|
||||||
virtual int channels() { return 1; }
|
|
||||||
|
|
||||||
// Returns size of encoded data (RTP) in bytes
|
// Returns size of encoded data (RTP) in bytes
|
||||||
struct EncodeResult
|
struct EncodeResult
|
||||||
@@ -75,10 +85,6 @@ public:
|
|||||||
// Returns size of produced data (PCM signed short) in bytes
|
// Returns size of produced data (PCM signed short) in bytes
|
||||||
virtual size_t plc(int lostFrames, std::span<uint8_t> output) = 0;
|
virtual size_t plc(int lostFrames, std::span<uint8_t> output) = 0;
|
||||||
|
|
||||||
// Returns size of codec in memory
|
|
||||||
virtual size_t getSize() const { return 0; };
|
|
||||||
|
|
||||||
virtual Audio::Format getAudioFormat() { return Audio::Format(this->samplerate(), this->channels());};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "MT_EvsCodec.h"
|
#include "MT_EvsCodec.h"
|
||||||
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
/*-------------------------------------------------------------------*
|
/*-------------------------------------------------------------------*
|
||||||
* rate2AMRWB_IOmode()
|
* rate2AMRWB_IOmode()
|
||||||
@@ -167,67 +167,58 @@ EVSCodec::~EVSCodec()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int EVSCodec::samplerate()
|
Codec::Info EVSCodec::info() {
|
||||||
{
|
return {
|
||||||
return st_dec->output_Fs;
|
.mName = MT_EVS_CODECNAME,
|
||||||
|
.mSamplerate = st_dec->output_Fs,
|
||||||
|
.mChannels = 1,
|
||||||
|
.mPcmLength = st_dec->output_Fs / 1000 * sp.ptime * 2,
|
||||||
|
.mFrameTime = sp.ptime,
|
||||||
|
.mRtpLength = 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int EVSCodec::pcmLength()
|
|
||||||
{
|
|
||||||
return samplerate() / 50 * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
int EVSCodec::frameTime()
|
Codec::EncodeResult EVSCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
|
||||||
return sp.ptime;
|
|
||||||
}
|
|
||||||
|
|
||||||
int EVSCodec::rtpLength()
|
|
||||||
{
|
|
||||||
// Variable sized codec - bitrate can be changed during the call
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int EVSCodec::encode(const void* input, int inputBytes, void* output, int outputCapacity)
|
|
||||||
{
|
{
|
||||||
// Encoding is not supported yet.
|
// Encoding is not supported yet.
|
||||||
return 0;
|
return {.mEncoded = 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
int EVSCodec::decode(const void* input, int input_length, void* output, int outputCapacity)
|
Codec::DecodeResult EVSCodec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
if (outputCapacity < pcmLength())
|
if (output.size_bytes() < pcmLength())
|
||||||
return 0;
|
return {.mDecoded = 0};
|
||||||
|
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
|
|
||||||
// Check if we get payload with CMR
|
// Check if we get payload with CMR
|
||||||
auto payload_iter = FixedPayload_EVSPrimary.find((input_length - 2) * 8);
|
auto payload_iter = FixedPayload_EVSPrimary.find((input.size_bytes() - 2) * 8);
|
||||||
if (payload_iter == FixedPayload_EVSPrimary.end())
|
if (payload_iter == FixedPayload_EVSPrimary.end())
|
||||||
{
|
{
|
||||||
// Check if we get payload with ToC and without CMR
|
// Check if we get payload with ToC and without CMR
|
||||||
payload_iter = FixedPayload_EVSPrimary.find((input_length - 1) * 8);
|
payload_iter = FixedPayload_EVSPrimary.find((input.size_bytes() - 1) * 8);
|
||||||
if (payload_iter == FixedPayload_EVSPrimary.end())
|
if (payload_iter == FixedPayload_EVSPrimary.end())
|
||||||
{
|
{
|
||||||
// Maybe there is no ToC ?
|
// Maybe there is no ToC ?
|
||||||
payload_iter = FixedPayload_EVSPrimary.find(input_length * 8);
|
payload_iter = FixedPayload_EVSPrimary.find(input.size_bytes() * 8);
|
||||||
if (payload_iter == FixedPayload_EVSPrimary.end())
|
if (payload_iter == FixedPayload_EVSPrimary.end())
|
||||||
{
|
{
|
||||||
// Bad payload size at all
|
// Bad payload size at all
|
||||||
return 0;
|
return {.mDecoded = 0};
|
||||||
}
|
}
|
||||||
/* Add ToC byte.
|
/* Add ToC byte.
|
||||||
* WARNING maybe it will be work incorrect with 56bit payload,
|
* WARNING maybe it will be work incorrect with 56bit payload,
|
||||||
* see 3GPP TS 26.445 Annex A, A.2.1.3 */
|
* see 3GPP TS 26.445 Annex A, A.2.1.3 */
|
||||||
char c = evs::rate2EVSmode(FixedPayload_EVSPrimary.find(input_length * 8)->second);
|
char c = evs::rate2EVSmode(FixedPayload_EVSPrimary.find(input.size_bytes() * 8)->second);
|
||||||
buffer += c;
|
buffer += c;
|
||||||
buffer += std::string(reinterpret_cast<const char*>(input), input_length);
|
buffer += std::string(reinterpret_cast<const char*>(input.data()), input.size_bytes());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
buffer = std::string(reinterpret_cast<const char*>(input), input_length);
|
buffer = std::string(reinterpret_cast<const char*>(input.data()), input.size_bytes());
|
||||||
}
|
}
|
||||||
else // Skip CMR byte
|
else // Skip CMR byte
|
||||||
buffer = std::string(reinterpret_cast<const char*>(input) + 1, input_length-1);
|
buffer = std::string(reinterpret_cast<const char*>(input.data()) + 1, input.size_bytes()-1);
|
||||||
|
|
||||||
|
|
||||||
// Output buffer for 48 KHz
|
// Output buffer for 48 KHz
|
||||||
@@ -263,7 +254,7 @@ int EVSCodec::decode(const void* input, int input_length, void* output, int outp
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* convert 'float' output data to 'short' */
|
/* convert 'float' output data to 'short' */
|
||||||
evs::syn_output(data, static_cast<short>(pcmLength() / 2), static_cast<short*>(output) + offset);
|
evs::syn_output(data, static_cast<short>(pcmLength() / 2), reinterpret_cast<short*>(output.data()) + offset);
|
||||||
offset += pcmLength() / 2;
|
offset += pcmLength() / 2;
|
||||||
if (st_dec->ini_frame < MAX_FRAME_COUNTER)
|
if (st_dec->ini_frame < MAX_FRAME_COUNTER)
|
||||||
{
|
{
|
||||||
@@ -271,12 +262,12 @@ int EVSCodec::decode(const void* input, int input_length, void* output, int outp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pcmLength();
|
return {.mDecoded = (size_t)pcmLength()};
|
||||||
}
|
}
|
||||||
|
|
||||||
int EVSCodec::plc(int lostFrames, void* output, int outputCapacity)
|
size_t EVSCodec::plc(int lostFrames, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EVSCodec::initDecoder(const StreamParameters& sp)
|
void EVSCodec::initDecoder(const StreamParameters& sp)
|
||||||
|
|||||||
@@ -2,15 +2,11 @@
|
|||||||
#define __MT_EVS_CODEC_H
|
#define __MT_EVS_CODEC_H
|
||||||
|
|
||||||
#include "../engine_config.h"
|
#include "../engine_config.h"
|
||||||
#include <set>
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include "MT_Codec.h"
|
#include "MT_Codec.h"
|
||||||
|
|
||||||
@@ -52,18 +48,14 @@ public:
|
|||||||
EVSCodec(const StreamParameters& sp);
|
EVSCodec(const StreamParameters& sp);
|
||||||
~EVSCodec() override;
|
~EVSCodec() override;
|
||||||
|
|
||||||
const char* name() override { return MT_EVS_CODECNAME; }
|
Info info() override;
|
||||||
int samplerate() override;
|
|
||||||
int pcmLength() override;
|
EncodeResult encode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
int frameTime() override;
|
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
int rtpLength() override;
|
size_t plc(int lostFrames, std::span<uint8_t> output) override;
|
||||||
int encode(const void* input, int inputBytes, void* output, int outputCapacity) override;
|
|
||||||
int decode(const void* input, int inputBytes, void* output, int outputCapacity) override;
|
|
||||||
int plc(int lostFrames, void* output, int outputCapacity) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
evs::Decoder_State* st_dec;
|
evs::Decoder_State* st_dec = nullptr;
|
||||||
//Encoder_State_fx* st_enc;
|
|
||||||
StreamParameters sp;
|
StreamParameters sp;
|
||||||
void initDecoder(const StreamParameters& sp);
|
void initDecoder(const StreamParameters& sp);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -212,15 +212,13 @@ void SrtpSession::close()
|
|||||||
|
|
||||||
SrtpKeySalt& SrtpSession::outgoingKey(SrtpSuite suite)
|
SrtpKeySalt& SrtpSession::outgoingKey(SrtpSuite suite)
|
||||||
{
|
{
|
||||||
Lock l(mGuard);
|
|
||||||
assert(suite > SRTP_NONE && suite <= SRTP_LAST);
|
assert(suite > SRTP_NONE && suite <= SRTP_LAST);
|
||||||
return mOutgoingKey[int(suite)-1];
|
Lock l(mGuard);
|
||||||
|
return mOutgoingKey[int(suite)-1]; // The automated review sometimes give the hints about the possible underflow array index access
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrtpSession::protectRtp(void* buffer, int* length)
|
bool SrtpSession::protectRtp(void* buffer, int* length)
|
||||||
{
|
{
|
||||||
// addSsrc(RtpHelper::findSsrc(buffer, *length), sdOutgoing);
|
|
||||||
|
|
||||||
Lock l(mGuard);
|
Lock l(mGuard);
|
||||||
if (mOutboundSession)
|
if (mOutboundSession)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,20 +20,17 @@
|
|||||||
|
|
||||||
enum SrtpSuite
|
enum SrtpSuite
|
||||||
{
|
{
|
||||||
SRTP_NONE,
|
SRTP_NONE = 0,
|
||||||
SRTP_AES_128_AUTH_80,
|
SRTP_AES_128_AUTH_80 = 1,
|
||||||
SRTP_AES_256_AUTH_80,
|
SRTP_AES_256_AUTH_80 = 2,
|
||||||
SRTP_AES_192_AUTH_80,
|
SRTP_AES_192_AUTH_80 = 3,
|
||||||
SRTP_AES_128_AUTH_32,
|
SRTP_AES_128_AUTH_32 = 4,
|
||||||
SRTP_AES_256_AUTH_32,
|
SRTP_AES_256_AUTH_32 = 5,
|
||||||
SRTP_AES_192_AUTH_32,
|
SRTP_AES_192_AUTH_32 = 6,
|
||||||
SRTP_AES_128_AUTH_NULL,
|
SRTP_AES_128_AUTH_NULL = 7,
|
||||||
SRTP_AED_AES_256_GCM,
|
SRTP_AED_AES_256_GCM = 8,
|
||||||
SRTP_AED_AES_128_GCM,
|
SRTP_AED_AES_128_GCM = 9,
|
||||||
SRTP_LAST = SRTP_AED_AES_128_GCM
|
SRTP_LAST = SRTP_AED_AES_128_GCM
|
||||||
// ToDo:
|
|
||||||
// a=crypto:1 AEAD_AES_256_GCM_8 inline:tN2A0vRjFBimpQsW2GasuJuPe7hKE26gki30APC8DVuySqCOYTs8lYBPR5I=
|
|
||||||
// a=crypto:3 AEAD_AES_128_GCM_8 inline:Ok7VL8SmBHSbZLw4dK6iQgpliYKGdY9BHLJcRw==
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SrtpSuite toSrtpSuite(const std::string_view& s);
|
extern SrtpSuite toSrtpSuite(const std::string_view& s);
|
||||||
|
|||||||
Reference in New Issue
Block a user