- fix Opus decoder - now audio is smooth

This commit is contained in:
Dmytro Bogovych 2024-11-11 12:52:50 +03:00
parent 8cb34fad83
commit e0b02db39d
2 changed files with 31 additions and 20 deletions

View File

@ -410,7 +410,7 @@ OpusCodec::OpusCodec(int samplerate, int channels, int ptime)
:mEncoderCtx(nullptr), mDecoderCtx(nullptr), mChannels(channels), mPTime(ptime), mSamplerate(samplerate), mDecoderChannels(0) :mEncoderCtx(nullptr), mDecoderCtx(nullptr), mChannels(channels), mPTime(ptime), mSamplerate(samplerate), mDecoderChannels(0)
{ {
int status; int status;
mEncoderCtx = opus_encoder_create(48000, mChannels, OPUS_APPLICATION_VOIP, &status); mEncoderCtx = opus_encoder_create(mSamplerate, mChannels, OPUS_APPLICATION_VOIP, &status);
if (OPUS_OK != opus_encoder_ctl(mEncoderCtx, OPUS_SET_COMPLEXITY(OPUS_CODEC_COMPLEXITY))) if (OPUS_OK != opus_encoder_ctl(mEncoderCtx, OPUS_SET_COMPLEXITY(OPUS_CODEC_COMPLEXITY)))
ICELogError(<< "Failed to set Opus encoder complexity"); ICELogError(<< "Failed to set Opus encoder complexity");
//if (OPUS_OK != opus_encoder_ctl(mEncoderCtx, OPUS_SET_FORCE_CHANNELS(AUDIO_CHANNELS))) //if (OPUS_OK != opus_encoder_ctl(mEncoderCtx, OPUS_SET_FORCE_CHANNELS(AUDIO_CHANNELS)))
@ -433,7 +433,7 @@ void OpusCodec::applyParams(const Params &params)
if (OPUS_OK != (error = opus_encoder_ctl(mEncoderCtx, OPUS_SET_PACKET_LOSS_PERC(params.mExpectedPacketLoss)))) if (OPUS_OK != (error = opus_encoder_ctl(mEncoderCtx, OPUS_SET_PACKET_LOSS_PERC(params.mExpectedPacketLoss))))
ICELogError(<< "Failed to (un)set expected packet loss. Error " << opus_strerror(error)); ICELogError(<< "Failed to (un)set expected packet loss. Error " << opus_strerror(error));
mDecodeResampler.start(channels(), 48000, mSamplerate); // mDecodeResampler.start(channels(), 48000, mSamplerate);
} }
OpusCodec::~OpusCodec() OpusCodec::~OpusCodec()
@ -493,10 +493,10 @@ int OpusCodec::encode(const void* input, int inputBytes, void* output, int outpu
int OpusCodec::decode(const void* input, int inputBytes, void* output, int outputCapacity) int OpusCodec::decode(const void* input, int inputBytes, void* output, int outputCapacity)
{ {
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((const unsigned char *) input);
int nr_of_frames = opus_decoder_get_nb_samples(mDecoderCtx, (const unsigned char *) input,
inputBytes);
// Recreate decoder if needed // Recreate decoder if needed
if (mDecoderChannels != nr_of_channels) if (mDecoderChannels != nr_of_channels)
@ -508,42 +508,53 @@ int OpusCodec::decode(const void* input, int inputBytes, void* output, int outpu
} }
mDecoderChannels = nr_of_channels; mDecoderChannels = nr_of_channels;
} }
int status = 0;
mDecoderCtx = opus_decoder_create(48000, mDecoderChannels, &status); if (!mDecoderCtx)
if (status) {
return 0; int status = 0;
mDecoderCtx = opus_decoder_create(mSamplerate, mDecoderChannels, &status);
if (status)
return 0;
}
int nr_of_frames = opus_decoder_get_nb_samples(mDecoderCtx, (const unsigned char *) input,
inputBytes);
// 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,
reinterpret_cast<const unsigned char *>(input), inputBytes, reinterpret_cast<const unsigned char *>(input), inputBytes,
buffer_decode, nr_of_frames, 0); buffer_decode, nr_of_frames, 0);
size_t resampler_processed = 0; size_t resampler_processed = 0;
opus_int16 *buffer_stereo = nullptr; opus_int16 *buffer_stereo = nullptr;
int buffer_stereo_capacity = buffer_capacity * 2;
switch (nr_of_channels) { switch (nr_of_channels) {
case 1: case 1:
// Convert to stereo before // Convert to stereo before
buffer_stereo = (opus_int16 *) alloca(buffer_capacity * 2); buffer_stereo = (opus_int16 *) alloca(buffer_stereo_capacity);
for (int i = 0; i < nr_of_frames; i++) { for (int i = 0; i < nr_of_frames; i++) {
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];
} }
return (int) mDecodeResampler.processBuffer(buffer_stereo, assert(buffer_stereo_capacity <= outputCapacity);
decoded * sizeof(opus_int16) * 2, memcpy(output, buffer_stereo, buffer_stereo_capacity);
resampler_processed, output, result = buffer_stereo_capacity;
outputCapacity);
break; break;
case 2: case 2:
return (int) mDecodeResampler.processBuffer(buffer_decode, assert(buffer_capacity <= outputCapacity);
decoded * sizeof(opus_int16) * memcpy(output, buffer_decode, buffer_capacity);
nr_of_channels, resampler_processed, output, result = buffer_capacity;
outputCapacity); break;
default:
assert(0);
} }
return 0; return result;
} }
int OpusCodec::plc(int lostPackets, void* output, int outputCapacity) int OpusCodec::plc(int lostPackets, void* output, int outputCapacity)

View File

@ -73,7 +73,7 @@ protected:
OpusEncoder *mEncoderCtx; OpusEncoder *mEncoderCtx;
OpusDecoder *mDecoderCtx; OpusDecoder *mDecoderCtx;
int mPTime, mSamplerate, mChannels; int mPTime, mSamplerate, mChannels;
Audio::SpeexResampler mDecodeResampler; // Audio::SpeexResampler mDecodeResampler;
int mDecoderChannels; int mDecoderChannels;
public: public:
struct Params struct Params