上一篇文章(http://my.oschina.net/u/2336532/blog/400790)我们解决了在FFmpeg下如何处理H264和AAC的扩展数据,根据解出的NALU长度恢复了H264的起始码和AAC的ADTS头,这样一般来说播放是没有问题。本篇文章来谈谈如何实现基于FFmpeg的track mode控制,也就是如何用FFmpeg提供的功能来实现基本的seek、快进、快退。好了,废话少了,下面开始基于FFmpeg的track mode之旅。

FFmpeg提供了一个seek函数,原型如下:

int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp,                   int flags);

参数说明:

s:操作上下文;

stream_index:基本流索引,表示当前的seek是针对哪个基本流,比如视频或者音频等等。

timestamp:要seek的时间点,以time_base或者AV_TIME_BASE为单位。

Flags:seek标志,可以设置为按字节,在按时间seek时取该点之前还是之后的关键帧,以及不按关键帧seek等,详细请参考FFmpeg的avformat.h说明。基于FFmpeg的所有track mode几乎都是用这个函数来直接或间接实现的。

  • 文件的seek功能实现

要转跳到视频100秒(100 000毫秒)处的第一个I帧(如果没有则向前找第一个):

av_seek_frame(pFormatCtx, vid_index, 100000*vid_time_scale/time_base, AVSEEK_FLAG_BACKWARD);

跳到音频80秒(80 000毫秒)处的帧(采样):

av_seek_frame(pFormatCtx, aud_index, 80000*aud_time_scale/ time_base, AVSEEK_FLAG_BACKWARD);

跳到文件开始的地方开始播放:

av_seek_frame(pFormatCtx, vid_index, 0, AVSEEK_FLAG_BACKWARD);

上面的time_scale、time_base都能通过流信息获取到,请参考前面的文章。有的文件不一定能seek成功,可以考虑在失败的情况下将AVSEEK_FLAG_BACKWARD改为AVSEEK_FLAG_ANY再次seek,不过seek到的视频帧可能不是I帧。

这个函数不管你当前在什么时间点上,都可以seek到任何合理位置。比如要实现在当前的基础上向后或向前跳转10秒,我们可以在av_read_frame函数拿到的包中含有当前时间戳的基础上增加或较少一个10000(换算成播放时间单位)再seek即可。所以这个函数可以用做进度的拖放、前进/后退一定时间、循环播放等功能。

  1. 快进快退

对于快进来说,一般解码器能实现2倍甚至再高倍速的播放,这种情况直接按照上一篇文章的基本播放流程就可以了。但对于4倍、8倍、16倍、32倍等高速播放,一般不能像传统播放那样一帧一帧的送数据,不只是解码能力问题,数据读取也可能因为带宽不够跟不上,我们只能提取其中的I帧进行播放,将B帧和P帧丢掉。下面我们就来讨论这个过程的实现流程。

快进时,通过当前数据包获得当前的时间PTS,将该PTS换算成时间再加上一小段时间,作为seek时间点向后找关键帧,此时flags可设置为AVSEEK_FLAG_FRAME。之后用av_read_frame获取到该关键帧。完成该帧解码显示后,再在该帧的PTS时间上增加一小段时间后seek,这样一直重复上述过程,流程如下图:

快退时,通过当前数据包获得当前的时间PTS,将该PTS换算成时间再减去一小段时间,作为seek时间点向前找关键帧,此时flags可设置为AVSEEK_FLAG_BACKWARD。之后用av_read_frame获取到该关键帧。完成该帧解码显示后,再在该帧的PTS时间上减去一小段时间后seek,这样一直重复上述结果,过程如下图:

这样,我们通过以上对av_seek_frame函数的运用,即可完成文件playback的各种track mode实现,其实理解了这个函数后,你还会有很多其他办法来实现,这里只是提供了一种简单且占内存少的办法。在特定的情况下还可以先全部走一遍所有帧,并记录下全部的I帧的时间戳、帧编号、位置信息等需要的信息,然后直接从该表里面获取信息后进行seek和读取这些关键帧进行快速播放。

想第一时间获得更多原创文章,请关注个人微信公众平台:程序员互动联盟(coder_online),扫一扫下方二维码或者搜索微信号coder_online即可关注,里面有大量Android,Chromium,Linux,编程技巧等相关文章等着您,我们还可以在线交流。

如需转载本文,请注明出处:http://my.oschina.net/u/2336532

谢谢合作!

