如何使用libavcodec高效地查找和解码第N帧?

3
请注意,这不是类似帖子的重复内容!
我想找到并解码第N帧,例如第7帧。
据我所知,使用“time_base”可以计算每一帧有多少个滴答,并通过将其乘以7来获得第7帧的位置。要计算滴答数,我执行以下操作:
AVStream inStream = getStreamFromAVFormatContext();

int fps = inStream->r_frame_rate.num;
AVRational timeBase = inStream->time_base;

int ticks_per_frame = (1/fps) / timeBase;
int _7thFramePos = ticks_per_frame * 7;
  1. 我计算第7帧的位置正确吗?如果是,那么要跳转到该帧,我只需要执行av_seek_frame(pFormatCtx, -1, _7thFramePos, AVSEEK_FLAG_ANY),是吗? 如果第7帧是P帧或B帧,我该如何解码它呢?
  2. 我注意到计算出来的值与inStream->codec->ticks_per_frame不同,为什么?它们不应该相同吗?有什么区别?
1个回答

1

这篇文章很好地解释了问题。 http://www.hackerfactor.com/blog/index.php?/archives/307-Picture-Go-Back.html

[1] AVStream结构的评论清楚地提到,“r_frame_rate”只是一个猜测,可能不准确,因为即使我有25fps的帧速率,在基准时间方面,我可能每秒有24或26帧。

[2] 要找到确切的帧数,您需要从开头解码帧并保持计数器,但这非常低效,可以针对某些文件格式进行优化,例如MP4,其中每个帧的信息都在文件头中。


可以提供一些例子吗? - theateist
那么我如何计算时间戳以传递给 av_seek_frame 函数? - theateist
如果您不需要100%准确性,可以使用带有AVSEEK_FLAG_FRAME标志的avformat_seek_file()函数。如果您需要100%准确性,则应从流的开头开始解码,并保持计数器直到达到所需的帧数,一旦达到所需的帧数,就停止解码。 - rajneesh
1 - avformat_seek_fileAVSEEK_FLAG_FRAME一起使用会做什么?它会找到哪一帧,最接近第N个I-Frame还是其他的? 2 - 你的意思是如果我需要X次获取X帧,每次都要从流的开头开始吗? - theateist
  1. AVSEEK_FLAG_FRAME - 允许您按帧编号指定搜索位置,avformat_seek_file()允许您指定所需帧编号的最小-最大偏差。
  2. 如果您需要跳转到第X帧,则需要先解码前X帧,但如果您可以在第一次时保留关键帧的索引,则可以进行优化,下一次可以在avformat_seek_file()中寻找最接近的关键帧,然后移动到所需的帧。
- rajneesh
  1. 我有点困惑,如果我可以指定帧数,为什么它不是100%准确的,会导致偏差呢?
  2. 假设我提前知道fps并且它是静态的,那么我的上述帧计算是否正确?
- theateist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接