如何在FFmpeg C API编码之前计算帧的正确PTS值?
对于编码我正在使用函数avcodec_encode_video2,然后通过编写它av_interleaved_write_frame.
我发现了一些公式,但其中没有一个不起作用.
在doxygen示例中,他们正在使用
frame->pts = 0;
for (;;) {
// encode & write frame
// ...
frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
}
Run Code Online (Sandbox Code Playgroud)
这篇博客说公式必须是这样的:
(1/FPS)*采样率*帧数
有人只使用帧号来设置pts:
frame->pts = videoCodecCtx->frame_number;
Run Code Online (Sandbox Code Playgroud)
或者替代方式:
int64_t now = av_gettime();
frame->pts = av_rescale_q(now, (AVRational){1, 1000000}, videoCodecCtx->time_base);
Run Code Online (Sandbox Code Playgroud)
最后一个:
// 40 * 90 means 40 ms and 90 because of the 90kHz by the standard for PTS-values.
frame->pts = encodedFrames * 40 * 90;
Run Code Online (Sandbox Code Playgroud)
哪一个是正确的?我认为这个问题的答案不仅对我有帮助.
小智 9
在尝试代码之前,最好更抽象地考虑PTS.
你正在做的是将3个"时间集"整合在一起.第一个是我们习惯的时间,基于每秒1000毫秒,每分钟60秒,依此类推.第二个是您正在使用的特定编解码器的编解码器时间.每个编解码器都有一种想要表示时间的特定方式,通常是1 /数字格式,这意味着每秒都有"数量"的刻度.第三种格式与第二种格式类似,不同之处在于它是您使用容器的时基.
有些人喜欢从实际时间开始,有些人更喜欢帧数,也不是"错误".
从帧数开始,您需要先根据帧速率进行转换.请注意我所说的所有转换都使用av_rescale_q(...).此转换的目的是将计数器转换为时间,因此您需要使用帧速率(通常为视频流时基)进行重新缩放.然后,您必须在编码之前将其转换为视频编解码器的time_base.
同样,实时,您的第一次转换需要从current_time - start_time缩放到您的视频编解码器时间.
任何只使用帧计数器的人可能正在使用time_base等于其帧速率的编解码器.大多数编解码器不能像这样工作,他们的黑客不可移植.例:
frame->pts = videoCodecCtx->frame_number; // BAD
Run Code Online (Sandbox Code Playgroud)
此外,任何在av_rescale_q中使用硬编码数字的人都在利用他们知道他们的time_base是什么的事实,这应该避免.该代码无法移植到其他视频格式.而是使用video_st->那么time_base,video_st-> codec->那么time_base和output_ctx->那么time_base理出头绪.
我希望从更高层次理解它会帮助你看到哪些是"正确的",哪些是"坏习惯".没有单一的答案,但也许现在您可以决定哪种方法最适合您.
| 归档时间: |
|
| 查看次数: |
7854 次 |
| 最近记录: |