解密FFmpeg播放状态控制内幕的更多相关文章

  1. 解密FFmpeg播放track mode控制

    上一篇文章(http://www.cnblogs.com/yangdanny/p/4421130.html)我们解决了在FFmpeg下如何处理H264和AAC的扩展数据,根据解出的NALU长度恢复了H ...

  2. apk支持html video控制 ,是播放状态就暂停,暂停状态就播放

    apk支持html video控制 <!DOCTYPE html> <html> <body> <div style="text-align:cen ...

  3. 基于 SailingEase WinForm Framework 开发客户端程序(3:实现菜单/工具栏按钮的解耦及状态控制)

    本系列文章将详细阐述客户端应用程序的设计理念,实现方法. 本系列文章以  SailingEase WinForm Framework 为基础进行设计并实现,但其中的设计理念及方法,亦适用于任何类型的客 ...

  4. FFMpeg的码率控制

    mediaxyz是一位研究ffmpeg有三年的高人了,这几天一直在折腾ffmpeg中的x264,就是不知道该如何控制码率,主要是参数太多,也不知道该如何设置,在google上search了一下,这方面 ...

  5. [转载] FFMpeg的码率控制

    mediaxyz是一位研究ffmpeg有三年的高人了,这几天一直在折腾ffmpeg中的x264,就是不知道该如何控制码率,主要是参数太多,也不知道该如何设置,在google上search了一下,这方面 ...

  6. mediaxyz访谈录:ffmpeg的码率控制

    mediaxyz是一位研究ffmpeg有三年的高人了,这几天一直在折腾ffmpeg中的x264,就是不知道该如何控制码率,主要是参数太多,也不知道该如何设置,在 google上search了一下,这方 ...

  7. ffmpeg播放器实现详解 - 视频显示

    ffplay是ffmpeg源码中一个自带的开源播放器实例,同时支持本地视频文件的播放以及在线流媒体播放,功能非常强大. FFplay: FFplay is a very simple and port ...

  8. 重新想象 Windows 8 Store Apps (65) - 后台任务: 音乐的后台播放和控制

    [源码下载] 重新想象 Windows 8 Store Apps (65) - 后台任务: 音乐的后台播放和控制 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后台 ...

  9. Win7 VS2017简单编译FFMPEG播放器FFPlay

    Win平台简单编译FFPlay播放器,顺便纪念下雷霄骅,一年前刚学FFMPEG时还看过他的博客,昨晚再次搜FFMPEG文章时才知道人已经走了... 做成了视频放到B站 https://www.bili ...

随机推荐

  1. ActivityGroup+LinearLayout实现iphone风格的底部tab菜单

    public class ActsGroup extends ActivityGroup {       private LinearLayout bodyView;     private Line ...

  2. mongodb的分布式集群(4、分片和副本集的结合)

    概述 前面3篇博客讲了mongodb的分布式和集群,当中第一种的主从复制我们差点儿不用,没有什么意义,剩下的两种,我们不论单独的使用哪一个.都会出现对应的问题.比較好的一种解决方式就是.分片和副本集的 ...

  3. [转]Oracle快速入门

    原文出处:http://blog.csdn.net/yueguanghaidao/article/details/7019377 select * from scott.salgrade; /*解锁s ...

  4. The Kernel Newbie Corner: Kernel Debugging Using proc "Sequence" Files--Part 1

    转载:https://www.linux.com/learn/linux-career-center/37985-the-kernel-newbie-corner-kernel-debugging-u ...

  5. WinForm实现跨进程通信的方法

    public class WinMessageHelper { private struct COPYDATASTRUCT { public IntPtr dwData; public int cbD ...

  6. Jquery 扩展方法

    $.fn是指jquery的命名空间,加上fn上的方法及属性,会对jquery实例每一个有效. 如扩展$.fn.abc() 那么你可以这样子:$("#div").abc(); 通常使 ...

  7. Play on Words 欧拉通路(回路)判断

    Play on Words note:  判断一下连通性. #include <iostream> #include <cstdio> #include <cstring ...

  8. PathAnimation

    使用Blend制作PathAnimation 1:选中Path转换为运动路径 2:选择目标对象 PathAnimation使用动态的Path PathAnimation动画在播放的时候,PahtGeo ...

  9. 1.4.8 拼凑在一起(putting the pieces together)

    putting the pieces together 在最高的级别,schema.xml结构如下, <schema> <types> <fields> <u ...

  10. IOS 设置定时器

    IOS 设置定时器  自动滚动视图 定时发送坐标信息 即时显示 时钟 NSTimer *timer; - (void)start {//1second 调用一次 timer = [NSTimer sc ...