test_audio_encoder.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. #include "code/codec/codec_audio_encoder.h"
  2. #include "code/base/logger.h"
  3. #include "code/base/media_common.h"
  4. #include <iostream>
  5. #include <vector>
  6. #include <memory>
  7. #include <chrono>
  8. #include <fstream>
  9. #include <algorithm>
  10. #include <cmath>
  11. using namespace av;
  12. using namespace av::codec;
  13. /**
  14. * 音频编码器测试类
  15. */
  16. class AudioEncoderTester {
  17. public:
  18. AudioEncoderTester() {
  19. Logger::instance().setLevel(LogLevel::DEBUG);
  20. Logger::instance().info("=== 音频编码器测试套件 ===");
  21. }
  22. /**
  23. * 测试基本音频编码功能
  24. */
  25. bool testBasicAudioEncoding() {
  26. Logger::instance().info("[测试] 基本音频编码功能...");
  27. try {
  28. // 创建音频编码器
  29. auto encoder = AudioEncoderFactory::create("aac");
  30. if (!encoder) {
  31. Logger::instance().error("[失败] 无法创建AAC编码器");
  32. return false;
  33. }
  34. // 设置编码参数
  35. AudioEncoderParams params;
  36. params.codecName = "aac";
  37. params.bitRate = 128000;
  38. params.sampleRate = 44100;
  39. params.channels = 2;
  40. params.channelLayout = AV_CHANNEL_LAYOUT_STEREO;
  41. params.sampleFormat = AV_SAMPLE_FMT_FLTP;
  42. params.frameSize = 1024;
  43. // 打开编码器
  44. ErrorCode result = encoder->open(params);
  45. if (result != ErrorCode::OK) {
  46. Logger::instance().errorf("[失败] 打开编码器失败: {}", static_cast<int>(result));
  47. return false;
  48. }
  49. // 创建测试音频帧
  50. AVFramePtr frame = createTestAudioFrame(params);
  51. if (!frame) {
  52. Logger::instance().error("[失败] 创建测试音频帧失败");
  53. return false;
  54. }
  55. // 编码音频帧
  56. std::vector<AVPacketPtr> packets;
  57. result = encoder->encode(frame, packets);
  58. if (result != ErrorCode::OK) {
  59. Logger::instance().errorf("[失败] 编码音频帧失败: {}", static_cast<int>(result));
  60. return false;
  61. }
  62. Logger::instance().infof("[成功] 编码产生了 {} 个数据包", packets.size());
  63. // 关闭编码器
  64. encoder->close();
  65. Logger::instance().info("[成功] 基本音频编码测试通过");
  66. return true;
  67. } catch (const std::exception& e) {
  68. Logger::instance().errorf("[异常] {}", e.what());
  69. return false;
  70. }
  71. }
  72. /**
  73. * 测试多种音频编码器
  74. */
  75. bool testMultipleEncoders() {
  76. Logger::instance().info("[测试] 多种音频编码器支持...");
  77. auto supportedEncoders = AudioEncoder::getSupportedEncoders();
  78. Logger::instance().infof("支持的编码器数量: {}", supportedEncoders.size());
  79. if (supportedEncoders.empty()) {
  80. Logger::instance().warning("[警告] 没有找到支持的音频编码器");
  81. return false;
  82. }
  83. int successCount = 0;
  84. // 只测试几个主要的编码器,避免实验性编码器导致的问题
  85. std::vector<std::string> testEncoders = {"aac", "libmp3lame", "libopus", "flac"};
  86. for (const auto& codecName : testEncoders) {
  87. // 检查编码器是否在支持列表中
  88. if (std::find(supportedEncoders.begin(), supportedEncoders.end(), codecName) == supportedEncoders.end()) {
  89. Logger::instance().infof("跳过不支持的编码器: {}", codecName);
  90. continue;
  91. }
  92. Logger::instance().infof("测试编码器: {}", codecName);
  93. try {
  94. auto encoder = AudioEncoderFactory::create(codecName);
  95. if (!encoder) {
  96. Logger::instance().errorf(" [失败] 无法创建编码器: {}", codecName);
  97. continue;
  98. }
  99. AudioEncoderParams params;
  100. params.codecName = codecName;
  101. params.bitRate = 128000;
  102. params.sampleRate = 44100;
  103. params.channels = 2;
  104. params.channelLayout = AV_CHANNEL_LAYOUT_STEREO;
  105. params.sampleFormat = AV_SAMPLE_FMT_FLTP;
  106. ErrorCode result = encoder->open(params);
  107. if (result == ErrorCode::OK) {
  108. Logger::instance().infof(" [成功] {} 编码器打开成功", codecName);
  109. successCount++;
  110. } else {
  111. Logger::instance().errorf(" [失败] {} 编码器打开失败: {}", codecName, static_cast<int>(result));
  112. }
  113. // 确保编码器正确关闭
  114. encoder->close();
  115. encoder.reset(); // 释放编码器资源
  116. } catch (const std::exception& e) {
  117. Logger::instance().errorf(" [异常] 测试编码器 {} 时发生异常: {}", codecName, e.what());
  118. }
  119. }
  120. Logger::instance().infof("成功测试的编码器: {}/{}", successCount, testEncoders.size());
  121. return successCount > 0;
  122. }
  123. /**
  124. * 测试音频重采样功能
  125. */
  126. bool testAudioResampling() {
  127. Logger::instance().info("[测试] 音频重采样功能...");
  128. try {
  129. AudioResampler resampler;
  130. // 设置重采样参数:从48kHz立体声转换为44.1kHz立体声
  131. AVChannelLayout srcLayout = AV_CHANNEL_LAYOUT_STEREO;
  132. AVChannelLayout dstLayout = AV_CHANNEL_LAYOUT_STEREO;
  133. bool result = resampler.init(srcLayout, AV_SAMPLE_FMT_FLTP, 48000,
  134. dstLayout, AV_SAMPLE_FMT_FLTP, 44100);
  135. if (!result) {
  136. Logger::instance().error("[失败] 初始化重采样器失败");
  137. return false;
  138. }
  139. // 创建测试音频帧
  140. AudioEncoderParams params;
  141. params.sampleRate = 48000;
  142. params.channels = 2;
  143. params.sampleFormat = AV_SAMPLE_FMT_FLTP;
  144. AVFramePtr srcFrame = createTestAudioFrame(params);
  145. if (!srcFrame) {
  146. Logger::instance().error("[失败] 创建源音频帧失败");
  147. return false;
  148. }
  149. // 执行重采样
  150. AVFramePtr dstFrame = resampler.resample(srcFrame);
  151. if (!dstFrame) {
  152. Logger::instance().error("[失败] 音频重采样失败");
  153. return false;
  154. }
  155. Logger::instance().infof("[成功] 重采样: {}Hz -> {}Hz", srcFrame->sample_rate, dstFrame->sample_rate);
  156. Logger::instance().infof("[成功] 样本数: {} -> {}", srcFrame->nb_samples, dstFrame->nb_samples);
  157. return true;
  158. } catch (const std::exception& e) {
  159. Logger::instance().errorf("[异常] {}", e.what());
  160. return false;
  161. }
  162. }
  163. /**
  164. * 测试编码器工厂
  165. */
  166. bool testEncoderFactory() {
  167. Logger::instance().info("[测试] 编码器工厂功能...");
  168. // 测试创建最佳编码器
  169. auto bestEncoder = AudioEncoderFactory::createBest();
  170. if (!bestEncoder) {
  171. Logger::instance().error("[失败] 无法创建最佳编码器");
  172. return false;
  173. }
  174. Logger::instance().info("[成功] 创建最佳编码器");
  175. // 测试创建无损编码器
  176. auto losslessEncoder = AudioEncoderFactory::createLossless();
  177. if (!losslessEncoder) {
  178. Logger::instance().error("[失败] 无法创建无损编码器");
  179. return false;
  180. }
  181. Logger::instance().info("[成功] 创建无损编码器");
  182. // 测试推荐编码器
  183. std::string recommended = AudioEncoder::getRecommendedEncoder();
  184. if (recommended.empty()) {
  185. Logger::instance().error("[失败] 无法获取推荐编码器");
  186. return false;
  187. }
  188. Logger::instance().infof("[成功] 推荐编码器: {}", recommended);
  189. return true;
  190. }
  191. /**
  192. * 测试编码器状态管理
  193. */
  194. bool testEncoderStateManagement() {
  195. Logger::instance().info("[测试] 编码器状态管理...");
  196. try {
  197. auto encoder = AudioEncoderFactory::create("aac");
  198. if (!encoder) {
  199. Logger::instance().error("[失败] 无法创建编码器");
  200. return false;
  201. }
  202. // 测试初始状态
  203. if (encoder->getState() != CodecState::IDLE) {
  204. Logger::instance().error("[失败] 初始状态不正确");
  205. return false;
  206. }
  207. // 测试打开编码器
  208. AudioEncoderParams params;
  209. params.codecName = "aac";
  210. params.bitRate = 128000;
  211. params.sampleRate = 44100;
  212. params.channels = 2;
  213. ErrorCode result = encoder->open(params);
  214. if (result != ErrorCode::OK) {
  215. Logger::instance().error("[失败] 打开编码器失败");
  216. return false;
  217. }
  218. if (encoder->getState() != CodecState::OPENED) {
  219. Logger::instance().error("[失败] 打开后状态不正确");
  220. return false;
  221. }
  222. // 测试关闭编码器
  223. encoder->close();
  224. if (encoder->getState() != CodecState::CLOSED) {
  225. Logger::instance().error("[失败] 关闭后状态不正确");
  226. return false;
  227. }
  228. Logger::instance().info("[成功] 编码器状态管理测试通过");
  229. return true;
  230. } catch (const std::exception& e) {
  231. Logger::instance().errorf("[异常] {}", e.what());
  232. return false;
  233. }
  234. }
  235. /**
  236. * 测试错误处理
  237. */
  238. bool testErrorHandling() {
  239. Logger::instance().info("[测试] 错误处理...");
  240. try {
  241. // 测试无效编码器名称
  242. auto encoder = AudioEncoderFactory::create("invalid_codec");
  243. if (encoder) {
  244. AudioEncoderParams params;
  245. params.codecName = "invalid_codec";
  246. ErrorCode result = encoder->open(params);
  247. if (result == ErrorCode::OK) {
  248. Logger::instance().error("[失败] 应该拒绝无效编码器");
  249. return false;
  250. }
  251. }
  252. // 测试无效参数
  253. encoder = AudioEncoderFactory::create("aac");
  254. if (encoder) {
  255. AudioEncoderParams params;
  256. params.codecName = "aac";
  257. params.sampleRate = -1; // 无效采样率
  258. params.channels = 0; // 无效声道数
  259. ErrorCode result = encoder->open(params);
  260. if (result == ErrorCode::OK) {
  261. Logger::instance().error("[失败] 应该拒绝无效参数");
  262. return false;
  263. }
  264. }
  265. Logger::instance().info("[成功] 错误处理测试通过");
  266. return true;
  267. } catch (const std::exception& e) {
  268. Logger::instance().errorf("[异常] {}", e.what());
  269. return false;
  270. }
  271. }
  272. /**
  273. * 运行所有测试
  274. */
  275. bool runAllTests() {
  276. Logger::instance().info("开始运行音频编码器测试套件...");
  277. bool allPassed = true;
  278. allPassed &= testBasicAudioEncoding();
  279. allPassed &= testMultipleEncoders();
  280. allPassed &= testAudioResampling();
  281. allPassed &= testEncoderFactory();
  282. allPassed &= testEncoderStateManagement();
  283. allPassed &= testErrorHandling();
  284. Logger::instance().info("=== 测试结果 ===");
  285. if (allPassed) {
  286. Logger::instance().info("[成功] 所有音频编码器测试通过!");
  287. } else {
  288. Logger::instance().error("[失败] 部分测试失败!");
  289. }
  290. return allPassed;
  291. }
  292. private:
  293. /**
  294. * 创建测试音频帧
  295. */
  296. AVFramePtr createTestAudioFrame(const AudioEncoderParams& params) {
  297. AVFramePtr frame = makeAVFrame();
  298. if (!frame) {
  299. return nullptr;
  300. }
  301. frame->format = params.sampleFormat;
  302. frame->sample_rate = params.sampleRate;
  303. frame->nb_samples = params.frameSize > 0 ? params.frameSize : 1024;
  304. // 设置声道布局
  305. if (params.channelLayout.nb_channels > 0) {
  306. av_channel_layout_copy(&frame->ch_layout, &params.channelLayout);
  307. } else {
  308. av_channel_layout_default(&frame->ch_layout, params.channels);
  309. }
  310. // 分配音频缓冲区
  311. int ret = av_frame_get_buffer(frame.get(), 0);
  312. if (ret < 0) {
  313. return nullptr;
  314. }
  315. // 填充测试数据(简单的正弦波)
  316. fillTestAudioData(frame.get());
  317. return frame;
  318. }
  319. /**
  320. * 填充测试音频数据
  321. */
  322. void fillTestAudioData(AVFrame* frame) {
  323. if (frame->format == AV_SAMPLE_FMT_FLTP) {
  324. // 浮点平面格式
  325. for (int ch = 0; ch < frame->ch_layout.nb_channels; ch++) {
  326. float* data = reinterpret_cast<float*>(frame->data[ch]);
  327. for (int i = 0; i < frame->nb_samples; i++) {
  328. // 生成440Hz正弦波
  329. double t = static_cast<double>(i) / frame->sample_rate;
  330. data[i] = static_cast<float>(0.5 * sin(2.0 * M_PI * 440.0 * t));
  331. }
  332. }
  333. } else if (frame->format == AV_SAMPLE_FMT_S16) {
  334. // 16位整数格式
  335. int16_t* data = reinterpret_cast<int16_t*>(frame->data[0]);
  336. for (int i = 0; i < frame->nb_samples * frame->ch_layout.nb_channels; i++) {
  337. double t = static_cast<double>(i / frame->ch_layout.nb_channels) / frame->sample_rate;
  338. data[i] = static_cast<int16_t>(16384 * sin(2.0 * M_PI * 440.0 * t));
  339. }
  340. }
  341. }
  342. };
  343. int main() {
  344. try {
  345. AudioEncoderTester tester;
  346. bool success = tester.runAllTests();
  347. return success ? 0 : 1;
  348. } catch (const std::exception& e) {
  349. Logger::instance().errorf("测试程序异常: {}", e.what());
  350. return 1;
  351. }
  352. }