多线程解码视频帧, 添加todo.txt
This commit is contained in:
parent
659ca4772d
commit
2641cb0bb3
@ -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
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user