mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-26 20:25:34 +08:00
Opus codec module test pass
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#include "OpusDecoderImpl.h"
|
||||
#define MAX_FRAME_SIZE 6 * 960
|
||||
#define CHANNELS 2
|
||||
#define MAX_FRAME_SIZE 960
|
||||
#define CHANNELS 1
|
||||
|
||||
OpusDecoderImpl::OpusDecoderImpl(int sampleRate, int channel) {
|
||||
int err;
|
||||
@@ -9,7 +9,7 @@ OpusDecoderImpl::OpusDecoderImpl(int sampleRate, int channel) {
|
||||
sample_rate = sample_rate;
|
||||
channel_num = channel;
|
||||
if (err < 0 || decoder == NULL) {
|
||||
printf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>\n");
|
||||
printf("Create opus decoder failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ bool OpusDecoderImpl::Decode(unsigned char* in_data, int len) {
|
||||
auto frame_size = opus_decode(decoder, in_data, len, out, MAX_FRAME_SIZE, 0);
|
||||
|
||||
if (frame_size < 0) {
|
||||
printf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>\n");
|
||||
printf("Invalid frame size\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ OpusEncoderImpl::OpusEncoderImpl(int sampleRate, int channel)
|
||||
|
||||
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_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,
|
||||
@@ -57,13 +57,13 @@ bool OpusEncoderImpl::PopFrame(StreamInfo &info) {
|
||||
// 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;
|
||||
const int frame_size = 48 * 20; // 1920
|
||||
int input_len = sizeof(opus_int16) * frame_size * channel_num;
|
||||
|
||||
OpusDecoderImpl decoder(48000, channel_num);
|
||||
OpusDecoderImpl decoder(sample_rate, channel_num);
|
||||
|
||||
opus_int16 input_data[frame_size * 2] = {0};
|
||||
unsigned char input_buffer[input_len] = {0};
|
||||
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) {
|
||||
@@ -99,6 +99,8 @@ void OpusEncoderImpl::EncodeRun() {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
}
|
||||
|
||||
free(input_buffer);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "OpusDecoderImpl.h"
|
||||
#include "base_type.h"
|
||||
#include "opus/opus.h"
|
||||
|
||||
@@ -21,6 +22,8 @@ class OpusEncoderImpl {
|
||||
std::mutex access_mutex;
|
||||
std::unique_ptr<std::thread> m_thread;
|
||||
|
||||
OpusDecoderImpl *decoder = nullptr;
|
||||
|
||||
public:
|
||||
OpusEncoderImpl(int sampleRate, int channel);
|
||||
void Feed(unsigned char *data, int len);
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
#include <SDL2/SDL.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavdevice/avdevice.h>
|
||||
#include <libavfilter/avfilter.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/channel_layout.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavutil/samplefmt.h>
|
||||
#include <libswresample/swresample.h>
|
||||
#include <libswscale/swscale.h>
|
||||
};
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
@@ -5,27 +22,197 @@
|
||||
#include "OpusEncoderImpl.h"
|
||||
#include "opus/opus.h"
|
||||
|
||||
int main() {
|
||||
OpusEncoderImpl* opusEncoder = new OpusEncoderImpl(48000, 2);
|
||||
static SDL_AudioDeviceID input_dev;
|
||||
static SDL_AudioDeviceID output_dev;
|
||||
|
||||
std::ifstream inputFile("ls.pcm", std::ios::binary);
|
||||
if (!inputFile) {
|
||||
std::cerr << "Failed to open input file." << std::endl;
|
||||
static Uint8 *buffer = 0;
|
||||
static int in_pos = 0;
|
||||
static int out_pos = 0;
|
||||
|
||||
char *out = "audio_old.pcm";
|
||||
FILE *outfile = fopen(out, "wb+");
|
||||
|
||||
static OpusEncoderImpl *opusEncoder = nullptr;
|
||||
|
||||
int64_t src_ch_layout = AV_CH_LAYOUT_MONO;
|
||||
int src_rate = 48000;
|
||||
enum AVSampleFormat src_sample_fmt = AV_SAMPLE_FMT_FLT;
|
||||
int src_nb_channels = 0;
|
||||
uint8_t **src_data = NULL; // <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
|
||||
int src_linesize;
|
||||
int src_nb_samples = 480;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
int64_t dst_ch_layout = AV_CH_LAYOUT_STEREO;
|
||||
int dst_rate = 48000;
|
||||
enum AVSampleFormat dst_sample_fmt = AV_SAMPLE_FMT_S16;
|
||||
int dst_nb_channels = 0;
|
||||
uint8_t **dst_data = NULL; // <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
|
||||
int dst_linesize;
|
||||
int dst_nb_samples;
|
||||
int max_dst_nb_samples;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
|
||||
const char *dst_filename = NULL; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>pcm<63><6D><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD>Ȼ<EFBFBD><EFBFBD><F3B2A5B7><EFBFBD>֤
|
||||
FILE *dst_file;
|
||||
|
||||
int dst_bufsize;
|
||||
const char *fmt;
|
||||
|
||||
// <20>ز<EFBFBD><D8B2><EFBFBD>ʵ<EFBFBD><CAB5>
|
||||
struct SwrContext *swr_ctx;
|
||||
|
||||
double t;
|
||||
int ret;
|
||||
|
||||
void cb_in(void *userdata, Uint8 *stream, int len) {
|
||||
// If len < 4, the printf below will probably segfault
|
||||
{
|
||||
fwrite(stream, 1, len, outfile);
|
||||
fflush(outfile);
|
||||
}
|
||||
{
|
||||
int64_t delay = swr_get_delay(swr_ctx, src_rate);
|
||||
dst_nb_samples =
|
||||
av_rescale_rnd(delay + src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
|
||||
if (dst_nb_samples > max_dst_nb_samples) {
|
||||
av_freep(&dst_data[0]);
|
||||
ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels,
|
||||
dst_nb_samples, dst_sample_fmt, 1);
|
||||
if (ret < 0) return;
|
||||
max_dst_nb_samples = dst_nb_samples;
|
||||
}
|
||||
|
||||
ret = swr_convert(swr_ctx, dst_data, dst_nb_samples,
|
||||
(const uint8_t **)&stream, src_nb_samples);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error while converting\n");
|
||||
return;
|
||||
}
|
||||
dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
|
||||
ret, dst_sample_fmt, 1);
|
||||
if (dst_bufsize < 0) {
|
||||
fprintf(stderr, "Could not get sample buffer size\n");
|
||||
return;
|
||||
}
|
||||
printf("t:%f in:%d out:%d\n", t, src_nb_samples, ret);
|
||||
fwrite(dst_data[0], 1, dst_bufsize, dst_file);
|
||||
opusEncoder->Feed(dst_data[0], dst_bufsize);
|
||||
}
|
||||
}
|
||||
|
||||
void cb_out(void *userdata, Uint8 *stream, int len) {
|
||||
// If len < 4, the printf below will probably segfault
|
||||
|
||||
SDL_memcpy(buffer + out_pos, stream, len);
|
||||
out_pos += len;
|
||||
}
|
||||
|
||||
int init() {
|
||||
dst_filename = "res.pcm";
|
||||
|
||||
dst_file = fopen(dst_filename, "wb");
|
||||
if (!dst_file) {
|
||||
fprintf(stderr, "Could not open destination file %s\n", dst_filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD><D8B2><EFBFBD><EFBFBD><EFBFBD>
|
||||
/* create resampler context */
|
||||
swr_ctx = swr_alloc();
|
||||
if (!swr_ctx) {
|
||||
fprintf(stderr, "Could not allocate resampler context\n");
|
||||
ret = AVERROR(ENOMEM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char sample[960];
|
||||
while (inputFile.read(sample, 960)) {
|
||||
opusEncoder->Feed((unsigned char*)sample, 960);
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD><D8B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/* set options */
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0);
|
||||
av_opt_set_int(swr_ctx, "in_sample_rate", src_rate, 0);
|
||||
av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", src_sample_fmt, 0);
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout, 0);
|
||||
av_opt_set_int(swr_ctx, "out_sample_rate", dst_rate, 0);
|
||||
av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", dst_sample_fmt, 0);
|
||||
|
||||
// <20><>ʼ<EFBFBD><CABC><EFBFBD>ز<EFBFBD><D8B2><EFBFBD>
|
||||
/* initialize the resampling context */
|
||||
if ((ret = swr_init(swr_ctx)) < 0) {
|
||||
fprintf(stderr, "Failed to initialize the resampling context\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// // <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>opus<75><73>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD>̣߳<DFB3><CCA3><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB>Ϊ<EFBFBD>˷<EFBFBD><CBB7><EFBFBD>
|
||||
// StreamInfo info;
|
||||
// while (opusEncoder.PopFrame(info)) {
|
||||
// .....
|
||||
// }
|
||||
/* allocate source and destination samples buffers */
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout);
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>ռ<EFBFBD>
|
||||
ret = av_samples_alloc_array_and_samples(&src_data, &src_linesize,
|
||||
src_nb_channels, src_nb_samples,
|
||||
src_sample_fmt, 0);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Could not allocate source samples\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* compute the number of converted samples: buffering is avoided
|
||||
* ensuring that the output buffer will contain at least all the
|
||||
* converted input samples */
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
max_dst_nb_samples = dst_nb_samples =
|
||||
av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
|
||||
|
||||
/* buffer is going to be directly written to a rawaudio file, no alignment */
|
||||
dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
|
||||
ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize,
|
||||
dst_nb_channels, dst_nb_samples,
|
||||
dst_sample_fmt, 0);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Could not allocate destination samples\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
init();
|
||||
|
||||
SDL_Init(SDL_INIT_AUDIO);
|
||||
|
||||
// 16Mb should be enough; the test lasts 5 seconds
|
||||
buffer = (Uint8 *)malloc(16777215);
|
||||
|
||||
SDL_AudioSpec want_in, want_out, have_in, have_out;
|
||||
|
||||
SDL_zero(want_in);
|
||||
want_in.freq = 48000;
|
||||
want_in.format = AUDIO_F32LSB;
|
||||
want_in.channels = 2;
|
||||
want_in.samples = 960;
|
||||
want_in.callback = cb_in;
|
||||
|
||||
input_dev = SDL_OpenAudioDevice(NULL, 1, &want_in, &have_in,
|
||||
SDL_AUDIO_ALLOW_ANY_CHANGE);
|
||||
|
||||
printf("%d %d %d %d\n", have_in.freq, have_in.format, have_in.channels,
|
||||
have_in.samples);
|
||||
if (input_dev == 0) {
|
||||
SDL_Log("Failed to open input: %s", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_PauseAudioDevice(input_dev, 0);
|
||||
SDL_PauseAudioDevice(output_dev, 0);
|
||||
|
||||
opusEncoder = new OpusEncoderImpl(have_in.freq, have_in.channels);
|
||||
|
||||
SDL_Delay(5000);
|
||||
|
||||
opusEncoder->Stop();
|
||||
SDL_CloseAudioDevice(output_dev);
|
||||
SDL_CloseAudioDevice(input_dev);
|
||||
free(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
fclose(outfile);
|
||||
}
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
// Opus<75><73><EFBFBD>뺯<EFBFBD><EBBAAF>
|
||||
#include <opus/opus.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#define SAMPLE_RATE 48000
|
||||
#define CHANNELS 2
|
||||
#define FRAME_SIZE 960
|
||||
#define APPLICATION OPUS_APPLICATION_AUDIO
|
||||
|
||||
// <20><><EFBFBD>뺯<EFBFBD><EBBAAF>
|
||||
int encode(const std::vector<opus_int16>& pcm,
|
||||
std::vector<unsigned char>& opus) {
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
int error;
|
||||
OpusEncoder* encoder =
|
||||
opus_encoder_create(SAMPLE_RATE, CHANNELS, APPLICATION, &error);
|
||||
if (error != OPUS_OK) {
|
||||
std::cerr << "Failed to create encoder: " << opus_strerror(error)
|
||||
<< std::endl;
|
||||
return error;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
opus_encoder_ctl(encoder, OPUS_SET_BITRATE(64000));
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
|
||||
int maxOpusSize = FRAME_SIZE * CHANNELS * sizeof(opus_int16);
|
||||
opus.resize(maxOpusSize);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD>
|
||||
int encodedSize =
|
||||
opus_encode(encoder, pcm.data(), FRAME_SIZE, opus.data(), maxOpusSize);
|
||||
if (encodedSize < 0) {
|
||||
std::cerr << "Encoding error: " << opus_strerror(encodedSize) << std::endl;
|
||||
return encodedSize;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
|
||||
opus_encoder_destroy(encoder);
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD>С
|
||||
opus.resize(encodedSize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc != 3) {
|
||||
std::cerr << "Usage: " << argv[0] << " input.pcm output.opus" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
|
||||
std::ifstream inputFile(argv[1], std::ios::binary);
|
||||
if (!inputFile) {
|
||||
std::cerr << "Failed to open input file." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// <20><>ȡPCM<43><4D><EFBFBD><EFBFBD>
|
||||
std::vector<opus_int16> pcmData;
|
||||
opus_int16 sample;
|
||||
while (inputFile.read(reinterpret_cast<char*>(&sample), sizeof(opus_int16))) {
|
||||
pcmData.push_back(sample);
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD>ΪOpus<75><73>ʽ
|
||||
std::vector<unsigned char> opusData;
|
||||
int result = encode(pcmData, opusData);
|
||||
if (result != 0) {
|
||||
std::cerr << "Encoding failed with error code " << result << std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
|
||||
std::ofstream outputFile(argv[2], std::ios::binary);
|
||||
if (!outputFile) {
|
||||
std::cerr << "Failed to open output file." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// д<><D0B4>Opus<75><73><EFBFBD><EFBFBD>
|
||||
outputFile.write(reinterpret_cast<const char*>(opusData.data()),
|
||||
opusData.size());
|
||||
|
||||
// <20><><EFBFBD><EFBFBD>
|
||||
std::cout << "Encoding complete. size:" << pcmData.size() * 2 << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user