Files
crossdesk/tests/opus/OpusEncoderImpl.cpp
2024-09-02 16:31:33 +08:00

118 lines
3.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "OpusEncoderImpl.h"
#include <stdlib.h>
#include <chrono>
#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("打开opus 编码器失败\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(sample_rate * channel_num));
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)); // 每个采样16个bit2个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 rate48 samples/ms * 20ms * 2 channel = 1920
void OpusEncoderImpl::EncodeRun() {
m_thread = std::thread([this]() {
const int frame_size = 48 * 20; // 1920
int input_len = sizeof(opus_int16) * frame_size * channel_num;
OpusDecoderImpl decoder(sample_rate, channel_num);
opus_int16 input_data[frame_size] = {0};
unsigned char *input_buffer = new unsigned char[input_len];
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 {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
free(input_buffer);
});
}
void OpusEncoderImpl::Stop() {
isRuning = false;
m_thread->join();
while (pcm_queue.size() > 0) {
pcm_queue.pop();
}
opus_encoder_destroy(encoder);
}
OpusEncoderImpl::~OpusEncoderImpl() {}