vcodec_receive_frame
函数没有收到其余的帧。我测试了视频总共有132帧,并且只收到了125帧在视频结尾处丢失了7帧。如何找回丢失的镜框?
但是发生了一些奇怪的事情。如您所见,我的MyDecode::receiveFrame()
函数的输出。首先执行块if (ret != 0){}
中的代码,但是丢失的帧位于视频的末尾。那么他们怎么会首先出来呢?造成这种情况的原因是什么?
MyDecode.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;
}
main.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;
}
}
答案 0 :(得分:4)
您必须发送NULL pkts到解码器以耗尽所有未决帧。
来自avcodec.h
流结束情况。这些需要“冲洗”(又称排水) 编解码器,因为编解码器可能会缓冲多个帧或数据包 内部出于性能考虑或出于必要(考虑B帧)。
处理方法如下:
-将无效值发送到avcodec_send_packet()(解码),而不是有效输入 或avcodec_send_frame()(编码)函数。这将进入排水 模式。
-调用avcodec_receive_frame()(解码)或avcodec_receive_packet() (编码)循环进行,直到返回AVERROR_EOF。该功能将 除非您忘记进入排水模式,否则不会返回AVERROR(EAGAIN)。 -在重新恢复解码之前,必须使用以下命令重置编解码器: avcodec_flush_buffers()。