mp/include/decoder.h

109 lines
2.3 KiB
C
Raw Normal View History

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