Compare commits
2 Commits
bdc4858bcc
...
72a7042ab9
| Author | SHA1 | Date | |
|---|---|---|---|
| 72a7042ab9 | |||
| b5fe9e59c4 |
@@ -535,16 +535,16 @@ Codec::EncodeResult AmrWbCodec::encode(std::span<const uint8_t> input, std::span
|
|||||||
#define L_FRAME 160
|
#define L_FRAME 160
|
||||||
#define AMR_BITRATE_DTX 15
|
#define AMR_BITRATE_DTX 15
|
||||||
|
|
||||||
int AmrWbCodec::decodeIuup(std::span<const uint8_t> input, std::span<uint8_t> output)
|
Codec::DecodeResult AmrWbCodec::decodeIuup(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
IuUP::Frame frame;
|
IuUP::Frame frame;
|
||||||
if (!IuUP::parse2(input.data(), input.size(), frame))
|
if (!IuUP::parse2(input.data(), input.size(), frame))
|
||||||
return 0;
|
return {.mDecoded = 0};
|
||||||
|
|
||||||
if (!frame.mHeaderCrcOk || !frame.mPayloadCrcOk)
|
if (!frame.mHeaderCrcOk || !frame.mPayloadCrcOk)
|
||||||
{
|
{
|
||||||
ICELogInfo(<< "CRC check failed.");
|
ICELogInfo(<< "CRC check failed.");
|
||||||
return 0;
|
return {.mDecoded = 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reserve space
|
// Reserve space
|
||||||
@@ -559,15 +559,15 @@ int AmrWbCodec::decodeIuup(std::span<const uint8_t> input, std::span<uint8_t> ou
|
|||||||
frameType = ftIndex;
|
frameType = ftIndex;
|
||||||
|
|
||||||
if (frameType == 0xFF)
|
if (frameType == 0xFF)
|
||||||
return 0;
|
return {.mDecoded = 0, .mIsCng = true};
|
||||||
|
|
||||||
dataToDecode.mutableData()[0] = (frameType << 3) | (1 << 2);
|
dataToDecode.mutableData()[0] = (frameType << 3) | (1 << 2);
|
||||||
|
|
||||||
D_IF_decode(mDecoderCtx, (const unsigned char*)dataToDecode.data(), (short*)output.data(), 0);
|
D_IF_decode(mDecoderCtx, (const unsigned char*)dataToDecode.data(), (short*)output.data(), 0);
|
||||||
return pcmLength();
|
return {.mDecoded = (size_t)pcmLength()};
|
||||||
}
|
}
|
||||||
|
|
||||||
int AmrWbCodec::decodePlain(std::span<const uint8_t> input, std::span<uint8_t> output)
|
Codec::DecodeResult AmrWbCodec::decodePlain(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
AmrPayloadInfo info;
|
AmrPayloadInfo info;
|
||||||
info.mCurrentTimestamp = mCurrentDecoderTimestamp;
|
info.mCurrentTimestamp = mCurrentDecoderTimestamp;
|
||||||
@@ -586,7 +586,7 @@ int AmrWbCodec::decodePlain(std::span<const uint8_t> input, std::span<uint8_t> o
|
|||||||
{
|
{
|
||||||
GAmrWbStatistics.mNonParsed++;
|
GAmrWbStatistics.mNonParsed++;
|
||||||
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;
|
||||||
@@ -595,22 +595,22 @@ int AmrWbCodec::decodePlain(std::span<const uint8_t> input, std::span<uint8_t> o
|
|||||||
if (ap.mDiscardPacket)
|
if (ap.mDiscardPacket)
|
||||||
{
|
{
|
||||||
GAmrWbStatistics.mDiscarded++;
|
GAmrWbStatistics.mDiscarded++;
|
||||||
return 0;
|
return {.mDecoded = 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the required output capacity
|
// Find the required output capacity
|
||||||
size_t capacity = 0;
|
size_t capacity = 0;
|
||||||
for (AmrFrame& frame: ap.mFrames)
|
for (AmrFrame& frame: ap.mFrames)
|
||||||
capacity += frame.mMode == 0xFF /* CNG */ ? pcmLength() * 8 : pcmLength();
|
capacity += frame.mMode == 0xFF /* CNG */ ? pcmLength() : pcmLength();
|
||||||
|
|
||||||
if (output.size() < capacity)
|
if (output.size() < capacity)
|
||||||
return 0;
|
return {.mDecoded = 0};
|
||||||
|
|
||||||
short* dataOut = (short*)output.data();
|
short* dataOut = (short*)output.data();
|
||||||
size_t dataOutSizeInBytes = 0;
|
size_t dataOutSizeInBytes = 0;
|
||||||
for (AmrFrame& frame: ap.mFrames)
|
for (AmrFrame& frame: ap.mFrames)
|
||||||
{
|
{
|
||||||
size_t frameOutputSize = frame.mMode == 0xFF ? pcmLength() * 8 : pcmLength();
|
size_t frameOutputSize = frame.mMode == 0xFF ? pcmLength() : pcmLength();
|
||||||
memset(dataOut, 0, frameOutputSize);
|
memset(dataOut, 0, frameOutputSize);
|
||||||
|
|
||||||
if (frame.mData)
|
if (frame.mData)
|
||||||
@@ -624,17 +624,16 @@ int AmrWbCodec::decodePlain(std::span<const uint8_t> input, std::span<uint8_t> o
|
|||||||
dataOutSizeInBytes += frameOutputSize;
|
dataOutSizeInBytes += frameOutputSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dataOutSizeInBytes;
|
return {.mDecoded = dataOutSizeInBytes,
|
||||||
|
.mIsCng = ap.mFrames.size() == 1 ? (ap.mFrames.front().mMode == 0xFF) : false};
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::DecodeResult AmrWbCodec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
Codec::DecodeResult AmrWbCodec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
if (mConfig.mIuUP)
|
if (mConfig.mIuUP)
|
||||||
return {.mDecoded = (size_t)decodeIuup(input, output)};
|
return decodeIuup(input, output);
|
||||||
else
|
else
|
||||||
return {.mDecoded = (size_t)decodePlain(input, output)};
|
return decodePlain(input, output);
|
||||||
|
|
||||||
return {.mDecoded = 0};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t AmrWbCodec::plc(int lostFrames, std::span<uint8_t> output)
|
size_t AmrWbCodec::plc(int lostFrames, std::span<uint8_t> output)
|
||||||
|
|||||||
@@ -85,8 +85,8 @@ protected:
|
|||||||
|
|
||||||
int mPreviousPacketLength;
|
int mPreviousPacketLength;
|
||||||
|
|
||||||
int decodeIuup(std::span<const uint8_t> input, std::span<uint8_t> output);
|
DecodeResult decodeIuup(std::span<const uint8_t> input, std::span<uint8_t> output);
|
||||||
int decodePlain(std::span<const uint8_t> input, std::span<uint8_t> output);
|
DecodeResult decodePlain(std::span<const uint8_t> input, std::span<uint8_t> output);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class CodecFactory: public Factory
|
class CodecFactory: public Factory
|
||||||
|
|||||||
@@ -681,8 +681,9 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& out
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Decode frame by frame
|
// Decode frame by frame
|
||||||
auto r = mCodec->decode({rtp.GetPayloadData() + i * mCodec->rtpLength(), (size_t)frameLength},
|
auto codecInput = std::span{rtp.GetPayloadData() + i * mCodec->rtpLength(), (size_t)frameLength};
|
||||||
{(uint8_t*)mDecodedFrame, sizeof mDecodedFrame});
|
auto codecOutput = std::span{(uint8_t*)mDecodedFrame, sizeof mDecodedFrame};
|
||||||
|
auto r = mCodec->decode(codecInput, codecOutput);
|
||||||
mDecodedLength = r.mDecoded;
|
mDecodedLength = r.mDecoded;
|
||||||
if (mDecodedLength > 0)
|
if (mDecodedLength > 0)
|
||||||
processDecoded(output, options);
|
processDecoded(output, options);
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ public:
|
|||||||
int mPcmLength = 0; // In bytes
|
int mPcmLength = 0; // In bytes
|
||||||
int mFrameTime = 0; // In milliseconds
|
int mFrameTime = 0; // In milliseconds
|
||||||
int mRtpLength = 0; // In bytes
|
int mRtpLength = 0; // In bytes
|
||||||
|
float mTimestampUnit = 0.0f;
|
||||||
};
|
};
|
||||||
// Returns information about this codec instance
|
// Returns information about this codec instance
|
||||||
virtual Info info() = 0;
|
virtual Info info() = 0;
|
||||||
@@ -63,6 +64,7 @@ public:
|
|||||||
int samplerate() { return info().mSamplerate; }
|
int samplerate() { return info().mSamplerate; }
|
||||||
int frameTime() { return info().mFrameTime; }
|
int frameTime() { return info().mFrameTime; }
|
||||||
std::string name() { return info().mName; }
|
std::string name() { return info().mName; }
|
||||||
|
float timestampUnit() { return info().mTimestampUnit == 0.0f ? 1.0f / info().mSamplerate : info().mTimestampUnit; }
|
||||||
|
|
||||||
Audio::Format getAudioFormat() {
|
Audio::Format getAudioFormat() {
|
||||||
return Audio::Format(this->info().mSamplerate, this->info().mChannels);
|
return Audio::Format(this->info().mSamplerate, this->info().mChannels);
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.20)
|
||||||
|
project(rtp_decode)
|
||||||
|
|
||||||
set (CMAKE_CXX_STANDARD 20)
|
set (CMAKE_CXX_STANDARD 20)
|
||||||
set (CMAKE_CXX_STANDARD_REQUIRED ON)
|
set (CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
add_executable(rtp_decode main.cpp)
|
|
||||||
add_subdirectory(../../src build_rtphone)
|
add_subdirectory(../../src build_rtphone)
|
||||||
|
|
||||||
|
add_executable(rtp_decode main.cpp)
|
||||||
target_link_libraries(rtp_decode PRIVATE rtphone)
|
target_link_libraries(rtp_decode PRIVATE rtphone)
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ static void usage(const char* progname)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Usage: %s <input.rtp> <output.wav> --codec <name> [--pt <N>] [--rate <N>] [--channels <N>]\n"
|
"Usage: %s <input.rtp> <output.wav> --codec <name> [--pt <N>] [--rate <N>] [--channels <N>]\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Codecs: pcmu pcma g722 g729 opus gsm gsmhr gsmefr amrnb amrwb evs ilbc20 ilbc30 isac16 isac32\n"
|
"Codecs: pcmu pcma g722 g729 opus gsm gsmhr gsmefr\n"
|
||||||
|
" amrnb amrwb amrnb-bwe amrwb-bwe evs ilbc20 ilbc30 isac16 isac32\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" --codec <name> Codec name (required)\n"
|
" --codec <name> Codec name (required)\n"
|
||||||
@@ -67,6 +68,8 @@ static const CodecDefaults kCodecTable[] = {
|
|||||||
{ "opus", 106, false },
|
{ "opus", 106, false },
|
||||||
{ "amrnb", -1, true },
|
{ "amrnb", -1, true },
|
||||||
{ "amrwb", -1, true },
|
{ "amrwb", -1, true },
|
||||||
|
{ "amrnb-bwe", -1, true },
|
||||||
|
{ "amrwb-bwe", -1, true },
|
||||||
{ "gsmhr", -1, true },
|
{ "gsmhr", -1, true },
|
||||||
{ "gsmefr", 126, false },
|
{ "gsmefr", 126, false },
|
||||||
{ "evs", 127, false },
|
{ "evs", 127, false },
|
||||||
@@ -104,6 +107,10 @@ static MT::CodecList::Settings buildSettings(const std::string& codecName, int p
|
|||||||
s.mAmrNbOctetPayloadType.insert(pt);
|
s.mAmrNbOctetPayloadType.insert(pt);
|
||||||
} else if (codecName == "amrwb") {
|
} else if (codecName == "amrwb") {
|
||||||
s.mAmrWbOctetPayloadType.insert(pt);
|
s.mAmrWbOctetPayloadType.insert(pt);
|
||||||
|
} else if (codecName == "amrnb-bwe") {
|
||||||
|
s.mAmrNbPayloadType.insert(pt);
|
||||||
|
} else if (codecName == "amrwb-bwe") {
|
||||||
|
s.mAmrWbPayloadType.insert(pt);
|
||||||
} else if (codecName == "evs") {
|
} else if (codecName == "evs") {
|
||||||
MT::CodecList::Settings::EvsSpec ev;
|
MT::CodecList::Settings::EvsSpec ev;
|
||||||
ev.mPayloadType = pt;
|
ev.mPayloadType = pt;
|
||||||
|
|||||||
Reference in New Issue
Block a user