| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419 |
- #include "code/codec/codec_audio_encoder.h"
- #include "code/base/logger.h"
- #include "code/base/media_common.h"
- #include <iostream>
- #include <vector>
- #include <memory>
- #include <chrono>
- #include <fstream>
- #include <algorithm>
- #include <cmath>
- using namespace av;
- using namespace av::codec;
- /**
- * 音频编码器测试类
- */
- class AudioEncoderTester {
- public:
- AudioEncoderTester() {
- Logger::instance().setLevel(LogLevel::DEBUG);
- Logger::instance().info("=== 音频编码器测试套件 ===");
- }
-
- /**
- * 测试基本音频编码功能
- */
- bool testBasicAudioEncoding() {
- Logger::instance().info("[测试] 基本音频编码功能...");
-
- try {
- // 创建音频编码器
- auto encoder = AudioEncoderFactory::create("aac");
- if (!encoder) {
- Logger::instance().error("[失败] 无法创建AAC编码器");
- return false;
- }
-
- // 设置编码参数
- AudioEncoderParams params;
- params.codecName = "aac";
- params.bitRate = 128000;
- params.sampleRate = 44100;
- params.channels = 2;
- params.channelLayout = AV_CHANNEL_LAYOUT_STEREO;
- params.sampleFormat = AV_SAMPLE_FMT_FLTP;
- params.frameSize = 1024;
-
- // 打开编码器
- ErrorCode result = encoder->open(params);
- if (result != ErrorCode::OK) {
- Logger::instance().errorf("[失败] 打开编码器失败: {}", static_cast<int>(result));
- return false;
- }
-
- // 创建测试音频帧
- AVFramePtr frame = createTestAudioFrame(params);
- if (!frame) {
- Logger::instance().error("[失败] 创建测试音频帧失败");
- return false;
- }
-
- // 编码音频帧
- std::vector<AVPacketPtr> packets;
- result = encoder->encode(frame, packets);
- if (result != ErrorCode::OK) {
- Logger::instance().errorf("[失败] 编码音频帧失败: {}", static_cast<int>(result));
- return false;
- }
-
- Logger::instance().infof("[成功] 编码产生了 {} 个数据包", packets.size());
-
- // 关闭编码器
- encoder->close();
-
- Logger::instance().info("[成功] 基本音频编码测试通过");
- return true;
-
- } catch (const std::exception& e) {
- Logger::instance().errorf("[异常] {}", e.what());
- return false;
- }
- }
-
- /**
- * 测试多种音频编码器
- */
- bool testMultipleEncoders() {
- Logger::instance().info("[测试] 多种音频编码器支持...");
-
- auto supportedEncoders = AudioEncoder::getSupportedEncoders();
- Logger::instance().infof("支持的编码器数量: {}", supportedEncoders.size());
-
- if (supportedEncoders.empty()) {
- Logger::instance().warning("[警告] 没有找到支持的音频编码器");
- return false;
- }
-
- int successCount = 0;
- // 只测试几个主要的编码器,避免实验性编码器导致的问题
- std::vector<std::string> testEncoders = {"aac", "libmp3lame", "libopus", "flac"};
-
- for (const auto& codecName : testEncoders) {
- // 检查编码器是否在支持列表中
- if (std::find(supportedEncoders.begin(), supportedEncoders.end(), codecName) == supportedEncoders.end()) {
- Logger::instance().infof("跳过不支持的编码器: {}", codecName);
- continue;
- }
-
- Logger::instance().infof("测试编码器: {}", codecName);
-
- try {
- auto encoder = AudioEncoderFactory::create(codecName);
- if (!encoder) {
- Logger::instance().errorf(" [失败] 无法创建编码器: {}", codecName);
- continue;
- }
-
- AudioEncoderParams params;
- params.codecName = codecName;
- params.bitRate = 128000;
- params.sampleRate = 44100;
- params.channels = 2;
- params.channelLayout = AV_CHANNEL_LAYOUT_STEREO;
- params.sampleFormat = AV_SAMPLE_FMT_FLTP;
-
- ErrorCode result = encoder->open(params);
- if (result == ErrorCode::OK) {
- Logger::instance().infof(" [成功] {} 编码器打开成功", codecName);
- successCount++;
- } else {
- Logger::instance().errorf(" [失败] {} 编码器打开失败: {}", codecName, static_cast<int>(result));
- }
-
- // 确保编码器正确关闭
- encoder->close();
- encoder.reset(); // 释放编码器资源
-
- } catch (const std::exception& e) {
- Logger::instance().errorf(" [异常] 测试编码器 {} 时发生异常: {}", codecName, e.what());
- }
- }
-
- Logger::instance().infof("成功测试的编码器: {}/{}", successCount, testEncoders.size());
- return successCount > 0;
- }
-
- /**
- * 测试音频重采样功能
- */
- bool testAudioResampling() {
- Logger::instance().info("[测试] 音频重采样功能...");
-
- try {
- AudioResampler resampler;
-
- // 设置重采样参数:从48kHz立体声转换为44.1kHz立体声
- AVChannelLayout srcLayout = AV_CHANNEL_LAYOUT_STEREO;
- AVChannelLayout dstLayout = AV_CHANNEL_LAYOUT_STEREO;
-
- bool result = resampler.init(srcLayout, AV_SAMPLE_FMT_FLTP, 48000,
- dstLayout, AV_SAMPLE_FMT_FLTP, 44100);
- if (!result) {
- Logger::instance().error("[失败] 初始化重采样器失败");
- return false;
- }
-
- // 创建测试音频帧
- AudioEncoderParams params;
- params.sampleRate = 48000;
- params.channels = 2;
- params.sampleFormat = AV_SAMPLE_FMT_FLTP;
-
- AVFramePtr srcFrame = createTestAudioFrame(params);
- if (!srcFrame) {
- Logger::instance().error("[失败] 创建源音频帧失败");
- return false;
- }
-
- // 执行重采样
- AVFramePtr dstFrame = resampler.resample(srcFrame);
- if (!dstFrame) {
- Logger::instance().error("[失败] 音频重采样失败");
- return false;
- }
-
- Logger::instance().infof("[成功] 重采样: {}Hz -> {}Hz", srcFrame->sample_rate, dstFrame->sample_rate);
- Logger::instance().infof("[成功] 样本数: {} -> {}", srcFrame->nb_samples, dstFrame->nb_samples);
-
- return true;
-
- } catch (const std::exception& e) {
- Logger::instance().errorf("[异常] {}", e.what());
- return false;
- }
- }
-
- /**
- * 测试编码器工厂
- */
- bool testEncoderFactory() {
- Logger::instance().info("[测试] 编码器工厂功能...");
-
- // 测试创建最佳编码器
- auto bestEncoder = AudioEncoderFactory::createBest();
- if (!bestEncoder) {
- Logger::instance().error("[失败] 无法创建最佳编码器");
- return false;
- }
- Logger::instance().info("[成功] 创建最佳编码器");
-
- // 测试创建无损编码器
- auto losslessEncoder = AudioEncoderFactory::createLossless();
- if (!losslessEncoder) {
- Logger::instance().error("[失败] 无法创建无损编码器");
- return false;
- }
- Logger::instance().info("[成功] 创建无损编码器");
-
- // 测试推荐编码器
- std::string recommended = AudioEncoder::getRecommendedEncoder();
- if (recommended.empty()) {
- Logger::instance().error("[失败] 无法获取推荐编码器");
- return false;
- }
- Logger::instance().infof("[成功] 推荐编码器: {}", recommended);
-
- return true;
- }
-
- /**
- * 测试编码器状态管理
- */
- bool testEncoderStateManagement() {
- Logger::instance().info("[测试] 编码器状态管理...");
-
- try {
- auto encoder = AudioEncoderFactory::create("aac");
- if (!encoder) {
- Logger::instance().error("[失败] 无法创建编码器");
- return false;
- }
-
- // 测试初始状态
- if (encoder->getState() != CodecState::IDLE) {
- Logger::instance().error("[失败] 初始状态不正确");
- return false;
- }
-
- // 测试打开编码器
- AudioEncoderParams params;
- params.codecName = "aac";
- params.bitRate = 128000;
- params.sampleRate = 44100;
- params.channels = 2;
-
- ErrorCode result = encoder->open(params);
- if (result != ErrorCode::OK) {
- Logger::instance().error("[失败] 打开编码器失败");
- return false;
- }
-
- if (encoder->getState() != CodecState::OPENED) {
- Logger::instance().error("[失败] 打开后状态不正确");
- return false;
- }
-
- // 测试关闭编码器
- encoder->close();
- if (encoder->getState() != CodecState::CLOSED) {
- Logger::instance().error("[失败] 关闭后状态不正确");
- return false;
- }
-
- Logger::instance().info("[成功] 编码器状态管理测试通过");
- return true;
-
- } catch (const std::exception& e) {
- Logger::instance().errorf("[异常] {}", e.what());
- return false;
- }
- }
-
- /**
- * 测试错误处理
- */
- bool testErrorHandling() {
- Logger::instance().info("[测试] 错误处理...");
-
- try {
- // 测试无效编码器名称
- auto encoder = AudioEncoderFactory::create("invalid_codec");
- if (encoder) {
- AudioEncoderParams params;
- params.codecName = "invalid_codec";
- ErrorCode result = encoder->open(params);
- if (result == ErrorCode::OK) {
- Logger::instance().error("[失败] 应该拒绝无效编码器");
- return false;
- }
- }
-
- // 测试无效参数
- encoder = AudioEncoderFactory::create("aac");
- if (encoder) {
- AudioEncoderParams params;
- params.codecName = "aac";
- params.sampleRate = -1; // 无效采样率
- params.channels = 0; // 无效声道数
-
- ErrorCode result = encoder->open(params);
- if (result == ErrorCode::OK) {
- Logger::instance().error("[失败] 应该拒绝无效参数");
- return false;
- }
- }
-
- Logger::instance().info("[成功] 错误处理测试通过");
- return true;
-
- } catch (const std::exception& e) {
- Logger::instance().errorf("[异常] {}", e.what());
- return false;
- }
- }
-
- /**
- * 运行所有测试
- */
- bool runAllTests() {
- Logger::instance().info("开始运行音频编码器测试套件...");
-
- bool allPassed = true;
-
- allPassed &= testBasicAudioEncoding();
- allPassed &= testMultipleEncoders();
- allPassed &= testAudioResampling();
- allPassed &= testEncoderFactory();
- allPassed &= testEncoderStateManagement();
- allPassed &= testErrorHandling();
-
- Logger::instance().info("=== 测试结果 ===");
- if (allPassed) {
- Logger::instance().info("[成功] 所有音频编码器测试通过!");
- } else {
- Logger::instance().error("[失败] 部分测试失败!");
- }
-
- return allPassed;
- }
-
- private:
- /**
- * 创建测试音频帧
- */
- AVFramePtr createTestAudioFrame(const AudioEncoderParams& params) {
- AVFramePtr frame = makeAVFrame();
- if (!frame) {
- return nullptr;
- }
-
- frame->format = params.sampleFormat;
- frame->sample_rate = params.sampleRate;
- frame->nb_samples = params.frameSize > 0 ? params.frameSize : 1024;
-
- // 设置声道布局
- if (params.channelLayout.nb_channels > 0) {
- av_channel_layout_copy(&frame->ch_layout, ¶ms.channelLayout);
- } else {
- av_channel_layout_default(&frame->ch_layout, params.channels);
- }
-
- // 分配音频缓冲区
- int ret = av_frame_get_buffer(frame.get(), 0);
- if (ret < 0) {
- return nullptr;
- }
-
- // 填充测试数据(简单的正弦波)
- fillTestAudioData(frame.get());
-
- return frame;
- }
-
- /**
- * 填充测试音频数据
- */
- void fillTestAudioData(AVFrame* frame) {
- if (frame->format == AV_SAMPLE_FMT_FLTP) {
- // 浮点平面格式
- for (int ch = 0; ch < frame->ch_layout.nb_channels; ch++) {
- float* data = reinterpret_cast<float*>(frame->data[ch]);
- for (int i = 0; i < frame->nb_samples; i++) {
- // 生成440Hz正弦波
- double t = static_cast<double>(i) / frame->sample_rate;
- data[i] = static_cast<float>(0.5 * sin(2.0 * M_PI * 440.0 * t));
- }
- }
- } else if (frame->format == AV_SAMPLE_FMT_S16) {
- // 16位整数格式
- int16_t* data = reinterpret_cast<int16_t*>(frame->data[0]);
- for (int i = 0; i < frame->nb_samples * frame->ch_layout.nb_channels; i++) {
- double t = static_cast<double>(i / frame->ch_layout.nb_channels) / frame->sample_rate;
- data[i] = static_cast<int16_t>(16384 * sin(2.0 * M_PI * 440.0 * t));
- }
- }
- }
- };
- int main() {
- try {
- AudioEncoderTester tester;
- bool success = tester.runAllTests();
- return success ? 0 : 1;
- } catch (const std::exception& e) {
- Logger::instance().errorf("测试程序异常: {}", e.what());
- return 1;
- }
- }
|