当前位置: 首页 > >

FFMPEG之时间基

fps=29.97


fps=29.97这是一个小数啊,我如果直接利用公式 frame number = time * fps 得到了也不是一个整数啊,而帧号应该是一个整数才对。
首先,29.97f/s这个变态的数是如何得到的?这起源于早期的NTSC电视制式,而现代的数字编码只是为了兼容而沿用了它的标准。其实在标准制定时,NTSC采用的是30f/s的帧率,只是后来为了消除由彩色信号及伴音信号所产生的图像干扰,每秒?幅由30帧稍微下?至29.97帧,同?频率由15750Hz稍微下降至15734.26Hz。欲知详情,参看Wikipedia。
然后,带小数点的帧率如何实现呢,显然每一秒不可能显示相同个数的帧。实际上存在着叫做SMPTE Non-Drop-Frame和SMPTE Drop-Frame的时间同步标准,也就是说在某些时候,会通过丢掉一些帧的方式来将时间同步上。
比如刚才提到的29.97帧率,我们可以计算:29.97 f/sec = 1798.2 f/min = 107892 f/hour;
对于30f/s的帧率我们可以计算: 30 f/s = 1800 f/s = 108000 f/hour;
这样,如果利用每秒30帧的速度来采集视频,而用29.97f/s的速率来播放视频,每个小时就少播放了108帧,这样播放时间会比真实时间变慢。为了解决这个问题,SMPTE 30 Drop-Frame就采取了丢掉这108帧的方式,具体策略是每1分钟丢两帧,如果是第10分钟则不丢,所以每小时丢掉的帧数是:2×60 ? 2×6 = 108 帧。


time_base


FFMPEG的很多结构中有AVRational time_base;这样的一个成员,它是AVRational结构的


typedef struct AVRational{
??? int num; ///< numerator
??? int den; ///< denominator
} AVRational;


AVRational这个结构标识一个分数,num为分数,den为分母。


?


实际上time_base的意思就是时间的刻度:


如(1,25),那么时间刻度就是1/25,(1,9000),那么时间刻度就是1/90000,那么,在刻度为1/25的体系下的time=5,转换成在刻度为1/90000体系下的时间time为(5*1/25)/(1/90000) = 3600*5=18000


ffmpeg中做pts计算时,存在大量这种转换


在以下结构中都有


AVCodecContext:编解码上下文。


AVStream:文件或其它容器中的某一个track。


如果由某个解码器产生固定帧率的码流,AVCodecContext中的AVRational根据帧率来设定,如25帧,那么num = 1,den=25


AVStream中的time_base一般根据其采样频率设定,如(1,90000)


在某些场景下涉及到PTS的计算时,就涉及到两个Time的转换,以及到底取哪里的time_base进行转换:


场景1:编码器产生的帧,直接存入某个容器的AVStream中,那么此时packet的Time要从AVCodecContext的time转换成目标AVStream的time


场景2:从一种容器中demux出来的源AVStream的frame,存入另一个容器中某个目的AVStream。


??????????? 此时的时间刻度应该从源AVStream的time,转换成目的AVStream timebase下的时间。


其实,问题的关键还是要理解,不同的场景下取到的数据帧的time是相对哪个时间体系的。


demux出来的帧的time:是相对于源AVStream的timebase


编码器出来的帧的time:是相对于源AVCodecContext的timebase


mux存入文件等容器的time:是相对于目的AVStream的timebase


这里的time指pts。
解码后,decoded_frame->pts的值使用AVStream->time_base为单位,后在AVFilter里面转换成以AVCodecContext->time_base为单位。?? //FIXME
编码后,pkt.pts、pkt.dts使用AVCodecContext->time_base为单位,后通过调用"av_packet_rescale_ts"转换为AVStream->time_base为单位。


tbn,tbr,tbc


??? ffmpeg -i video.flv
??? Stream #0.0[0x1e0]: Video: mpeg2video, yuv420p, 704x576 [PAR 12:11 DAR 4:3], 9578 kb/s, 25 tbr, 90k tbn, 50 tbc
??? tbn = the time base in AVStream that has come from the container
??? tbc = the time base in AVCodecContext for the codec used for a particular stream
??? tbr = tbr is guessed from the video stream and is the value users want to see when they look for the video frame rate
不是所有参数都能得到的,有的文件没有这些信息,要看解析层而定。
代码如下:
??? if(st->codec->codec_type == CODEC_TYPE_VIDEO){
????? if(st->r_frame_rate.den && st->r_frame_rate.num)
??????? print_fps(av_q2d(st->r_frame_rate), "tbr");
????? if(st->time_base.den && st->time_base.num)
??????? print_fps(1/av_q2d(st->time_base), "tbn");
????? if(st->codec->time_base.den && st->codec->time_base.num)
??????? print_fps(1/av_q2d(st->codec->time_base), "tbc");
??? }
25?? tbr代表帧率;
90k tbn代表文件层(st)的时间精度,即1S=1200k,和duration相关;
50?? tbc代表视频层(st->codec)的时间精度,即1S=50,和strem->duration和时间戳相关。
?


转载自:http://blog.csdn.net/supermanwg/article/details/14521869



友情链接: year2525网 工作范文网 QS-ISP 138资料网 528200 工作范文网 baothai 表格模版