零基础学习视频解码之FFMpeg中比较重要的函数以及数据结构(转)

在正式开始解码练习前先了解下关于FFmpeg中比较重要的函数以及数据结构。

1. 数据结构: 

(1) AVFormatContext 

  AVFormatContext是一个贯穿始终的数据结构,很多函数都要用到它作为参数。FFmpeg代码中对这个数据结构的注释是:format I/O context 此结构包含了一个视频流的格式内容。其中存有了AVInputFormat(or AVOutputFormat同一时间AVFormatContext内只能存在其中一个),和AVStream、AVPacket这几个重要的数据结构以及一些其他的相关信息,比如title,author,copyright等。还有一些可能在编解码中会用到的信息,诸如:duration, file_size, bit_rate等。

  初始化: 由于AVFormatConext结构包含许多信息因此初始化过程是分步完成,而且有些变量如果没有值可用,也可不初始化。但是由于一般声明都是用指针因此一个分配内存过程不可少:

  

AVFormatContext *pFormatCtx;

pFormatCtx = avformat_alloc_context();

 

(2) AVOutputFormat 

  编解码器将要使用哪个codec的“指示”。

AVOutputFormat *fmt; 

fmt = guess_format(NULL, filename, NULL);

  根据filename来判断文件格式,同时也初始化了用什么编码器。当然,如果是用AVInputFormat *fmt的化,就是fix用什么解码器。(指定输出序列->fix编码器,指定输入序列->fix解码器)

(3) AVInputFormat

  从AVFormatContext中获取AVInputFormat

AVInputFormat *inputFormat;
inputFormat = pFormatCtx->iformat;

(4) AVCodecContext 

  此结构在Ffmpeg SDK中的注释是:main external api structure其重要性可见一斑。而且在avcodec它的定义处,对其每个成员变量,都给出了十分详细的介绍。应该说AVCodecContext的初始化是Codec使用中最重要的一环, 而且AVCodecContext是AVStream的一个成员结构。

(5) AVCodec 

  结构AVCodec中成员变量和成员函数比较少,但是很重要。他包含了CodecID,也就是用哪个Codec、  像素格式信息。还有前面提到过的5个函数(init、encode、close、decoder、flush)。AVCodec的初始化後的使用都是依附于AVCodecContex,前者是后者的成员。在AVCodecContext初始化後 ,AVCodec也就能很好的初始化了。

(6) AVFrame 

  AVFrame是作为一个描述“原始图像”(也就是YUV或是RGB…还有其他的吗?)的结构,他的头两个成员数据,uint8_t

*data[4],int linesize[4],第一个存放的是Y、Cb、Cr(yuv格式),linesize是啥?由这两个数据还能提取处另外一个数据结构:AVPicture。

  此外,AVFrame还含有其他一些成员数据,比如。是否key_frame、已编码图像书coded_picture_number、是否作为参考帧reference、宏块类型 *mb_type等等。

  AVFrame的初始化并没有他结构上看上去的那么简单。由于AVFrame还有一个承载图像数据的任务(data[4])因此,对他分配内存应该要小心完成。

(7) AVPacket 

  AVPacket的存在是作为写入文件的基本单元而存在的。我们可能会认为直接把编码后的比特流写入文件不就可以了,为什么还要麻烦设置一个AVPacket结构。在我看来这样的编码设置是十分有必要的,特别是在做视频实时传输,同步、边界问题可以通过AVPacket来解决。AVPacket的成员数据有两个时间戳、数据data(通常是编码后数据)、大小size等等(参见avformat.h 48行)。讲AVPacket的用法就不得不提到编解码函数,因为AVPacket的好些信息只有在编解码后才能的知。

(8) AVPicture

  AVPicture的存在有以下原因,AVPicture将Picture的概念从Frame中提取出来,就只由Picture(图片)本身的信息,亮度、色度和行大小。而Frame还有如是否是key frame之类的信息。这样的类似“分级”是整个概念更加清晰。 AVPacket作为将编码后数据写入文件的基本数据单元,他的单元大小、数据都是由AVPacket来的

