多线程解码视频帧, 添加todo.txt

This commit is contained in:
JIe Jie 2024-02-22 11:45:01 +08:00
parent 659ca4772d
commit 2641cb0bb3
3 changed files with 56 additions and 49 deletions

View File

@ -13,9 +13,9 @@ template<typename T>
requires std::is_same_v<T, AVPacket> || std::is_same_v<T, AVFrame>
struct MediaQueue
{
static constexpr int MAX_SIZE = 500;
static constexpr int MAX_SIZE = 30;
bool full = false;
std::queue<T> queue;
std::queue<T*> queue;
std::condition_variable cv;
std::mutex mut;
@ -38,14 +38,15 @@ bool MediaQueue<T>::push(const T* item) {
auto temp = av_packet_alloc();
av_packet_ref(temp, item);
size += temp->size;
queue.push(*temp);
}else if(std::is_same_v<T, AVFrame>) {
queue.push(temp);
}
else if (std::is_same_v<T, AVFrame>) {
auto temp = av_frame_alloc();
av_frame_ref(temp, item);
queue.push(*temp);
queue.push(temp);
}
count++;
if(count >= MAX_SIZE) {
if (count >= MAX_SIZE) {
full = true;
}
cv.notify_all();
@ -57,18 +58,19 @@ bool MediaQueue<T>::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<T, AVPacket>) {
if (av_packet_ref(item, &temp) < 0) {
AVPacket* temp = queue.front();
if (av_packet_ref(item, temp) < 0) {
return false;
}
av_packet_unref(&temp);
av_packet_unref(temp);
}
else if (std::is_same_v<T, AVFrame>) {
if (av_frame_ref(item, &temp) < 0) {
AVFrame* temp = queue.front();
if (av_frame_ref(item, temp) < 0) {
return false;
}
av_frame_unref(&temp);
av_frame_unref(temp);
}
queue.pop();
count--;
@ -85,11 +87,10 @@ bool MediaQueue<T>::pop(T* item, bool block, bool quit) {
return false;
}
struct VideoParam
{
MediaQueue<AVPacket> queue;
MediaQueue<AVPacket> packetQueue;
MediaQueue<AVFrame> frameQueue;
AVFormatContext* fmtCtx;
AVCodecContext* codecCtx;
int width;
@ -97,11 +98,12 @@ struct VideoParam
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);
void RequestFrame(VideoParam& param);
#endif

View File

@ -33,7 +33,7 @@ void RequestPacket(VideoParam& param) {
AVPacket* packet = av_packet_alloc();
while (true) {
if(param.queue.isFill()) {
if (param.packetQueue.isFill()) {
std::this_thread::sleep_for(100ms);
continue;
}
@ -44,7 +44,7 @@ void RequestPacket(VideoParam& param) {
}
if (ret == 0) {
if (packet->stream_index == videoStreamIndex) {
param.queue.push(packet);
param.packetQueue.push(packet);
av_packet_unref(packet);
}
else if (ret == AVERROR_EOF)
@ -52,57 +52,52 @@ void RequestPacket(VideoParam& param) {
param.eof = true;
av_packet_unref(packet);
break;
}else {
}
else {
av_packet_unref(packet);
}
}else if(param.fmtCtx->pb->error == 0) {
}
else if (param.fmtCtx->pb->error == 0) {
std::this_thread::sleep_for(100ms);
}
}
av_packet_unref(packet);
}
AVFrame* RequestFrame(VideoParam& param) {
void RequestFrame(VideoParam& param) {
const auto& fmtCtx = param.fmtCtx;
const auto& codecCtx = param.codecCtx;
const auto& videoStreamIndex = param.videoStreamIndex;
AVPacket* packet = av_packet_alloc();
AVFrame* frame = av_frame_alloc();
//frame->format = AV_PIX_FMT_YUV420P;
while (true) {
if (!param.queue.pop(packet, true, param.quit)) {
if(param.quit)
//NOTE:if no need do something, just return nullptr
return nullptr;
if (param.frameQueue.isFill()) {
std::this_thread::sleep_for(30ms);
continue;
}
if (!param.packetQueue.pop(packet, true, param.quit)) {
if (param.quit)
{
av_packet_unref(packet);
av_frame_unref(frame);
return;
}
continue;
}
int ret = avcodec_send_packet(codecCtx, packet);
if(ret < 0) {
av_packet_unref(packet);
av_frame_free(&frame);
return nullptr;
if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
continue;
}
if (ret == 0) {
ret = avcodec_receive_frame(codecCtx, frame);
if (ret == 0) {
av_packet_unref(packet);
return frame;
}
if (ret == AVERROR(EAGAIN)) {
continue;
}
av_frame_free(&frame);
av_packet_free(&packet);
return nullptr;
}
if (ret == AVERROR_EOF)
ret = avcodec_receive_frame(codecCtx, frame);
if (ret < 0 && ret != AVERROR_EOF)
{
av_packet_unref(packet);
return nullptr;
continue;
}
av_packet_unref(packet);
param.frameQueue.push(frame);
av_frame_unref(frame);
}
}

10
todo.txt Normal file
View File

@ -0,0 +1,10 @@
bug:
1. 退出时异常
todo:
1. 添加音频播放
2. 优化视频帧率同步
3. 添加音频操作
4. 添加视频操作
5. 优化内存
6. 优化代码