多线程解码视频帧, 添加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

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

View File

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