我有一个3500帧的HEVC序列,我正在写一个解码器来读取它(逐帧读取并转储到yuv)。在我的main()中,我有一个for循环,调用一个解码器()3500次(我假设在这个阶段main()知道有多少帧。)
因此,对于每次调用decoder(),我都需要返回一个完整的帧。这就是解码器()的样子..
bool decode(pFormatCtx, pCodecCtx)
{
int gotaFrame=0;
while (gotaFrame==0) {
printf("1\t");
if ( !av_read_frame(pFormatCtx, &packet) ) {
if(packet.stream_index==videoStreamIndex) {
// try decoding
avcodec_decode_video2(pCodecCtx, pFrame, &gotaFrame, &packet);
if (gotaFrame) { // decode success.
printf("2\t");
// dump to yuv ... not shown here.
// cleanup
av_frame_unref(pFrame);
av_frame_free(&pFrame);
av_free_packet(&packet);
return true;
}
}
}
}
}
行为是这样的:1 1 1 1 1 1 1 1 1 1 1 1 2 1 2 1 2 ......在解码之前看起来好像读了几帧?第一帧是I帧,所以不应该立即解码?
使用这段代码,我最终失去了几帧(由1系列表示)。有人可以帮帮我吗?我的代码中有什么问题吗?
更新:测试片段仅限视频。没有音频。
答案 0 :(得分:9)
您所看到的是正确的行为。解码器提供几帧以实现多线程效率。并且可能需要几个框架来启动泵。原样。基本上,为了使您的程序保持响应,avcodec_decode_video2将帧排队等待解码,然后返回。这可以防止程序长时间阻塞。在B帧的情况下,绝对需要延迟解码,其中解码顺序可能与显示顺序不同。
那么,如何不丢失这些帧?在av_read_frame停止返回新帧之后,您必须通过使用空数据包调用avcodec_decode_video2来刷新解码器,直到不再重新调整帧为止。
答案 1 :(得分:0)
最可能失败的是测试if(packet.stream_index==videoStreamIndex)
,而不是av_read_frame
:您可能正在从另一个流中读取数据包(例如,音频流数据包被标记为" i-frames&#34 ;)
对于你的第一个I帧,I帧通常需要解码两个数据包(即第一次调用avcodec_decode_video2
返回gotaFrame == 0
)