media_common.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. #include "media_common.h"
  2. #include "logger.h"
  3. #include <algorithm>
  4. #include <sstream>
  5. #include <fstream>
  6. #include <filesystem>
  7. #include <cctype>
  8. #include <iomanip>
  9. #include <cstring>
  10. #include <limits>
  11. // FFmpeg头文件
  12. extern "C" {
  13. #include <libavutil/avutil.h>
  14. #include <libavcodec/avcodec.h>
  15. #include <libavformat/avformat.h>
  16. #include <libswscale/swscale.h>
  17. #include <libswresample/swresample.h>
  18. #include <libavutil/log.h>
  19. #include <libavutil/error.h>
  20. #include <libavutil/pixfmt.h>
  21. #include <libavutil/pixdesc.h>
  22. #include <libavutil/samplefmt.h>
  23. #include <libavutil/frame.h>
  24. #include <libavcodec/packet.h>
  25. }
  26. namespace av {
  27. // 字符串工具实现
  28. namespace string_utils {
  29. std::vector<std::string> split(const std::string& str, char delimiter) {
  30. std::vector<std::string> result;
  31. std::stringstream ss(str);
  32. std::string item;
  33. while (std::getline(ss, item, delimiter)) {
  34. result.push_back(item);
  35. }
  36. return result;
  37. }
  38. std::vector<std::string> split(const std::string& str, const std::string& delimiter) {
  39. std::vector<std::string> result;
  40. size_t start = 0;
  41. size_t end = str.find(delimiter);
  42. while (end != std::string::npos) {
  43. result.push_back(str.substr(start, end - start));
  44. start = end + delimiter.length();
  45. end = str.find(delimiter, start);
  46. }
  47. result.push_back(str.substr(start));
  48. return result;
  49. }
  50. std::string trim(const std::string& str) {
  51. return trimLeft(trimRight(str));
  52. }
  53. std::string trimLeft(const std::string& str) {
  54. auto start = str.begin();
  55. while (start != str.end() && std::isspace(*start)) {
  56. start++;
  57. }
  58. return std::string(start, str.end());
  59. }
  60. std::string trimRight(const std::string& str) {
  61. auto end = str.end();
  62. while (end != str.begin() && std::isspace(*(end - 1))) {
  63. end--;
  64. }
  65. return std::string(str.begin(), end);
  66. }
  67. std::string replace(const std::string& str, const std::string& from, const std::string& to) {
  68. std::string result = str;
  69. size_t pos = 0;
  70. while ((pos = result.find(from, pos)) != std::string::npos) {
  71. result.replace(pos, from.length(), to);
  72. pos += to.length();
  73. }
  74. return result;
  75. }
  76. std::string toLower(const std::string& str) {
  77. std::string result = str;
  78. std::transform(result.begin(), result.end(), result.begin(), ::tolower);
  79. return result;
  80. }
  81. std::string toUpper(const std::string& str) {
  82. std::string result = str;
  83. std::transform(result.begin(), result.end(), result.begin(), ::toupper);
  84. return result;
  85. }
  86. bool startsWith(const std::string& str, const std::string& prefix) {
  87. return str.length() >= prefix.length() &&
  88. str.compare(0, prefix.length(), prefix) == 0;
  89. }
  90. bool endsWith(const std::string& str, const std::string& suffix) {
  91. return str.length() >= suffix.length() &&
  92. str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0;
  93. }
  94. bool contains(const std::string& str, const std::string& substr) {
  95. return str.find(substr) != std::string::npos;
  96. }
  97. } // namespace string_utils
  98. // 文件路径工具实现
  99. namespace path_utils {
  100. std::string join(const std::string& path1, const std::string& path2) {
  101. if (path1.empty()) return path2;
  102. if (path2.empty()) return path1;
  103. std::filesystem::path p1(path1);
  104. std::filesystem::path p2(path2);
  105. return (p1 / p2).string();
  106. }
  107. std::string getDirectory(const std::string& path) {
  108. std::filesystem::path p(path);
  109. return p.parent_path().string();
  110. }
  111. std::string getFilename(const std::string& path) {
  112. std::filesystem::path p(path);
  113. return p.filename().string();
  114. }
  115. std::string getExtension(const std::string& path) {
  116. std::filesystem::path p(path);
  117. return p.extension().string();
  118. }
  119. std::string removeExtension(const std::string& path) {
  120. std::filesystem::path p(path);
  121. return p.replace_extension().string();
  122. }
  123. std::string normalize(const std::string& path) {
  124. std::filesystem::path p(path);
  125. return std::filesystem::weakly_canonical(p).string();
  126. }
  127. std::string toNative(const std::string& path) {
  128. std::filesystem::path p(path);
  129. return p.make_preferred().string();
  130. }
  131. bool exists(const std::string& path) {
  132. return std::filesystem::exists(path);
  133. }
  134. bool isFile(const std::string& path) {
  135. return std::filesystem::is_regular_file(path);
  136. }
  137. bool isDirectory(const std::string& path) {
  138. return std::filesystem::is_directory(path);
  139. }
  140. bool isAbsolute(const std::string& path) {
  141. std::filesystem::path p(path);
  142. return p.is_absolute();
  143. }
  144. bool createDirectory(const std::string& path) {
  145. try {
  146. return std::filesystem::create_directories(path);
  147. } catch (const std::exception& e) {
  148. AV_LOGGER_ERRORF("Failed to create directory '{}': {}", path, e.what());
  149. return false;
  150. }
  151. }
  152. bool removeFile(const std::string& path) {
  153. try {
  154. return std::filesystem::remove(path);
  155. } catch (const std::exception& e) {
  156. AV_LOGGER_ERRORF("Failed to remove file '{}': {}", path, e.what());
  157. return false;
  158. }
  159. }
  160. } // namespace path_utils
  161. // 时间工具实现
  162. namespace time_utils {
  163. int64_t getCurrentTimeMs() {
  164. return std::chrono::duration_cast<std::chrono::milliseconds>(
  165. std::chrono::steady_clock::now().time_since_epoch()).count();
  166. }
  167. int64_t getCurrentTimeUs() {
  168. return std::chrono::duration_cast<std::chrono::microseconds>(
  169. std::chrono::steady_clock::now().time_since_epoch()).count();
  170. }
  171. std::string formatTime(int64_t timeMs, const std::string& format) {
  172. auto time_t = std::chrono::system_clock::to_time_t(
  173. std::chrono::system_clock::time_point(
  174. std::chrono::milliseconds(timeMs)));
  175. std::ostringstream oss;
  176. oss << std::put_time(std::localtime(&time_t), format.c_str());
  177. return oss.str();
  178. }
  179. std::string formatDuration(int64_t durationMs) {
  180. int64_t hours = durationMs / (1000 * 60 * 60);
  181. int64_t minutes = (durationMs % (1000 * 60 * 60)) / (1000 * 60);
  182. int64_t seconds = (durationMs % (1000 * 60)) / 1000;
  183. int64_t ms = durationMs % 1000;
  184. std::ostringstream oss;
  185. if (hours > 0) {
  186. oss << hours << ":" << std::setfill('0') << std::setw(2) << minutes
  187. << ":" << std::setw(2) << seconds;
  188. } else {
  189. oss << minutes << ":" << std::setfill('0') << std::setw(2) << seconds;
  190. }
  191. if (ms > 0) {
  192. oss << "." << std::setw(3) << ms;
  193. }
  194. return oss.str();
  195. }
  196. // Timer实现
  197. Timer::Timer() {
  198. reset();
  199. }
  200. void Timer::start() {
  201. m_startTime = std::chrono::high_resolution_clock::now();
  202. m_running = true;
  203. }
  204. void Timer::stop() {
  205. if (m_running) {
  206. m_endTime = std::chrono::high_resolution_clock::now();
  207. m_running = false;
  208. }
  209. }
  210. void Timer::reset() {
  211. m_startTime = std::chrono::high_resolution_clock::now();
  212. m_endTime = m_startTime;
  213. m_running = false;
  214. }
  215. int64_t Timer::elapsedMs() const {
  216. auto endTime = m_running ? std::chrono::high_resolution_clock::now() : m_endTime;
  217. return std::chrono::duration_cast<std::chrono::milliseconds>(endTime - m_startTime).count();
  218. }
  219. int64_t Timer::elapsedUs() const {
  220. auto endTime = m_running ? std::chrono::high_resolution_clock::now() : m_endTime;
  221. return std::chrono::duration_cast<std::chrono::microseconds>(endTime - m_startTime).count();
  222. }
  223. bool Timer::isRunning() const {
  224. return m_running;
  225. }
  226. // ScopedTimer实现
  227. ScopedTimer::ScopedTimer(const std::string& name) : m_name(name) {
  228. m_timer.start();
  229. }
  230. ScopedTimer::~ScopedTimer() {
  231. m_timer.stop();
  232. AV_LOGGER_INFOF("[Timer] {} took {} ms", m_name, m_timer.elapsedMs());
  233. }
  234. } // namespace time_utils
  235. // 内存工具实现
  236. namespace memory_utils {
  237. size_t alignSize(size_t size, size_t alignment) {
  238. return (size + alignment - 1) & ~(alignment - 1);
  239. }
  240. void* alignedAlloc(size_t size, size_t alignment) {
  241. #ifdef _WIN32
  242. return _aligned_malloc(size, alignment);
  243. #else
  244. void* ptr = nullptr;
  245. if (posix_memalign(&ptr, alignment, size) != 0) {
  246. return nullptr;
  247. }
  248. return ptr;
  249. #endif
  250. }
  251. void alignedFree(void* ptr) {
  252. #ifdef _WIN32
  253. _aligned_free(ptr);
  254. #else
  255. free(ptr);
  256. #endif
  257. }
  258. // MemoryPool实现
  259. MemoryPool::MemoryPool(size_t blockSize, size_t blockCount)
  260. : m_blockSize(blockSize) {
  261. size_t totalSize = blockSize * blockCount;
  262. m_memory.resize(totalSize);
  263. // 初始化空闲块列表
  264. for (size_t i = 0; i < blockCount; ++i) {
  265. m_freeBlocks.push_back(m_memory.data() + i * blockSize);
  266. }
  267. }
  268. MemoryPool::~MemoryPool() {
  269. // 析构函数自动清理
  270. }
  271. void* MemoryPool::allocate() {
  272. std::lock_guard<std::mutex> lock(m_mutex);
  273. if (m_freeBlocks.empty()) {
  274. return nullptr;
  275. }
  276. void* ptr = m_freeBlocks.back();
  277. m_freeBlocks.pop_back();
  278. return ptr;
  279. }
  280. void MemoryPool::deallocate(void* ptr) {
  281. if (!ptr) return;
  282. std::lock_guard<std::mutex> lock(m_mutex);
  283. // 验证指针是否属于这个内存池
  284. uint8_t* bytePtr = static_cast<uint8_t*>(ptr);
  285. if (bytePtr >= m_memory.data() &&
  286. bytePtr < m_memory.data() + m_memory.size()) {
  287. m_freeBlocks.push_back(ptr);
  288. }
  289. }
  290. size_t MemoryPool::getAvailableBlocks() const {
  291. std::lock_guard<std::mutex> lock(m_mutex);
  292. return m_freeBlocks.size();
  293. }
  294. } // namespace memory_utils
  295. // FFmpeg工具实现
  296. namespace ffmpeg_utils {
  297. std::string errorToString(int errorCode) {
  298. char buffer[AV_ERROR_MAX_STRING_SIZE];
  299. av_strerror(errorCode, buffer, sizeof(buffer));
  300. return std::string(buffer);
  301. }
  302. bool checkError(int ret, const std::string& operation) {
  303. if (ret < 0) {
  304. AV_LOGGER_ERRORF("{} failed: {}", operation, errorToString(ret));
  305. return false;
  306. }
  307. return true;
  308. }
  309. std::string pixelFormatToString(AVPixelFormat format) {
  310. const char* name = av_get_pix_fmt_name(format);
  311. return name ? std::string(name) : "unknown";
  312. }
  313. std::string sampleFormatToString(AVSampleFormat format) {
  314. const char* name = av_get_sample_fmt_name(format);
  315. return name ? std::string(name) : "unknown";
  316. }
  317. std::string codecTypeToString(AVMediaType type) {
  318. const char* name = av_get_media_type_string(type);
  319. return name ? std::string(name) : "unknown";
  320. }
  321. bool isValidPixelFormat(AVPixelFormat format) {
  322. return format != AV_PIX_FMT_NONE && av_get_pix_fmt_name(format) != nullptr;
  323. }
  324. bool isValidSampleFormat(AVSampleFormat format) {
  325. return format != AV_SAMPLE_FMT_NONE && av_get_sample_fmt_name(format) != nullptr;
  326. }
  327. bool isValidSampleRate(int sampleRate) {
  328. return sampleRate > 0 && sampleRate <= 192000;
  329. }
  330. bool isValidChannels(int channels) {
  331. return channels > 0 && channels <= 32;
  332. }
  333. // 统一使用智能指针的帧分配函数
  334. AVFramePtr allocateFrame(AVPixelFormat format, int width, int height) {
  335. AVFramePtr frame = makeAVFrame();
  336. if (!frame) {
  337. return nullptr;
  338. }
  339. frame->format = format;
  340. frame->width = width;
  341. frame->height = height;
  342. if (av_frame_get_buffer(frame.get(), 32) < 0) {
  343. return nullptr; // 智能指针自动释放
  344. }
  345. return frame;
  346. }
  347. AVFramePtr allocateAudioFrame(AVSampleFormat format, int sampleRate, int channels, int nbSamples) {
  348. AVFramePtr frame = makeAVFrame();
  349. if (!frame) {
  350. return nullptr;
  351. }
  352. frame->format = format;
  353. frame->sample_rate = sampleRate;
  354. frame->ch_layout.nb_channels = channels;
  355. frame->nb_samples = nbSamples;
  356. if (av_frame_get_buffer(frame.get(), 0) < 0) {
  357. return nullptr; // 智能指针自动释放
  358. }
  359. return frame;
  360. }
  361. void freeFrame(AVFrame** frame) {
  362. if (frame && *frame) {
  363. av_frame_free(frame);
  364. }
  365. }
  366. AVPacket* allocatePacket() {
  367. return av_packet_alloc();
  368. }
  369. void freePacket(AVPacket** packet) {
  370. if (packet && *packet) {
  371. av_packet_free(packet);
  372. }
  373. }
  374. bool initializeFFmpeg() {
  375. static bool initialized = false;
  376. if (initialized) {
  377. return true;
  378. }
  379. try {
  380. // FFmpeg 4.0+ 不需要显式注册
  381. av_log_set_level(AV_LOG_QUIET);
  382. initialized = true;
  383. AV_LOGGER_INFO("FFmpeg initialized successfully");
  384. return true;
  385. } catch (const std::exception& e) {
  386. AV_LOGGER_ERRORF("Failed to initialize FFmpeg: {}", e.what());
  387. return false;
  388. }
  389. }
  390. void cleanupFFmpeg() {
  391. // FFmpeg 4.0+ 不需要显式清理
  392. AV_LOGGER_INFO("FFmpeg cleanup completed");
  393. }
  394. } // namespace ffmpeg_utils
  395. } // namespace av