(9) AVStream

  AVStream作为继AVFormatContext後第二个贯穿始终的结构是有其理由的。他的成员数据中有AVCodecContext这基本的上是对所使用的Video Codec的参数进行设定的(包括bit rate、分辨率等重要信息)。同时作为“Stream”,它包含了“流”

  这个概念中的一些数据,比如:帧率(r_frame_rate)、基本时间计量单位(time_base)、(需要编解码的)首帧位置(start_time)、持续时间(duration)、帧数(nb_frames)以及一些ip信息。当然后面的这些信息中有些不是必须要初始化的,但是AVCodecContex是一定要初始化的,而且就是作为初始化AVStream最重要的一个部分。

  以上是FFMpeg中比较重要的数据结构。下面的这个生成关系理一下思路:(->表示 派生出)

  AVFormatContext->AVStream->AVCodecContext->AVCodec

  |

  AVOutputFormat or AVInputFormat

  AVFrame->AVPicture….>AVPacket

2.FFMpeg 中的函数:

  FFMpeg SDK提供了许多初始化函数和编码函数。我们要做的就是对主要数据结构正确的初始化,以及正确使用相应的编解码函数以及读写(I/O)操作函数。作为一个整体化的代码SDK,FFMpeg有一些他自己的标准化使用过程。比如函数av_register_all(); 就是一个最开始就该调用的“注册函数”,他初始化了libavcodec,“注册”了所有的的codec和视频文件格式(format)。

  (1). av_register_all (); 

    usage: initialize ibavcoded, and register all codecs and formats

    每个使用FFMpeg SDK的工程都必须调用的函数。进行codec和format的注册,然后才能使用。

(2). AVFormatContext *avformat_alloc_context(void);

    usage: allocate the output media context.实际是初始化AVFormatContext的成员数据AVClass:

  (3).void av_dump_format(AVFormatContext *ic, int index, const char *url, int is_output); 

    usage: 这一步会用有效的信息把 AVFormatContext 的流域(streams field)填满。作为一个可调试的诊断,我们会将这些信息全盘输出到标准错误输出中,不过你在一个应用程序的产品中并不用这么做:

  (4).int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options);

    usage:打开一个视频文件

  (5).int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);

    usage:获取视频文件的流信息

  (6).AVCodec *avcodec_find_decoder(enum AVCodecID id);

    usage:获取视频编码格式

  (7).int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);

    usage:用一个编码格式打开一个编码文件

  (8).int av_read_frame(AVFormatContext *s, AVPacket *pkt);

    usage:从frame中读取packet

  (9).int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, const AVPacket *avpkt);

    usage:解码声音

所以解码流程如下:

  所以解码流程为:注册所有格式->初始化AVFormatContext->打开一个视频文件->获取视频文件的流信息->获取初始的视频流->获得视频流编码内容->获得音频流编码内容->获取视频编码格式->获取音频编码格式->用一个编码格式打开一个编码文件->从frame中读取packet->解码视频->解码音频->释放packet->关闭解码器->关闭AVFormatContext

  解码流程函数:av_register_all()->avformat_alloc_context()->avformat_open_input()->avformat_find_stream_info()->avcodec_find_decoder()->avcodec_open2()->av_new_packet()->av_read_frame()->avcodec_decode_video2()-->avcodec_decode_audio4()->av_free_packet()->avcodec_close()->avformat_close_input()

http://www.cnblogs.com/tanlon/p/3879081.html

时间: 2024-12-16 10:40:00

零基础学习视频解码之FFMpeg中比较重要的函数以及数据结构(转)的相关文章

[原]零基础学习视频解码之FFMpeg中比较重要的函数以及数据结构

在正式开始解码练习前先了解下关于FFmpeg中比较重要的函数以及数据结构. 1. 数据结构:  (1) AVFormatContext  AVFormatContext是一个贯穿始终的数据结构,很多函数都要用到它作为参数.FFmpeg代码中对这个数据结构的注释是:format I/O context 此结构包含了一个视频流的格式内容.其中存有了AVInputFormat(or AVOutputFormat同一时间AVFormatContext内只能存在其中一个),和AVStream.AVPack

[原]零基础学习视频解码系列文章

注:本系列文章的开发环境:Ubuntu 14.04+Eclipse4.3.2+CDT+FFmpeg2.3+SDL1.25 [原]零基础学习视频解码之安装ffmpeg [原]零基础学习视频解码之FFMpeg中比较重要的函数以及数据结构 [原]零基础学习视频解码之解码图像 [原]SDL开发教程 [原]零基础学习视频解码之解码声音 [原]零基础学习视频解码之视频线程 [原]零基础学习视频解码之同步视频 [原]零基础学习视频解码之同步音频 [原]零基础学习视频解码之seek [原]零基础学习视频解码之后

