#ifndef DECODER_H #define DECODER_H extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/imgutils.h" } #include #include #include #include struct VideoParam { AVFormatContext* fmtCtx; AVCodecContext* codecCtx; int width; int height; int videoStreamIndex; }; template requires std::is_same_v || std::is_same_v struct MediaQueue { std::queue queue; std::condition_variable cv; std::mutex mut; uint32_t size; uint32_t count; MediaQueue() = default; bool push(const T* item); bool pop(T* item, bool block = false, bool quit = false); }; template requires std::is_same_v || std::is_same_v bool MediaQueue::push(const T* item) { if (item == nullptr) return false; std::unique_lock lock(mut); if constexpr (std::is_same_v) { auto temp = av_packet_alloc(); av_packet_ref(temp, item); queue.push(*temp); size += temp->size; count++; }else if(std::is_same_v) { auto temp = av_frame_alloc(); av_frame_ref(temp, item); queue.push(*temp); count++; } cv.notify_all(); return true; } template requires std::is_same_v || std::is_same_v bool MediaQueue::pop(T* item, bool block, bool quit) { std::unique_lock lock(mut); while (!quit) { if (!queue.empty()) { T temp = queue.front(); if constexpr (std::is_same_v) { if (av_packet_ref(item, &temp) < 0) { return false; } av_packet_unref(&temp); } else if (std::is_same_v) { if (av_frame_ref(item, &temp) < 0) { return false; } av_frame_unref(&temp); } queue.pop(); count--; return true; } else if (block) { cv.wait(lock); } else { return false; } } return false; } void InitDecoder(const char* filepath, VideoParam& param); AVFrame* RequestFrame(VideoParam& param); #endif