Add opus codec test

This commit is contained in:
dijunkun
2023-11-21 22:30:25 -08:00
parent 19506af831
commit e44c5b1cc7
12 changed files with 368 additions and 2 deletions

View File

@@ -0,0 +1,116 @@
#include "OpusEncoderImpl.h"
#include <stdlib.h>
#include <unistd.h>
#include <cstring>
#include "OpusDecoderImpl.h"
#define MAX_PACKET_SIZE 3 * 1276
OpusEncoderImpl::OpusEncoderImpl(int sampleRate, int channel)
: channel_num(channel), sample_rate(sampleRate) {
int err;
int applications[3] = {OPUS_APPLICATION_AUDIO, OPUS_APPLICATION_VOIP,
OPUS_APPLICATION_RESTRICTED_LOWDELAY};
encoder = opus_encoder_create(sampleRate, channel_num, applications[1], &err);
if (err != OPUS_OK || encoder == NULL) {
printf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>opus <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>\n");
}
opus_encoder_ctl(encoder, OPUS_SET_VBR(0)); // 0:CBR, 1:VBR
opus_encoder_ctl(encoder, OPUS_SET_VBR_CONSTRAINT(true));
opus_encoder_ctl(encoder, OPUS_SET_BITRATE(96000));
opus_encoder_ctl(encoder, OPUS_SET_COMPLEXITY(8)); // 8 0~10
opus_encoder_ctl(encoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
opus_encoder_ctl(encoder,
OPUS_SET_LSB_DEPTH(16)); // ÿ<><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>16<31><36>bit<69><74>2<EFBFBD><32>byte
opus_encoder_ctl(encoder, OPUS_SET_DTX(0));
opus_encoder_ctl(encoder, OPUS_SET_INBAND_FEC(0));
EncodeRun();
}
// every pcm frame takes 23ms
void OpusEncoderImpl::Feed(unsigned char *data, int len) {
mutex.lock();
for (auto i = 0; i < len; i++) {
pcm_queue.emplace(data[i]);
}
mutex.unlock();
}
bool OpusEncoderImpl::PopFrame(StreamInfo &info) {
if (info_queue.size() > 0) {
access_mutex.lock();
info = info_queue.front();
info_queue.pop();
access_mutex.unlock();
return true;
}
return false;
}
// 48000 sample rate<74><65>48 samples/ms * 20ms * 2 channel = 1920
void OpusEncoderImpl::EncodeRun() {
m_thread = std::make_unique<std::thread>([this]() {
const int frame_size = 48 * 20; // 960
const int input_len = sizeof(opus_int16) * frame_size * 2;
OpusDecoderImpl decoder(48000, channel_num);
opus_int16 input_data[frame_size * 2] = {0};
unsigned char input_buffer[input_len] = {0};
unsigned char out_data[MAX_PACKET_SIZE] = {0};
while (isRuning) {
if (pcm_queue.size() >= input_len) {
mutex.lock();
for (int i = 0; i < input_len; i++) {
input_buffer[i] = pcm_queue.front();
pcm_queue.pop();
}
mutex.unlock();
auto ret = opus_encode(encoder, (opus_int16 *)input_buffer, frame_size,
out_data, MAX_PACKET_SIZE);
if (ret < 0) {
printf("opus decode failed, %d\n", ret);
break;
}
unsigned char *opus_buffer = (unsigned char *)malloc(ret);
memcpy(opus_buffer, out_data, ret);
decoder.Decode(opus_buffer, ret);
StreamInfo info;
info.data = opus_buffer;
info.len = ret;
info.dts = 20;
access_mutex.lock();
info_queue.push(info);
access_mutex.unlock();
} else {
usleep(1000);
}
}
});
}
void OpusEncoderImpl::Stop() {
isRuning = false;
m_thread->join();
while (pcm_queue.size() > 0) {
pcm_queue.pop();
}
opus_encoder_destroy(encoder);
}
OpusEncoderImpl::~OpusEncoderImpl() {}