#ifndef DECODEPARAM_H #define DECODEPARAM_H extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/imgutils.h" } #include #include #include #include using namespace std::literals::chrono_literals; template requires std::is_same_v || std::is_same_v struct MediaQueue { static constexpr int MAX_SIZE = 30; 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()) { if constexpr (std::is_same_v) { AVPacket* temp = queue.front(); if (av_packet_ref(item, temp) < 0) { return false; } av_packet_unref(temp); } else if (std::is_same_v) { AVFrame* temp = queue.front(); if (av_frame_ref(item, temp) < 0) { return false; } av_frame_free(&temp); delete temp; } queue.pop(); count--; full = false; return true; } else if (block) { cv.wait(lock); } else { return false; } } return false; } struct VideoParam { MediaQueue packetQueue; MediaQueue frameQueue; AVCodecContext* codecCtx; int width; int height; int videoStreamIndex; AVStream* stream; bool eof = false; bool pause = false; bool quit = false; double totalTime = 0; double currentTime = 0; }; struct AudioParam { MediaQueue packetQueue; AVCodecContext* codecCtx; AVStream* stream; int audioStreamIndex; static constexpr int MAX_BUFFER_SIZE = 192000; uint8_t* buffer = new uint8_t[MAX_BUFFER_SIZE]; uint32_t bufferSize = 0; uint32_t bufferIndex = 0; bool eof = false; bool pause = false; bool isVideo = false; bool quit = false; double currentTime = 0; double totalTime = 0; double lastPts; double getCurrentTime() const { const int diff = bufferSize - bufferIndex; const int bytePreSec = codecCtx->sample_rate * codecCtx->ch_layout.nb_channels * 2; return currentTime - static_cast(diff) / bytePreSec; } }; struct MediaParam { VideoParam videoParam; AudioParam audioParam; AVFormatContext* fmtCtx; }; #endif