FFmpeg中有个比较重要的概念就是时间基。
ffmpeg本身有个时间基,视频输入流有时间基,输出流有时间基,音频也是相同道理。
主要的目的是方便他们自己内部计算。
我们先拿视频播放器来举例,其中要对时间进行处理的是视频的时间,音频的时间,然后两者要进行同步。
我们播放一个视频打印日志发现
视频的时间基是1/12800,这个12800怎么算出来的我是真不知道
音频时间基是1/48000,这个还好理解,音频采样率就是48000,也就是一秒钟采样48000个sample,那么每个sample就是对应1/48000秒。
我播放的视频刚好在26秒左右,看打印出来的日志是不是不那么看不懂了。26142其实就是毫秒(ms),不管音频视频的时间有多么奇葩,乘以timebase后都转换成了我们熟悉的毫秒
使用以下方式转换:
我们再以
项目地址
这个中的视频剪辑
就是下面这个,主要解码音视频,编码音视频都涉及到了时间基。
所以用这个说下时间基比较合适(对应文件是
项目地址 中的
VideoClip.cpp):
视频剪辑就是裁剪时间维度,比如我只要视频的4秒到10秒之间的视频,所以涉及的逻辑是先跳转(seek)到附近的关键帧,然后再解码到指定的地方,然后将avframe(yuv数据)进行编码,当然音频也是。
这里面就有输入流(audio,video)的时间基,因为要重新生成一个mp4文件,所以有输出流(audio,video)的时间基。所以我们需要转换
如果不转换要么写入不进去,要么播放有问题。
再看看AV_TIME_BASE:哪里需要用这个时间基呢?
比如我们录像的时候又视频和音频,比如视频的是1秒25帧,音频的采样率是44100。
那么视频的一帧所占的时间是1/25秒,音频的一个sample是1/44100秒,这时他们的时间基就是AV_TIME_BASE。不过还是需要做成分数形式timeBaseFFmpeg = (AVRational) {1, AV_TIME_BASE};我们每编码一个视频帧就需要打上时间戳,比如我们第一帧视频就是1 * (timeBaseFFmpeg * (1 / 25)),音频是相同道理。
但是在输出mp4文件的时候输出流有各自的时间基。所以这个时候需要做个转换。
av_packet_rescale_ts(vPkt, timeBaseFFmpeg, videoOutStream->time_base);
这是直接把AVpacket中对应的duration ,pts,dts都直接转换了。