2024-02-22 20:36:02 +08:00
|
|
|
#ifndef DECODEPARAM_H
|
|
|
|
#define DECODEPARAM_H
|
2024-02-23 16:24:42 +08:00
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
#include "libavcodec/avcodec.h"
|
|
|
|
#include "libavformat/avformat.h"
|
|
|
|
#include "libavutil/imgutils.h"
|
|
|
|
}
|
|
|
|
#include <queue>
|
|
|
|
#include <condition_variable>
|
|
|
|
#include <mutex>
|
|
|
|
#include <chrono>
|
|
|
|
using namespace std::literals::chrono_literals;
|
|
|
|
|
2024-02-21 21:20:14 +08:00
|
|
|
template<typename T>
|
|
|
|
requires std::is_same_v<T, AVPacket> || std::is_same_v<T, AVFrame>
|
2024-02-22 11:45:01 +08:00
|
|
|
struct MediaQueue
|
2024-02-21 21:20:14 +08:00
|
|
|
{
|
2024-02-22 11:45:01 +08:00
|
|
|
static constexpr int MAX_SIZE = 30;
|
2024-02-21 22:34:00 +08:00
|
|
|
bool full = false;
|
2024-02-22 11:45:01 +08:00
|
|
|
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;
|
2024-02-21 22:34:00 +08:00
|
|
|
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;
|
2024-02-21 22:34:00 +08:00
|
|
|
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;
|
2024-02-22 11:45:01 +08:00
|
|
|
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);
|
2024-02-22 11:45:01 +08:00
|
|
|
queue.push(temp);
|
2024-02-21 22:34:00 +08:00
|
|
|
}
|
|
|
|
count++;
|
2024-02-22 11:45:01 +08:00
|
|
|
if (count >= MAX_SIZE) {
|
2024-02-21 22:34:00 +08:00
|
|
|
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>) {
|
2024-02-22 11:45:01 +08:00
|
|
|
AVPacket* temp = queue.front();
|
|
|
|
if (av_packet_ref(item, temp) < 0) {
|
2024-02-21 21:20:14 +08:00
|
|
|
return false;
|
|
|
|
}
|
2024-02-22 11:45:01 +08:00
|
|
|
av_packet_unref(temp);
|
2024-02-21 21:20:14 +08:00
|
|
|
}
|
|
|
|
else if (std::is_same_v<T, AVFrame>) {
|
2024-02-22 11:45:01 +08:00
|
|
|
AVFrame* temp = queue.front();
|
|
|
|
if (av_frame_ref(item, temp) < 0) {
|
2024-02-21 21:20:14 +08:00
|
|
|
return false;
|
|
|
|
}
|
2024-02-23 10:32:08 +08:00
|
|
|
av_frame_free(&temp);
|
|
|
|
delete temp;
|
2024-02-21 21:20:14 +08:00
|
|
|
}
|
|
|
|
queue.pop();
|
|
|
|
count--;
|
2024-02-21 22:34:00 +08:00
|
|
|
full = false;
|
2024-02-22 11:45:01 +08:00
|
|
|
return true;
|
2024-02-21 21:20:14 +08:00
|
|
|
}
|
|
|
|
else if (block) {
|
|
|
|
cv.wait(lock);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-02-21 22:34:00 +08:00
|
|
|
struct VideoParam
|
|
|
|
{
|
2024-02-22 11:45:01 +08:00
|
|
|
MediaQueue<AVPacket> packetQueue;
|
|
|
|
MediaQueue<AVFrame> frameQueue;
|
2024-02-21 22:34:00 +08:00
|
|
|
AVCodecContext* codecCtx;
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
int videoStreamIndex;
|
2024-02-27 14:26:22 +08:00
|
|
|
AVStream* stream;
|
2024-02-21 22:34:00 +08:00
|
|
|
bool eof = false;
|
|
|
|
bool pause = false;
|
|
|
|
bool quit = false;
|
2024-02-27 14:26:22 +08:00
|
|
|
double totalTime = 0;
|
|
|
|
double currentTime = 0;
|
2024-02-21 22:34:00 +08:00
|
|
|
};
|
2024-02-21 21:20:14 +08:00
|
|
|
|
2024-02-22 20:36:02 +08:00
|
|
|
struct AudioParam
|
|
|
|
{
|
|
|
|
MediaQueue<AVPacket> packetQueue;
|
|
|
|
AVCodecContext* codecCtx;
|
2024-02-27 14:26:22 +08:00
|
|
|
AVStream* stream;
|
2024-02-22 20:36:02 +08:00
|
|
|
int audioStreamIndex;
|
2024-02-23 16:24:42 +08:00
|
|
|
static constexpr int MAX_BUFFER_SIZE = 192000;
|
|
|
|
uint8_t* buffer = new uint8_t[MAX_BUFFER_SIZE];
|
|
|
|
uint32_t bufferSize = 0;
|
|
|
|
uint32_t bufferIndex = 0;
|
2024-02-22 20:36:02 +08:00
|
|
|
bool eof = false;
|
|
|
|
bool pause = false;
|
2024-02-26 17:42:56 +08:00
|
|
|
bool isVideo = false;
|
2024-02-22 20:36:02 +08:00
|
|
|
bool quit = false;
|
2024-02-27 14:26:22 +08:00
|
|
|
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<double>(diff) / bytePreSec;
|
|
|
|
}
|
2024-02-22 20:36:02 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct MediaParam
|
|
|
|
{
|
|
|
|
VideoParam videoParam;
|
|
|
|
AudioParam audioParam;
|
2024-02-23 16:24:42 +08:00
|
|
|
AVFormatContext* fmtCtx;
|
2024-02-22 20:36:02 +08:00
|
|
|
};
|
2024-02-20 11:16:08 +08:00
|
|
|
#endif
|