[原]零基础学习视频解码之安装ffmpeg

写在文章前面:ffmpeg是一个开源的编解码框架,拥有很强大的功能.但是对于如果使用其来做开发呈现着严重两极分化,大神们讨论着高深的问题,大多数像我这样的小白连门都进不去.最近无意间领会了如何入门,现在写下这个系列文章<零基础学习视频解码>用来帮大家提供入门基础.博主的开发机器是基于Ubuntu 14.04 64位的,所以这个系列的文章都是在Ubuntu下完成的. 一.安装SDL C语言没有图形库,其中SDL比较小巧,并且是开源的,适合入门者学习.另外安装ffmpeg的时候会检测是否安装SDL

[原]零基础学习视频解码之后记

嘿嘿,在此之前从来没有用c写个一个简单的demo,最多也是用c写写数据结构练习题什么的,通过这个学习了解了很多以前不了解的东西. 本人比较懒,做什么事情都是只有三分钟热度,但是一直对ffmpeg解码向往而入门不得.<零基础学习视频解码>系列文章严格意义上来说不算是原创,我无非是将按照http://dranger.com/ffmpeg/这个介绍在Ubuntu 14.04上面用Eclipse+CDT插件去实现了一遍,原文中的很多接口在ffmpeg2.3上面变了,有些接口甚至被删除了,这导致大多数情

[原]零基础学习视频解码之seek

现在,我们要添加一些功能,当你看不能倒带的电影,是不是很烦? 那么函数av_seek_frame功能看起来是多么赏心悦目. 我们将让左,右箭头来回走在影片中通过一个小的向上和向下箭头很多,其中“三多一少”是10秒,“很多”为60秒.因此,我们需要设置我们的主循环,用来捕获击键.然而,当我们得到一个按键,就不能直接称之为函数av_seek_frame.我们所要做的是在我们的主解码循环中,decode_thread循环做相应的处理. 为了检测按键,我们先来看看,看看我们得到了一个SDL_KEYDOW

[原]零基础学习视频解码之同步视频

来源:http://www.cnblogs.com/tanlon/p/3893540.html?utm_source=tuicool&utm_medium=referral

[原]基础学习视频解码之视频线程

在上两篇文章[原]零基础学习视频解码之解码图像和[原]零基础学习视频解码之解码声音我们初步了解如何解码视频图像和视频声音.但是这些都是初步简单的解码出来而已,我们的主要功能是处理非常多:它是通过事件循环中运行,读取数据包,并在视频解码.所以,我们要做的就是拆分这些功能:我们将有一个线程,该线程将负责数据包进行解码;这些数据包将被添加到该队列中,并通过相应的音频和视频解码线程读取. 音频线:我们在上一篇已经建立了我们想要的方式; 视频线:视频线会相对比较麻烦一些,因为我们要自己显示自己的视频画面.

salesforce零基础学习(八十七)Apex 中Picklist类型通过Control 字段值获取Dependent List 值

注:本篇解决方案内容实现转自:http://mysalesforceescapade.blogspot.com/2015/03/getting-dependent-picklist-values-from.html 群里面有个小伙伴问了一个关于两个有Dependence关系的Picklist字段如何在Apex中通过control字段的值获取到Dependence字段的值,针对Salesforce配置来说,我们很好配置出两个Dependence字段的关系,通过点击设置一下include关系即可.如

[原]基础学习视频解码之同步视频

在前面几章,我们了解了视频解码的原理,了解了音频解码的原理,也将视频和音频分别放在了相应的解码线程中去了.所以这整个过程中,我们有一个基本无用的电影播放器.它可以播放视频,它也可以播放音频,但是这个并不完整,因为音频和视频并不同步,我们接下来要做的就是将音频和视频同步起来. 音频流有一个采样率,并且视频流具有每秒值的帧.但是,如果我们只是靠只是计算帧和帧速率乘以同步视频,有的情况下,它会声画不同步的. 当我们从av_read_frame()的数据包,它包含了这个包里面的信息的PTS和DTS值.但