ffmpeg转码时对编码率和固定码率的处理

摘要:
当输入视频流的帧速率不固定,如rmvb,但输出视频流的帧速率固定时,ffmpeg执行以下处理:1.记录与输出视频流ost对应的输入视频流ist,变量为ost-˃sync_ist这是在av_转码函数初始化输出流。doublevdelta=sync_ipts ost-˃sync_opts;5.根据vdelta判断不同情况。看起来ffmpeg_ sync_ Method中的视频始终设置为-1。ffmpeg的帧插入操作似乎重复当前输出帧的输出nb_帧次。AVFrame*old_frame=enc-˃coded_frame;enc-˃coded_frame=dec-˃coded_ frame;//修复/XXX删除此黑客包。数据=最终图片;pkt.size=大小;pkt.pts=平均重新缩放q;pkt.flags |=AV_ pkt_FLAG_ KEY;write_帧;enc-˃coded_frame=旧帧;输出数据以pkt-in数据显示,final_ Picture是处理后的输入Pic。Rmvb的vedioMDPR块存储fps和fps2信息。Ffmpeg采用fps作为帧速率,fps2丢弃它。

http://www.rosoo.net/a/201107/14663.html

一般fps在代码里这样表示

Fps = den/num

如果den = 15,num=1,则fps = 15。

如果帧率固定,pts*fps 就表示当前是第几帧。

当输入视频流的帧率不固定,如rmvb ,而输出视频流的帧率固定,ffmpeg作如下处理(参考ffmpeg代码版本0.6.1):

