gpt4 book ai didi

FFmpeg - avcodec_receive_frame 在接收帧之前不接收所有帧并丢失帧

转载 作者:行者123 更新时间:2023-12-04 22:52:16 25 4
gpt4 key购买 nike

vcodec_receive_frame函数没有接收到其余的帧。我测试了视频总共有 132 帧,它只收到了 125 帧 在视频结尾丢失 7 帧 .如何找回丢失的帧?

但是奇怪的事情发生了。如您所见,我的 MyDecode::receiveFrame() 的输出功能。 block 内的代码if (ret != 0){}首先执行,但丢失的帧在视频的末尾。那么他们怎么会先出来呢?是什么导致了这种情况发生?

我的解码.cpp

AVFrame* MyDecode::receiveFrame()
{
mux.lock();
if (!codecCtx) {
mux.unlock();
return 0;
}
AVFrame* frame = av_frame_alloc();
int ret = avcodec_receive_frame(codecCtx, frame);
mux.unlock();
if (ret != 0)
{
static int lost_frames = 1;
std::cout << "Lost frames: " << lost_frames << std::endl;
lost_frames += 1;
av_frame_free(&frame);
return nullptr;
}
std::cout << "Received frames: " << received_frame_num << std::endl;
received_frame_num += 1;
return frame;
}

bool MyDecode::sendPacket(AVPacket* packet)
{
if (!packet || !packet->data || packet->size == 0)
return false;
mux.lock();
if (!codecCtx) {
mux.unlock();
return false;
}
int ret = avcodec_send_packet(codecCtx, packet);
mux.unlock();
av_packet_free(&packet);
if (ret != 0) {
return false;
}
return true;
}

控制台输出
Total frames: 132
Lost frames: 1
Lost frames: 2
Lost frames: 3
Lost frames: 4
Lost frames: 5
Lost frames: 6
Lost frames: 7
Received frames: 1
Received frames: 2
Received frames: 3
................
Received frames: 125

更新:

MyDemux.cpp
AVPacket* MyDemux::readFrame()
{
mux.lock();
if (!formatCtx) {
std::cout << "formaetCtx is null" << std::endl;
mux.unlock();
return nullptr;
}
AVPacket* packet = av_packet_alloc();
if (!packet) {
std::cout << "packet is null" << std::endl;
mux.unlock();
return nullptr;
}

int ret = av_read_frame(formatCtx, packet);
if (ret != 0) {
while (true) {
av_read_frame(formatCtx, nullptr);
}
mux.unlock();
av_packet_free(&packet);
av_packet_unref(packet);
return nullptr;
}
media_type = packet->stream_index;
mux.unlock();
return packet;
}

主.cpp
while (true) {
AVPacket* pkt = demux.readFrame();
if (demux.get_media_type() == 0) {
AVFrame* frame = video_decode.receiveFrame();
videoWidget->paintFrame(frame);
}
else if (demux.get_media_type() == 1) {
}
if (!pkt) {
std::cout << "to break" << std::endl;
break;
}
}

最佳答案

您必须向解码器发送 NULL pkts 以耗尽所有未决帧。

来自 avcodec.h

End of stream situations. These require "flushing" (aka draining) the codec, as the codec might buffer multiple frames or packets internally for performance or out of necessity (consider B-frames).
This is handled as follows:
- Instead of valid input, send NULL to the avcodec_send_packet() (decoding) or avcodec_send_frame() (encoding) functions. This will enter draining mode.
- Call avcodec_receive_frame() (decoding) or avcodec_receive_packet() (encoding) in a loop until AVERROR_EOF is returned. The functions will not return AVERROR(EAGAIN), unless you forgot to enter draining mode. - Before decoding can be resumed again, the codec has to be reset with avcodec_flush_buffers().

关于FFmpeg - avcodec_receive_frame 在接收帧之前不接收所有帧并丢失帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55292212/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com