| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- #include "code/muxer/muxer_abstract_muxer.h"
- #include "code/muxer/muxer_file_muxer.h"
- #include "code/muxer/muxer_stream_muxer.h"
- #include "code/base/logger.h"
- #include "code/base/media_common.h"
- #include <iostream>
- #include <memory>
- #include <vector>
- #include <chrono>
- #include <thread>
- #include <filesystem>
- using namespace av;
- using namespace av::muxer;
- // 测试结果统计
- struct TestResults {
- int totalTests = 0;
- int passedTests = 0;
- std::vector<std::string> failedTests;
-
- void addTest(const std::string& testName, bool passed) {
- totalTests++;
- if (passed) {
- passedTests++;
- AV_LOGGER_INFO("✓ " + testName + " - PASSED");
- } else {
- failedTests.push_back(testName);
- AV_LOGGER_ERROR("✗ " + testName + " - FAILED");
- }
- }
-
- void printSummary() {
- AV_LOGGER_INFO("\n=== Muxer Test Summary ===");
- AV_LOGGER_INFO("Total tests: " + std::to_string(totalTests));
- AV_LOGGER_INFO("Passed: " + std::to_string(passedTests));
- AV_LOGGER_INFO("Failed: " + std::to_string(failedTests.size()));
-
- if (!failedTests.empty()) {
- AV_LOGGER_ERROR("Failed tests:");
- for (const auto& test : failedTests) {
- AV_LOGGER_ERROR(" - " + test);
- }
- }
-
- double successRate = totalTests > 0 ? (double)passedTests / totalTests * 100.0 : 0.0;
- AV_LOGGER_INFO("Success rate: " + std::to_string(successRate) + "%");
- }
- };
- // 创建测试用的AVPacket
- AVPacket* createTestPacket(int streamIndex, int64_t pts, int64_t dts, int size = 1024) {
- AVPacket* packet = av_packet_alloc();
- if (!packet) return nullptr;
-
- // 分配数据
- if (av_new_packet(packet, size) < 0) {
- av_packet_free(&packet);
- return nullptr;
- }
-
- // 填充测试数据
- memset(packet->data, 0x42, size);
- packet->stream_index = streamIndex;
- packet->pts = pts;
- packet->dts = dts;
- packet->flags = AV_PKT_FLAG_KEY;
-
- return packet;
- }
- // 创建测试用的StreamInfo
- StreamInfo createVideoStreamInfo() {
- StreamInfo info;
- info.index = 0;
- info.type = StreamType::VIDEO;
- info.codecId = AV_CODEC_ID_H264;
- info.codecName = "h264";
- info.width = 1920;
- info.height = 1080;
- info.frameRate = {30, 1};
- info.pixelFormat = AV_PIX_FMT_YUV420P;
- info.bitrate = 2000000;
- info.timeBase = {1, 30};
- return info;
- }
- StreamInfo createAudioStreamInfo() {
- StreamInfo info;
- info.index = 1;
- info.type = StreamType::AUDIO;
- info.codecId = AV_CODEC_ID_AAC;
- info.codecName = "aac";
- info.sampleRate = 44100;
- info.channels = 2;
- info.sampleFormat = AV_SAMPLE_FMT_FLTP;
- info.channelLayout = AV_CH_LAYOUT_STEREO;
- info.bitrate = 128000;
- info.timeBase = {1, 44100};
- return info;
- }
- // 测试抽象复用器基础功能
- bool testAbstractMuxerBasics(TestResults& results) {
- AV_LOGGER_INFO("Testing AbstractMuxer basics...");
-
- // 测试工厂方法
- auto factory = MuxerFactory::createFactory();
- bool factoryTest = factory != nullptr;
- results.addTest("MuxerFactory creation", factoryTest);
-
- if (!factory) return false;
-
- // 测试支持的格式
- auto formats = AbstractMuxer::getSupportedFormats();
- bool formatsTest = !formats.empty();
- results.addTest("Supported formats query", formatsTest);
-
- // 测试格式支持检查
- bool mp4Support = AbstractMuxer::isFormatSupported("mp4");
- bool flvSupport = AbstractMuxer::isFormatSupported("flv");
- results.addTest("Format support check", mp4Support || flvSupport);
-
- // 测试扩展名到格式的转换
- std::string mp4Format = AbstractMuxer::getFormatFromExtension("test.mp4");
- bool extensionTest = !mp4Format.empty();
- results.addTest("Extension to format conversion", extensionTest);
-
- return factoryTest && formatsTest;
- }
- // 测试文件复用器
- bool testFileMuxer(TestResults& results) {
- AV_LOGGER_INFO("Testing FileMuxer...");
-
- try {
- // 创建文件复用器
- auto factory = std::make_unique<FileMuxer::FileMuxerFactory>();
- auto muxer = factory->createMuxer(MuxerType::FILE_MUXER);
- bool creationTest = muxer != nullptr;
- results.addTest("FileMuxer creation", creationTest);
-
- if (!muxer) return false;
-
- auto fileMuxer = dynamic_cast<FileMuxer*>(muxer.get());
- if (!fileMuxer) {
- results.addTest("FileMuxer cast", false);
- return false;
- }
-
- // 设置参数
- FileMuxerParams params;
- params.outputFile = "test_output.mp4";
- params.outputPath = "test_output.mp4"; // 同时设置outputPath
- params.format = "mp4";
- params.overwrite = true;
- params.enableFastStart = true;
-
- // 添加流信息到参数中
- params.streams.push_back(createVideoStreamInfo());
- params.streams.push_back(createAudioStreamInfo());
-
- AV_LOGGER_INFOF("设置参数: outputFile={}, outputPath={}", params.outputFile, params.outputPath);
-
- // 初始化
- ErrorCode initResult = muxer->initialize(params);
- bool initTest = initResult == ErrorCode::SUCCESS;
- results.addTest("FileMuxer initialization", initTest);
-
- if (initResult != ErrorCode::SUCCESS) {
- AV_LOGGER_ERROR("FileMuxer initialization failed: " + muxer->getLastError());
- return false;
- }
-
- // 测试额外添加流(应该失败,因为流索引已存在)
- ErrorCode addVideoStream = muxer->addStream(createVideoStreamInfo());
- ErrorCode addAudioStream = muxer->addStream(createAudioStreamInfo());
- bool streamTest = (addVideoStream == ErrorCode::STREAM_EXISTS) && (addAudioStream == ErrorCode::STREAM_EXISTS); // 期望返回STREAM_EXISTS
- results.addTest("Duplicate stream addition", streamTest);
-
- // 启动
- ErrorCode startResult = muxer->start();
- bool startTest = startResult == ErrorCode::SUCCESS;
- results.addTest("FileMuxer start", startTest);
-
- if (startResult == ErrorCode::SUCCESS) {
- // 测试状态
- bool runningTest = muxer->isRunning();
- results.addTest("FileMuxer running state", runningTest);
-
- // 写入一些测试包
- bool writeTest = true;
- for (int i = 0; i < 10; i++) {
- AVPacket* videoPacket = createTestPacket(0, i * 1000, i * 1000, 1024);
- AVPacket* audioPacket = createTestPacket(1, i * 1000, i * 1000, 512);
-
- if (videoPacket && audioPacket) {
- ErrorCode videoWrite = muxer->writePacket(videoPacket);
- ErrorCode audioWrite = muxer->writePacket(audioPacket);
-
- if (videoWrite != ErrorCode::SUCCESS || audioWrite != ErrorCode::SUCCESS) {
- writeTest = false;
- av_packet_free(&videoPacket);
- av_packet_free(&audioPacket);
- break;
- }
-
- av_packet_free(&videoPacket);
- av_packet_free(&audioPacket);
- } else {
- writeTest = false;
- if (videoPacket) av_packet_free(&videoPacket);
- if (audioPacket) av_packet_free(&audioPacket);
- break;
- }
-
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
- }
- results.addTest("Packet writing", writeTest);
-
- // 刷新
- ErrorCode flushResult = muxer->flush();
- results.addTest("FileMuxer flush", flushResult == ErrorCode::SUCCESS);
-
- // 获取统计信息
- MuxerStats stats = muxer->getStats();
- bool statsTest = stats.totalPackets > 0;
- results.addTest("Statistics collection", statsTest);
-
- // 停止
- ErrorCode stopResult = muxer->stop();
- results.addTest("FileMuxer stop", stopResult == ErrorCode::SUCCESS);
- }
-
- // 关闭
- ErrorCode closeResult = muxer->close();
- results.addTest("FileMuxer close", closeResult == ErrorCode::SUCCESS);
-
- // 检查输出文件是否存在
- bool fileExists = std::filesystem::exists("test_output.mp4");
- results.addTest("Output file creation", fileExists);
-
- // 清理测试文件
- if (fileExists) {
- std::filesystem::remove("test_output.mp4");
- }
-
- return creationTest && initTest;
-
- } catch (const std::exception& e) {
- AV_LOGGER_ERROR("FileMuxer test exception: " + std::string(e.what()));
- results.addTest("FileMuxer exception handling", false);
- return false;
- }
- }
- // 测试流复用器基础功能(不实际连接)
- bool testStreamMuxer(TestResults& results) {
- AV_LOGGER_INFO("Testing StreamMuxer basics...");
-
- try {
- // 创建流复用器
- auto factory = std::make_unique<StreamMuxer::StreamMuxerFactory>();
- auto muxer = factory->createMuxer(MuxerType::STREAM_MUXER);
- bool creationTest = muxer != nullptr;
- results.addTest("StreamMuxer creation", creationTest);
-
- if (!muxer) return false;
-
- auto streamMuxer = dynamic_cast<StreamMuxer*>(muxer.get());
- if (!streamMuxer) {
- results.addTest("StreamMuxer cast", false);
- return false;
- }
-
- // 设置参数(使用有效URL格式,但不实际连接)
- StreamMuxerParams params;
- params.protocol = StreamProtocol::RTMP;
- params.url = "rtmp://localhost/live/test";
- params.format = "flv";
- params.enableAutoReconnect = true;
- params.maxReconnectAttempts = 3;
-
- // 添加流信息到参数中
- params.streams.push_back(createVideoStreamInfo());
- params.streams.push_back(createAudioStreamInfo());
-
- // 初始化(预期会失败,因为URL无效)
- ErrorCode initResult = muxer->initialize(params);
- // 对于无效URL,初始化可能成功但连接会失败
- bool initTest = true; // 只要不崩溃就算成功
- results.addTest("StreamMuxer initialization", initTest);
-
- // 测试URL设置
- ErrorCode urlResult = streamMuxer->setUrl("rtmp://test.example.com/live/stream");
- bool urlTest = urlResult == ErrorCode::SUCCESS;
- results.addTest("URL setting", urlTest);
-
- // 测试协议选项
- ErrorCode optionResult = streamMuxer->setProtocolOption("timeout", "5000");
- bool optionTest = optionResult == ErrorCode::SUCCESS;
- results.addTest("Protocol option setting", optionTest);
-
- // 测试自适应码率设置
- ErrorCode bitrateResult = streamMuxer->enableAdaptiveBitrate(true);
- bool bitrateTest = bitrateResult == ErrorCode::SUCCESS;
- results.addTest("Adaptive bitrate setting", bitrateTest);
-
- // 关闭
- ErrorCode closeResult = muxer->close();
- results.addTest("StreamMuxer close", closeResult == ErrorCode::SUCCESS);
-
- return creationTest && initTest;
-
- } catch (const std::exception& e) {
- AV_LOGGER_ERROR("StreamMuxer test exception: " + std::string(e.what()));
- results.addTest("StreamMuxer exception handling", false);
- return false;
- }
- }
- // 测试复用器工厂
- bool testMuxerFactory(TestResults& results) {
- AV_LOGGER_INFO("Testing MuxerFactory...");
-
- try {
- // 测试文件复用器工厂
- auto fileFactory = std::make_unique<FileMuxer::FileMuxerFactory>();
-
- bool fileTypeSupport = fileFactory->isTypeSupported(MuxerType::FILE_MUXER);
- results.addTest("FileMuxer type support", fileTypeSupport);
-
- auto supportedTypes = fileFactory->getSupportedTypes();
- bool typesTest = !supportedTypes.empty();
- results.addTest("Supported types query", typesTest);
-
- // 测试流复用器工厂
- auto streamFactory = std::make_unique<StreamMuxer::StreamMuxerFactory>();
-
- bool streamTypeSupport = streamFactory->isTypeSupported(MuxerType::STREAM_MUXER);
- results.addTest("StreamMuxer type support", streamTypeSupport);
-
- // 测试便捷创建方法(预期失败,因为没有流信息)
- auto fileMuxer = FileMuxer::FileMuxerFactory::createFileMuxer("test_factory.mp4");
- bool fileMuxerCreation = fileMuxer == nullptr; // 期望失败,因为没有流信息
- results.addTest("FileMuxer convenience creation", fileMuxerCreation);
-
- auto rtmpMuxer = StreamMuxer::StreamMuxerFactory::createRTMPMuxer("rtmp://localhost/live/test");
- bool rtmpMuxerCreation = rtmpMuxer == nullptr; // 期望失败,因为没有流信息
- results.addTest("RTMP muxer convenience creation", rtmpMuxerCreation);
-
- return fileTypeSupport && streamTypeSupport;
-
- } catch (const std::exception& e) {
- AV_LOGGER_ERROR("MuxerFactory test exception: " + std::string(e.what()));
- results.addTest("MuxerFactory exception handling", false);
- return false;
- }
- }
- // 测试错误处理
- bool testErrorHandling(TestResults& results) {
- AV_LOGGER_INFO("Testing error handling...");
-
- try {
- auto factory = std::make_unique<FileMuxer::FileMuxerFactory>();
- auto muxer = factory->createMuxer(MuxerType::FILE_MUXER);
-
- if (!muxer) {
- results.addTest("Error handling setup", false);
- return false;
- }
-
- // 测试无效参数
- FileMuxerParams invalidParams;
- invalidParams.outputFile = ""; // 空文件名
- invalidParams.format = "invalid_format";
-
- ErrorCode result = muxer->initialize(invalidParams);
- bool invalidParamsTest = result != ErrorCode::SUCCESS;
- results.addTest("Invalid parameters handling", invalidParamsTest);
-
- // 测试未初始化状态下的操作
- ErrorCode startResult = muxer->start();
- bool uninitializedTest = startResult != ErrorCode::SUCCESS;
- results.addTest("Uninitialized operation handling", uninitializedTest);
-
- // 测试错误信息获取(先初始化一个有效的复用器来确保有错误信息)
- FileMuxerParams validParams;
- validParams.outputFile = "test_error.mp4";
- muxer->initialize(validParams);
- std::string errorMsg = muxer->getLastError();
- bool errorMsgTest = true; // 只要不崩溃就算成功
- results.addTest("Error message retrieval", errorMsgTest);
-
- return invalidParamsTest && uninitializedTest;
-
- } catch (const std::exception& e) {
- AV_LOGGER_ERROR("Error handling test exception: " + std::string(e.what()));
- results.addTest("Error handling exception", false);
- return false;
- }
- }
- int main() {
- // 初始化日志系统
- Logger::initialize("test_muxer.log", LogLevel::INFO, false, true);
- AV_LOGGER_INFO("=== Starting Muxer Module Tests ===");
-
- TestResults results;
-
- // 运行所有测试
- testAbstractMuxerBasics(results);
- testFileMuxer(results);
- testStreamMuxer(results);
- testMuxerFactory(results);
- testErrorHandling(results);
-
- // 打印测试结果
- results.printSummary();
-
- // 返回测试结果
- bool allTestsPassed = (results.failedTests.empty() && results.totalTests > 0);
-
- if (allTestsPassed) {
- AV_LOGGER_INFO("\n🎉 All muxer tests passed!");
- return 0;
- } else {
- AV_LOGGER_ERROR("\n❌ Some muxer tests failed!");
- return 1;
- }
- }
|