#ifndef DECODER_H #define DECODER_H extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/imgutils.h" } #include #include #include template requires std::is_same_v || std::is_same_v struct MediaQueue { static constexpr int MAX_SIZE = 500; bool full = false; std::queue queue; std::condition_variable cv; std::mutex mut; uint32_t size; uint32_t count; MediaQueue() = default; bool isFill() const { return full; } 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; if (count >= MAX_SIZE) return false; std::unique_lock lock(mut); if constexpr (std::is_same_v) { auto temp = av_packet_alloc(); av_packet_ref(temp, item); size += temp->size; queue.push(*temp); }else if(std::is_same_v) { auto temp = av_frame_alloc(); av_frame_ref(temp, item); queue.push(*temp); } count++; if(count >= MAX_SIZE) { full = true; } 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--; full = false; return true; } else if (block) { cv.wait(lock); } else { return false; } } return false; } struct VideoParam { MediaQueue queue; AVFormatContext* fmtCtx; AVCodecContext* codecCtx; int width; int height; int videoStreamIndex; bool eof = false; bool pause = false; bool quit = false; }; void InitDecoder(const char* filepath, VideoParam& param); void RequestPacket(VideoParam& param); AVFrame* RequestFrame(VideoParam& param); #endif