#include "media_common.h" #include "logger.h" #include #include #include #include #include #include #include #include // FFmpeg头文件 extern "C" { #include #include #include #include #include #include #include #include #include #include #include #include } namespace av { // 字符串工具实现 namespace string_utils { std::vector split(const std::string& str, char delimiter) { std::vector result; std::stringstream ss(str); std::string item; while (std::getline(ss, item, delimiter)) { result.push_back(item); } return result; } std::vector split(const std::string& str, const std::string& delimiter) { std::vector result; size_t start = 0; size_t end = str.find(delimiter); while (end != std::string::npos) { result.push_back(str.substr(start, end - start)); start = end + delimiter.length(); end = str.find(delimiter, start); } result.push_back(str.substr(start)); return result; } std::string trim(const std::string& str) { return trimLeft(trimRight(str)); } std::string trimLeft(const std::string& str) { auto start = str.begin(); while (start != str.end() && std::isspace(*start)) { start++; } return std::string(start, str.end()); } std::string trimRight(const std::string& str) { auto end = str.end(); while (end != str.begin() && std::isspace(*(end - 1))) { end--; } return std::string(str.begin(), end); } std::string replace(const std::string& str, const std::string& from, const std::string& to) { std::string result = str; size_t pos = 0; while ((pos = result.find(from, pos)) != std::string::npos) { result.replace(pos, from.length(), to); pos += to.length(); } return result; } std::string toLower(const std::string& str) { std::string result = str; std::transform(result.begin(), result.end(), result.begin(), ::tolower); return result; } std::string toUpper(const std::string& str) { std::string result = str; std::transform(result.begin(), result.end(), result.begin(), ::toupper); return result; } bool startsWith(const std::string& str, const std::string& prefix) { return str.length() >= prefix.length() && str.compare(0, prefix.length(), prefix) == 0; } bool endsWith(const std::string& str, const std::string& suffix) { return str.length() >= suffix.length() && str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0; } bool contains(const std::string& str, const std::string& substr) { return str.find(substr) != std::string::npos; } } // namespace string_utils // 文件路径工具实现 namespace path_utils { std::string join(const std::string& path1, const std::string& path2) { if (path1.empty()) return path2; if (path2.empty()) return path1; std::filesystem::path p1(path1); std::filesystem::path p2(path2); return (p1 / p2).string(); } std::string getDirectory(const std::string& path) { std::filesystem::path p(path); return p.parent_path().string(); } std::string getFilename(const std::string& path) { std::filesystem::path p(path); return p.filename().string(); } std::string getExtension(const std::string& path) { std::filesystem::path p(path); return p.extension().string(); } std::string removeExtension(const std::string& path) { std::filesystem::path p(path); return p.replace_extension().string(); } std::string normalize(const std::string& path) { std::filesystem::path p(path); return std::filesystem::weakly_canonical(p).string(); } std::string toNative(const std::string& path) { std::filesystem::path p(path); return p.make_preferred().string(); } bool exists(const std::string& path) { return std::filesystem::exists(path); } bool isFile(const std::string& path) { return std::filesystem::is_regular_file(path); } bool isDirectory(const std::string& path) { return std::filesystem::is_directory(path); } bool isAbsolute(const std::string& path) { std::filesystem::path p(path); return p.is_absolute(); } bool createDirectory(const std::string& path) { try { return std::filesystem::create_directories(path); } catch (const std::exception& e) { AV_LOGGER_ERRORF("Failed to create directory '{}': {}", path, e.what()); return false; } } bool removeFile(const std::string& path) { try { return std::filesystem::remove(path); } catch (const std::exception& e) { AV_LOGGER_ERRORF("Failed to remove file '{}': {}", path, e.what()); return false; } } } // namespace path_utils // 时间工具实现 namespace time_utils { int64_t getCurrentTimeMs() { return std::chrono::duration_cast( std::chrono::steady_clock::now().time_since_epoch()).count(); } int64_t getCurrentTimeUs() { return std::chrono::duration_cast( std::chrono::steady_clock::now().time_since_epoch()).count(); } std::string formatTime(int64_t timeMs, const std::string& format) { auto time_t = std::chrono::system_clock::to_time_t( std::chrono::system_clock::time_point( std::chrono::milliseconds(timeMs))); std::ostringstream oss; oss << std::put_time(std::localtime(&time_t), format.c_str()); return oss.str(); } std::string formatDuration(int64_t durationMs) { int64_t hours = durationMs / (1000 * 60 * 60); int64_t minutes = (durationMs % (1000 * 60 * 60)) / (1000 * 60); int64_t seconds = (durationMs % (1000 * 60)) / 1000; int64_t ms = durationMs % 1000; std::ostringstream oss; if (hours > 0) { oss << hours << ":" << std::setfill('0') << std::setw(2) << minutes << ":" << std::setw(2) << seconds; } else { oss << minutes << ":" << std::setfill('0') << std::setw(2) << seconds; } if (ms > 0) { oss << "." << std::setw(3) << ms; } return oss.str(); } // Timer实现 Timer::Timer() { reset(); } void Timer::start() { m_startTime = std::chrono::high_resolution_clock::now(); m_running = true; } void Timer::stop() { if (m_running) { m_endTime = std::chrono::high_resolution_clock::now(); m_running = false; } } void Timer::reset() { m_startTime = std::chrono::high_resolution_clock::now(); m_endTime = m_startTime; m_running = false; } int64_t Timer::elapsedMs() const { auto endTime = m_running ? std::chrono::high_resolution_clock::now() : m_endTime; return std::chrono::duration_cast(endTime - m_startTime).count(); } int64_t Timer::elapsedUs() const { auto endTime = m_running ? std::chrono::high_resolution_clock::now() : m_endTime; return std::chrono::duration_cast(endTime - m_startTime).count(); } bool Timer::isRunning() const { return m_running; } // ScopedTimer实现 ScopedTimer::ScopedTimer(const std::string& name) : m_name(name) { m_timer.start(); } ScopedTimer::~ScopedTimer() { m_timer.stop(); AV_LOGGER_INFOF("[Timer] {} took {} ms", m_name, m_timer.elapsedMs()); } } // namespace time_utils // 内存工具实现 namespace memory_utils { size_t alignSize(size_t size, size_t alignment) { return (size + alignment - 1) & ~(alignment - 1); } void* alignedAlloc(size_t size, size_t alignment) { #ifdef _WIN32 return _aligned_malloc(size, alignment); #else void* ptr = nullptr; if (posix_memalign(&ptr, alignment, size) != 0) { return nullptr; } return ptr; #endif } void alignedFree(void* ptr) { #ifdef _WIN32 _aligned_free(ptr); #else free(ptr); #endif } // MemoryPool实现 MemoryPool::MemoryPool(size_t blockSize, size_t blockCount) : m_blockSize(blockSize) { size_t totalSize = blockSize * blockCount; m_memory.resize(totalSize); // 初始化空闲块列表 for (size_t i = 0; i < blockCount; ++i) { m_freeBlocks.push_back(m_memory.data() + i * blockSize); } } MemoryPool::~MemoryPool() { // 析构函数自动清理 } void* MemoryPool::allocate() { std::lock_guard lock(m_mutex); if (m_freeBlocks.empty()) { return nullptr; } void* ptr = m_freeBlocks.back(); m_freeBlocks.pop_back(); return ptr; } void MemoryPool::deallocate(void* ptr) { if (!ptr) return; std::lock_guard lock(m_mutex); // 验证指针是否属于这个内存池 uint8_t* bytePtr = static_cast(ptr); if (bytePtr >= m_memory.data() && bytePtr < m_memory.data() + m_memory.size()) { m_freeBlocks.push_back(ptr); } } size_t MemoryPool::getAvailableBlocks() const { std::lock_guard lock(m_mutex); return m_freeBlocks.size(); } } // namespace memory_utils // FFmpeg工具实现 namespace ffmpeg_utils { std::string errorToString(int errorCode) { char buffer[AV_ERROR_MAX_STRING_SIZE]; av_strerror(errorCode, buffer, sizeof(buffer)); return std::string(buffer); } bool checkError(int ret, const std::string& operation) { if (ret < 0) { AV_LOGGER_ERRORF("{} failed: {}", operation, errorToString(ret)); return false; } return true; } std::string pixelFormatToString(AVPixelFormat format) { const char* name = av_get_pix_fmt_name(format); return name ? std::string(name) : "unknown"; } std::string sampleFormatToString(AVSampleFormat format) { const char* name = av_get_sample_fmt_name(format); return name ? std::string(name) : "unknown"; } std::string codecTypeToString(AVMediaType type) { const char* name = av_get_media_type_string(type); return name ? std::string(name) : "unknown"; } bool isValidPixelFormat(AVPixelFormat format) { return format != AV_PIX_FMT_NONE && av_get_pix_fmt_name(format) != nullptr; } bool isValidSampleFormat(AVSampleFormat format) { return format != AV_SAMPLE_FMT_NONE && av_get_sample_fmt_name(format) != nullptr; } bool isValidSampleRate(int sampleRate) { return sampleRate > 0 && sampleRate <= 192000; } bool isValidChannels(int channels) { return channels > 0 && channels <= 32; } // 统一使用智能指针的帧分配函数 AVFramePtr allocateFrame(AVPixelFormat format, int width, int height) { AVFramePtr frame = makeAVFrame(); if (!frame) { return nullptr; } frame->format = format; frame->width = width; frame->height = height; if (av_frame_get_buffer(frame.get(), 32) < 0) { return nullptr; // 智能指针自动释放 } return frame; } AVFramePtr allocateAudioFrame(AVSampleFormat format, int sampleRate, int channels, int nbSamples) { AVFramePtr frame = makeAVFrame(); if (!frame) { return nullptr; } frame->format = format; frame->sample_rate = sampleRate; frame->ch_layout.nb_channels = channels; frame->nb_samples = nbSamples; if (av_frame_get_buffer(frame.get(), 0) < 0) { return nullptr; // 智能指针自动释放 } return frame; } void freeFrame(AVFrame** frame) { if (frame && *frame) { av_frame_free(frame); } } AVPacket* allocatePacket() { return av_packet_alloc(); } void freePacket(AVPacket** packet) { if (packet && *packet) { av_packet_free(packet); } } bool initializeFFmpeg() { static bool initialized = false; if (initialized) { return true; } try { // FFmpeg 4.0+ 不需要显式注册 av_log_set_level(AV_LOG_QUIET); initialized = true; AV_LOGGER_INFO("FFmpeg initialized successfully"); return true; } catch (const std::exception& e) { AV_LOGGER_ERRORF("Failed to initialize FFmpeg: {}", e.what()); return false; } } void cleanupFFmpeg() { // FFmpeg 4.0+ 不需要显式清理 AV_LOGGER_INFO("FFmpeg cleanup completed"); } } // namespace ffmpeg_utils } // namespace av