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. /* try again and reuse existing stream */
  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. double vdelta = 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/XXX remove this hack
  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转码时对编码率和固定码率的处理的更多相关文章

  1. 使用ffmpeg转码时遇到aac报错

    今天尝试用ffmpeg转一个视频的格式,结果报出这个错误: The encoder 'aac' is experimental but experimental codecs are not enab ...

  2. 最新版ffmpeg源码分析

    最新版ffmpeg源码分析一:框架 (ffmpeg v0.9) 框架 最新版的ffmpeg中发现了一个新的东西:avconv,而且ffmpeg.c与avconv.c一个模样,一研究才发现是libav下 ...

  3. 修改FFMpeg源码—捕获丢包

    概述 最近我们项目有一个需求就是解决客户端播放RTSP视频流花屏的问题,一般来说丢包就会引起花屏,导致客户端花屏的因素又有很多,比如说: 相机到服务器丢包 服务器到客户端丢包 等等... 其中服务器到 ...

  4. ffmpeg转码器移植VC的工程:ffmpeg for MFC

    本文介绍一个自己做的FFMPEG移植到VC下的开源工程:ffmpeg for MFC.本工程将ffmpeg工程中的ffmpeg转码器(ffmpeg.c)移植到了VC环境下.并且使用MFC做了一套简单的 ...

  5. ffmpeg源码编译安装(Compile ffmpeg with source) Part 2 : 扩展安装

    在Ubuntu,Debian,Mint上编译ffmpeg 本文主要为在Ubuntu,Debian和Mint上编译安装ffmpeg和库文件以及一些扩展的编解码器.当然这与从源中安装无关. 请首先看一下通 ...

  6. 【转】使用ffmpeg转码的MP4文件需要加载完了才能播放的解决办法

    1.前一段时间做了一个ffmpeg转码MP4的项目,但是转出来的MP4部署在网站上需要把整个视频加载完成才能播放,到处找资料,最后找到解决方案记录于此备忘. FFMpeg转码由此得到的mp4文件中, ...

  7. ffmpeg转码器移植VC的project:ffmpeg for MFC

    本文介绍一个自己做的FFMPEG移植到VC下的开源project:ffmpeg for MFC.本project将ffmpegproject中的ffmpeg转码器(ffmpeg.c)移植到了VC环境下 ...

  8. FFmpeg源码简单分析:结构体成员管理系统-AVOption

    ===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...

  9. NVIDIA FFmpeg 转码技术分析

    NVIDIA FFmpeg 转码技术分析 所有从 Kepler 一代开始的 NVIDIA GPUs 都支持完全加速的硬件视频编码,而从费米一代开始的所有 GPUs 都支持完全加速的硬件视频解码.截至 ...

随机推荐

  1. 一、换系统wince ---到 linux ubuntu 桌面

    今天终于拿到了OK6410,还是比较满意.预装的为wince系统,现要修改为linux 按照  OK6410-A开发板LINUX3.0.1-2013-01用户手册 进行 1.遇到问题.无法写入SD卡( ...

  2. Xcode7 制作通用的framework(转)

      2016-01-07 16:24 2994人阅读 评论(0) 收藏 举报 分类: ios x code(55) 1.新建一个静态库工程. file→ new→ project, 弹出框中选择iOS ...

  3. 读TCP-IP详解卷1:协议(1)

    1.TCP传给IP的数据单元称作TCP报文段或简称为TCP段(TCP segment)IP传给网络接口层的数据单元称作IP数据报(IPdatagram).通过以太网传输的比特流称作帧(Frame).

  4. < java.lang >-- String字符串

    java中用String类进行描述.对字符串进行了对象的封装.这样的好处是可以对字符串这种常见数据进行方便的操作.对象封装后,可以定义N多属性和行为. 如何定义字符串对象呢?String s = &q ...

  5. UML 中的用例图解析以及starUML详细介绍

    UML中的用例(Use Case)概念分析及StarUML实例 在UML 中use case 似 乎最簡單的,用例建模的最主要功能就是用来表达系统的功能性需求或行为,依我的理解用例建模可分为用例图和用 ...

  6. cocos2dx中导演的职责有哪些?

    1.一个游戏里面只有一个导演,因此采用了单例的设计模式,用getInstance方法来获得 2.游戏中导演负责openGL ES的初始化,场景的切换,游戏的暂停继续(相当于拍电影的ka),节点坐标与世 ...

  7. 封装insertAfter、addClass、格式化时间

    insertAfter,在JS节点操作中,并没有insertAfter方法,因此需要重新封装 function insertAfter(newEle,targetNode) { var oParent ...

  8. IIS8中 出现ashx 401:未授权,uploadify上传文件失败

    环境:阿里云服务器 windows2012  + IIS8 +asp.net 访问IIS 出现能正常访问aspx页面,但是通过ajax访问ashx上传文件的时候就出现ashx  Status Code ...

  9. 【Valid Parentheses】cpp

    题目: Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the ...

  10. 学习Linux第七天

    1.shell echo $HOME 默认在shell中编写的变量全部是局部变量,如果重新打开console的话,那么这些变量将全部丢失,全局的变量可以写在文件~/.bashrc文件. 2.判断 !/ ...