来源:http://blog.csdn.net/chance_yin/article/details/10323441php
1、研究数字多媒体,首先要了解几个基本术语(ffmpeg的相关文档几乎都是英文的,不弄懂几个基本术语看文档仍是比较吃力的)java
一、容器/文件 (Container/file) ,既多媒体源文件git
二、媒体流(Stream):与时间相关的一段连续数据。既某一时刻对应某个数据,这样的多个连续数据组在一块儿就成了媒体流。数组
三、数据帧/数据包(Frame/Packet):一个媒体流由大量的数据帧构成。数据帧也是编解码器最小的处理单元。数据结构
2、FFmpeg 基础---FFmpeg中重要的几个数据结构app
一、AVCodecContext,这是一个描述编解码器上下文的数据结构,包含了众多编解码器须要的参数信息less
若是是单纯使用libavcodec,这部分信息须要调用者进行初始化;若是是使用整个FFMPEG库,这部分信息在调用 avformat_open_input和avformat_find_stream_info的过程当中根据文件的头信息及媒体流内的头部信息完成初始 化。其中几个主要域的释义以下:ide
二、AVStream 该结构体描述一个媒体流函数
主要域的释义以下,其中大部分域的值能够由avformat_open_input根据文件头的信息肯定,缺乏的信息须要经过调用avformat_find_stream_info读帧及软解码进一步获取:oop
三、AVFormatContext,这个结构体描述了一个媒体文件或媒体流的构成和基本信息
这是FFMpeg中最为基本的一个结构,是其余全部结构的根,是一个多媒体文件或流的根本抽象。其中:
一般,这个结构由avformat_open_input在内部建立并以缺省值初始化部分红员。可是,若是调用者但愿本身建立该结构,则须要显式为该结构的一些成员置缺省值——若是没有缺省值的话,会致使以后的动做产生异常。如下成员须要被关注:
四、AVPacket
FFMPEG使用AVPacket来暂存媒体数据包及附加信息(解码时间戳、显示时间戳、时长等),这样的媒体数据包所承载的每每不是原始格式的音视频数据,而是以某种方式编码后的数据,编码信息由对应的媒体流结构AVStream给出。AVPacket包含如下数据域:
AVPacket结构自己只是个容器,它使用data成员引用实际的数据缓冲区。这个缓冲区的管理方式有两种,其一是经过调用av_new_packet 直接建立缓冲区,其二是引用已经存在的缓冲区。缓冲区的释放经过调用av_free_packet实现,其内部实现也采用了两种不一样的释放方式,第一种方 式是调用AVPacket的destruct函数,这个destruct函数多是缺省的av_destruct_packet,对应 av_new_packet或av_dup_packet建立的缓冲区,也多是某个自定义的释放函数,表示缓冲区的提供者但愿使用者在结束缓冲区的时候 按照提供者指望的方式将其释放,第二种方式是仅仅将data和size的值清0,这种状况下每每是引用了一个已经存在的缓冲区,AVPacket的 destruct指针为空。
在使用AVPacket时,对于缓冲区的提供者,必须注意经过设置destruct函数指针指定正确的释放方式,若是缓冲区提供者打算本身释放缓冲区,则 切记将destruct置空;而对于缓冲区的使用者,务必在使用结束时调用av_free_packet释放缓冲区(虽然释放操做可能只是一个假动做)。 若是某个使用者打算较长时间内占用一个AVPacket——好比不打算在函数返回以前释放它——最好调用av_dup_packet进行缓冲区的克隆,将 其转化为自有分配的缓冲区,以避免对缓冲区的不当占用形成异常错误。av_dup_packet会为destruct指针为空的AVPacket新建一个缓 冲区,而后将原缓冲区的数据拷贝至新缓冲区,置data的值为新缓冲区的地址,同时设destruct指针为av_destruct_packet。
3、时间信息 / 多媒体同步
时间信息用于实现多媒体同步。
同步的目的在于展现多媒体信息时,可以保持媒体对象之间固有的时间关系。同步有两类,一类是流内同步,其主要任务是保证单个媒体流内的时间关系,以知足感 知要求,如按照规定的帧率播放一段视频;另外一类是流间同步,主要任务是保证不一样媒体流之间的时间关系,如音频和视频之间的关系(lipsync)。
对于固定速率的媒体,如固定帧率的视频或固定比特率的音频,能够将时间信息(帧率或比特率)置于文件首部(header),如AVI的hdrl List、MP4的moov box,还有一种相对复杂的方案是将时间信息嵌入媒体流的内部,如MPEG TS和Real video,这种方案能够处理变速率的媒体,亦可有效避免同步过程当中的时间漂移。
FFMPEG会为每个数据包打上时间标签,以更有效地支持上层应用的同步机制。时间标签有两种,一种是DTS,称为解码时间标签,另外一种是PTS,称为 显示时间标签。对于声音来讲 ,这两个时间标签是相同的,但对于某些视频编码格式,因为采用了双向预测技术,会形成DTS和PTS的不一致。
无双向预测帧的状况:
图像类型: I P P P P P P ... I P P DTS: 0 1 2 3 4 5 6... 100 101 102 PTS: 0 1 2 3 4 5 6... 100 101 102
有双向预测帧的状况:
图像类型: I P B B P B B ... I P B DTS: 0 1 2 3 4 5 6 ... 100 101 102 PTS: 0 3 1 2 6 4 5 ... 100 104 102
对于存在双向预测帧的状况,一般要求解码器对图像重排序,以保证输出的图像顺序为显示顺序:
解码器输入:I P B B P B B (DTS) 0 1 2 3 4 5 6 (PTS) 0 3 1 2 6 4 5 解码器输出:X I B B P B B P (PTS) X 0 1 2 3 4 5 6
时间信息的获取:
经过调用avformat_find_stream_info,多媒体应用能够从AVFormatContext对象中拿到媒体文件的时间信息:主要是总 时间长度和开始时间,此外还有与时间信息相关的比特率和文件大小。其中时间信息的单位是AV_TIME_BASE:微秒。