1、 记录和输出视频流ost相对应的输入视频流ist,变量为ost->sync_ist。这是在av_transcode函数进行输出流初始化时进行的。代码分别为:

  1. if(ist->discard&&ist->st->discard!=AVDISCARD_ALL&&!skip&&
  2. ist->st->codec->codec_type==ost->st->codec->codec_type){
  3. if(best_nb_frames<ist->st->codec_info_nb_frames){
  4. best_nb_frames=ist->st->codec_info_nb_frames;
  5. ost->source_index=j;
  6. found=1;
  7. }
  8. }
  9. if(!found){
  10. if(!opt_programid){
  11. /*tryagainandreuseexistingstream*/
  12. for(j=0;j<nb_istreams;j++){
  13. ist=ist_table[j];
  14. if(ist->st->codec->codec_type==ost->st->codec->codec_type
  15. &&ist->st->discard!=AVDISCARD_ALL){
  16. ost->source_index=j;
  17. found=1;
  18. }
  19. }
  20. }
  21. ist=ist_table[ost->source_index];
  22. ist->discard=0;
  23. ost->sync_ist=(nb_stream_maps>0)?
  24. ist_table[file_table[stream_maps[n].sync_file_index].ist_index+
  25. stream_maps[n].sync_stream_index]:ist;

2、 记录输出视频流ost的时间戳。输出为固定帧率,故可以简化为记录帧数,变量为ost->sync_opts。

3、 将ost对应的ist的pts转换成固定帧率的帧数形式。代码为

  1. sync_ipts=get_sync_ipts(ost)/av_q2d(enc->time_base);

get_sync_ipts计算ost对应的ist的pts,

av_q2d返回enc->time_base.num/ enc->time_base.den,即1/fps.

4、 将sync_ipts和ost->sync_opts进行求差。

  1. doublevdelta=sync_ipts-ost->sync_opts;

5、 根据vdelta来判断不同的情况。

l 情况一:Vdelta<-1.1,表示当前输入帧的播放时间在当前输出帧的前一帧之前,故舍弃该帧,nb_frames = 0。

l 情况二: (video_sync_method == 2 || (video_sync_method<0 && (s->oformat->flags & AVFMT_VARIABLE_FPS))){

if(vdelta<=-0.6){

nb_frames=0;

}else if(vdelta>0.6)

ost->sync_opts= lrintf(sync_ipts);}

这里video_sync_method==2 和video_sync_method < 0 表示什么意义,不是很清楚。貌似ffmpeg里video_sync_method一直设为-1。AVFMT_VARIABLE_FPS应该是变帧率的意 思。这种情况下,vdelta<=0.6,表示位于当前帧之前,也舍弃该帧,nb_frames = 0;vdelta>0.6表示位于当前帧之后,直接把该帧的时间戳作为输出的时间出来输出该帧;0.6<vdelta<=0.6时,不 做任何处理,nb_frames 根据默认值为1。

l 情况三:vdelta > 1.1

此时nb_frames = lrintf(vdelta),需要做插帧操作。

Ffmpeg的插帧操作,貌似是把当前输出帧重复输出nb_frames次。

  1. AVFrame*old_frame=enc->coded_frame;
  2. enc->coded_frame=dec->coded_frame;//FIXME/XXXremovethishack
  3. pkt.data=(uint8_t*)final_picture;
  4. pkt.size=sizeof(AVPicture);
  5. pkt.pts=av_rescale_q(ost->sync_opts,enc->time_base,ost->st->time_base);
  6. pkt.flags|=AV_PKT_FLAG_KEY;
  7. write_frame(s,&pkt,ost->st->codec,bitstream_filters[ost->file_index][pkt.stream_index]);
  8. enc->coded_frame=old_frame;

输出的数据在pkt.data里,final_picture即为经过处理的输入Pic。

6、输出视频流的帧率,是从输入视频流的包头数据中获得的。Rmvb的vedio MDPR块里,保存有fps和fps2信息。Ffmpeg取fps作为帧率,fps2丢弃了。Fps2有什么用,还不清楚。介绍rmvb格式的文章里也没有看到过关于fps的任何介绍。

免责声明:文章转载自《ffmpeg转码时对编码率和固定码率的处理》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇IDEA中RestfulToolkit插件的安装及使用airtest之脚本批量运行下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

ffmpeg 踩坑实录 近期使用总结(三)

一、背景介绍     将ffmpeg运用到项目上已经有一段时间了,趁现在有空赶紧记下来。 二、技术点总结    2.1 实现方式     项目里面主要运用的形式是,在java端,调用操作系统的方法,并执行切片命令。 在执行切片之前,出于对代码的健壮性考虑,一般会下意识地对文件和目标地址进行检查和创建路径。 这里除了,判断传入的String对象是否为空之外,...

三篇文章了解 TiDB 技术内幕——说计算

在这我们将关系模型简单理解为 Table 和 SQL 语句,那么问题变为如何在 KV 结构上保存 Table 以及如何在 KV 结构上运行 SQL 语句。 假设我们有这样一个表的定义: CREATE TABLE User { ID int, Name varchar(20), Role varchar(20), Age int, PRIMARY KEY (...

Python字符编码

字符编码 计算机只认识数字,我们平时在使用计算机时,用的都是人类能读懂的字符(用高级语言编程的结果也无非是在文件内写了一堆字符),如何能让计算机读懂人类的字符?必须经过一个过程: 字符--------(翻译过程)------->数字 这个过程实际就是一个字符如何对应一个特定数字的标准,这个标准称之为字符编码 一、存取文件的原理(nodepad++,...

编码 编码的转化

什么是字符编码 因为计算机是外国人创造的所以计算机最开始只能识别最开始的基本数字(毕竟是外国人创造的所以最开始是不支持伟大的汉语 ,所以everybody努力学习吧 创造 我们自己的伟大的技术) 计算机要想工作必须通电,也就是说‘电’驱使计算机干活,而‘电’的特性,就是高低电平(高低平即二进制数1,低电平即二进制数0),也就是说计算机只认识数字 很明显,我...

高效的数据压缩编码方式 Protobuf

一. protocol buffers 是什么? Protocol buffers 是一种语言中立,平台无关,可扩展的序列化数据的格式,可用于通信协议,数据存储等。 Protocol buffers 在序列化数据方面,它是灵活的,高效的。相比于 XML 来说,Protocol buffers 更加小巧,更加快速,更加简单。一旦定义了要处理的数据的数据结构之...

FFmpeg流媒体处理-收流与推流

本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10623968.html 1. 简介 流媒体是使用了流式传输的多媒体应用技术。如下是维基百科关于流媒体概念的定义: 流媒体 (streaming media) 是指将一连串的媒体数据压缩后,经过网络分段发送数据,在网络上即时传输影音以供观赏的一种技...