标签:
来源:http://blog.csdn.net/chance_yin/article/details/10323441
一、研究数字多媒体,首先要了解几个基本术语(ffmpeg的相关文档几乎都是英文的,不弄懂几个基本术语看文档还是比较吃力的)
1、容器/文件 (Container/file) ,既多媒体源文件
2、媒体流(Stream):与时间相关的一段连续数据。既某一时刻对应某个数据,这样的多个连续数据组在一起就成了媒体流。
3、数据帧/数据包(Frame/Packet):一个媒体流由大量的数据帧构成。数据帧也是编解码器最小的处理单元。
二、FFmpeg 基础---FFmpeg中重要的几个数据结构
1、AVCodecContext,这是一个描述编解码器上下文的数据结构,包含了众多编解码器需要的参数信息
如果是单纯使用libavcodec,这部分信息需要调用者进行初始化;如果是使用整个FFMPEG库,这部分信息在调用 avformat_open_input和avformat_find_stream_info的过程中根据文件的头信息及媒体流内的头部信息完成初始 化。其中几个主要域的释义如下:
2、AVStream 该结构体描述一个媒体流
主要域的释义如下,其中大部分域的值可以由avformat_open_input根据文件头的信息确定,缺少的信息需要通过调用avformat_find_stream_info读帧及软解码进一步获取:
3、AVFormatContext,这个结构体描述了一个媒体文件或媒体流的构成和基本信息
这是FFMpeg中最为基本的一个结构,是其他所有结构的根,是一个多媒体文件或流的根本抽象。其中:
通常,这个结构由avformat_open_input在内部创建并以缺省值初始化部分成员。但是,如果调用者希望自己创建该结构,则需要显式为该结构的一些成员置缺省值——如果没有缺省值的话,会导致之后的动作产生异常。以下成员需要被关注:
4、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。
三、时间信息 / 多媒体同步
时间信息用于实现多媒体同步。
同步的目的在于展示多媒体信息时,能够保持媒体对象之间固有的时间关系。同步有两类,一类是流内同步,其主要任务是保证单个媒体流内的时间关系,以满足感 知要求,如按照规定的帧率播放一段视频;另一类是流间同步,主要任务是保证不同媒体流之间的时间关系,如音频和视频之间的关系(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:微秒。
标签:
原文地址:http://www.cnblogs.com/sunminmin/p/4976297.html