ffmpga结构体和常用函数(总结)

  模块:

    libavcodec    - 编码解码器
        libavdevice   - 输入输出设备的支持
        libavfilter   - 视音频滤镜支持
        libavformat   - 视音频等格式的解析
        libavutil     - 工具库
        libpostproc   - 后期效果处理
        libswscale    - 图像颜色、尺寸转换

1. ffmpga代码简析

 

1.2 源码——通用部分

(1). av_register_all (),     avcodec_register_all ()

  avcodec_register_all() : 注册 hwaccel,encoder,decoder,parser,bitstream
    av_register_all() : 注册 muxer,demuxer,protocol,在所有基于ffmpeg的应用程序中几乎第一个被调用的。只有调用了该函数,才能使用复用器,编码器等
    avfilter_register_all() : 注册 滤镜filter

(2).内存分配:av_malloc(),av_realloc(),av_mallocz(),av_calloc(),av_free(),av_freep()

  内存操作常见函数位于  libavutil\mem.中:

av_malloc()——简单封装了系统的malloc(),并做错误检查工作;

av_realloc()——简单封装了系统的realloc(),用于对申请的内存大小进行调整;

av_mallocz()——av_mallocz()中调用了av_malloc()之后,又调用memset()将分配的内存设置为0

av_calloc()——简单封装了av_mallocz();

av_freep()——释放申请的内存;

av_freep()——简单封装了av_free(),并且在释放内存之后将目标指针设置为null。

 

(3).ffmpeg结构体

a) 解协议(http,rtsp,rtmp,mms)

AVIOContext,URLProtocol,URLContext 主要存储视音频使用的协议的类型以及状态。URLProtocol存储输入视音频使用的封装格式。每种协议都对应一个URLProtocol结构。(注 意:FFMPEG中文件也被当做一种协议“file”)

b)解封装(flv,avi,rmvb,mp4)

AVFormatContext主要存储视音频封装格式中包含的信息;AVInputFormat存储输入视音频使用的封装格式。每种视音频封装格式都对应一个AVInputFormat 结构。

c) 解码(h264,mpeg2,aac,mp3)

每个AVStream存储一个视频/音频流的相关数据;每个AVStream对应一个AVCodecContext,存储该视频/音频流使用解码方式的相关数据;每个AVCodecContext中对应一个AVCodec,包含该视频/音频对应的解码器。每种解码器都对应一个AVCodec结构。

d) 存数据

视频的话,每个结构一般是存一帧;音频可能有好几帧

解码前数据:AVPacket

解码后数据:AVFrame

 

AVFormatContext:统领全局的基本结构体。主要用于处理封装格式(FLV/MKV/RMVB等)

AVIOContext:输入输出对应的结构体,用于输入输出(读写文件,RTMP协议等)。

AVStream,AVCodecContext:视音频流对应的结构体,用于视音频编解码。

AVFrame:存储非压缩的数据(视频对应RGB/YUV像素数据,音频对应PCM采样数据)

AVPacket:存储压缩数据(视频对应H.264等码流数据,音频对应AAC/MP3等码流数据)

 

<1>. AVFormatContext是一个贯穿始终的数据结构,很多函数都要用到它作为参数。它是FFMPEG解封装(flv,mp4,rmvb,avi)功能的结构体。下面看几个主要变量的作用(在这里考虑解码的情况):

struct AVInputFormat *iformat:输入数据的封装格式

AVIOContext *pb:输入数据的缓存

unsigned int nb_streams:视音频流的个数

AVStream **streams:视音频流

char filename[1024]:文件名

int64_t duration:时长(单位:微秒ms,转换为秒需要除以1000000)

int bit_rate:比特率(单位bps,转换为kbps需要除以1000)

AVDictionary *metadata:元数据

 <2>. AVFrame结构体一般用于存储原始数据(即非压缩数据,例如对视频来说是YUV,RGB,对音频来说是PCM),此外还包含了一些相关的信息。比如 说,解码的时候存储了宏块类型表,QP表,运动矢量表等数据。编码的时候也存储了相关的数据。因此在使用FFMPEG进行码流分析的时候,AVFrame 是一个很重要的结构体。下面看几个主要变量的作用(在这里考虑解码的情况):

  uint8_t *data[AV_NUM_DATA_POINTERS]:解码后原始数据(对视频来说是YUV,RGB,对音频来说是PCM)

  int linesize[AV_NUM_DATA_POINTERS]:data中“一行”数据的大小。注意:未必等于图像的宽,一般大于图像的宽。

  int width, height:视频帧宽和高(1920x1080,1280x720...)

  int nb_samples:音频的一个AVFrame中可能包含多个音频帧,在此标记包含了几个

  int format:解码后原始数据类型(YUV420,YUV422,RGB24...)

  int key_frame:是否是关键帧

  enum AVPictureType pict_type:帧类型(I,B,P...)

  AVRational sample_aspect_ratio:宽高比(16:9,4:3...)

  int64_t pts:显示时间戳

  int coded_picture_number:编码帧序号

  int display_picture_number:显示帧序号

  int8_t *qscale_table:QP表

  uint8_t *mbskip_table:跳过宏块表

  int16_t (*motion_val[2])[2]:运动矢量表

  uint32_t *mb_type:宏块类型表

  short *dct_coeff:DCT系数,这个没有提取过

  int8_t *ref_index[2]:运动估计参考帧列表(貌似H.264这种比较新的标准才会涉及到多参考帧)

  int interlaced_frame:是否是隔行扫描

  uint8_t motion_subsample_log2:一个宏块中的运动矢量采样个数,取log的

<3>.AVCodecContext,主要的外部API结构体,这个结构体主要用在编解码过程中,而且,编码过程中用到本结构体的参数比解码用到的参数多

enum AVMediaType codec_type:编解码器的类型(视频,音频...)

struct AVCodec  *codec:采用的解码器AVCodec(H.264,MPEG2...)

int bit_rate:平均比特率

uint8_t *extradata; int extradata_size:针对特定编码器包含的附加信息(例如对于H.264解码器来说,存储SPS,PPS等)

AVRational time_base:根据该参数,可以把PTS转化为实际的时间(单位为秒s)

int width, height:如果是视频的话,代表宽和高

int refs:运动估计参考帧的个数(H.264的话会有多帧,MPEG2这类的一般就没有了)

int sample_rate:采样率(音频)

int channels:声道数(音频)

enum AVSampleFormat sample_fmt:采样格式

int profile:型(H.264里面就有,其他编码标准应该也有)

int level:级(和profile差不太多)

<4>.AVIOContext,管理输入输出数据的结构体

unsigned char *buffer:缓存开始位置

int buffer_size:缓存大小(默认32768)

unsigned char *buf_ptr:当前指针读取到的位置

unsigned char *buf_end:缓存结束的位置

void *opaque:URLContext结构体

在解码的情况下,buffer用于存储ffmpeg读入的数据。例如打开一个视频文件的时候,先把数据从硬盘读入buffer,然后在送给解码器用于解码。

其中opaque指向了URLContext。注意,这个结构体并不在FFMPEG提供的头文件中,而是在FFMPEG的源代码中。

<5>.AVCodec是存储编解码器信息的结构体

const char *name:编解码器的名字,比较短

const char *long_name:编解码器的名字,全称,比较长

enum AVMediaType type:指明了类型,是视频,音频,还是字幕

enum AVCodecID id:ID,不重复

const AVRational *supported_framerates:支持的帧率(仅视频)

const enum AVPixelFormat *pix_fmts:支持的像素格式(仅视频)

const int *supported_samplerates:支持的采样率(仅音频)

const enum AVSampleFormat *sample_fmts:支持的采样格式(仅音频)

const uint64_t *channel_layouts:支持的声道数(仅音频)

int priv_data_size:私有数据的大小

<6>.AVStream是存储每一个视频/音频流信息的结构体

  int index:标识该视频/音频流

  AVCodecContext *codec:指向该视频/音频流的AVCodecContext(它们是一一对应的关系)

  AVRational time_base:时基。通过该值可以把PTS,DTS转化为真正的时间。FFMPEG其他结构体中也有这个字段,但是根据我的经验,  只有AVStream中的time_base是可用的。PTS*time_base=真正的时间

  int64_t duration:该视频/音频流长度

  AVDictionary *metadata:元数据信息

  AVRational avg_frame_rate:帧率(注:对视频来说,这个挺重要的)

  AVPacket attached_pic:附带的图片。比如说一些MP3,AAC音频文件附带的专辑封面。

<7>. AVPacket存储压缩编码数据相关信息的结构体,暂存解复用之后、解码之前的媒体数据(一个音/视频帧、一个字幕包等)及附加信息(解码时间戳、显示时间戳、时长等)

  uint8_t *data:压缩编码的数据。

  例如对于H.264来说。1个AVPacket的data通常对应一个NAL。

  注意:在这里只是对应,而不是一模一样。他们之间有微小的差别:使用FFMPEG类库分离出多媒体文件中的H.264码流

  因此在使用FFMPEG进行视音频处理的时候,常常可以将得到的AVPacket的data数据直接写成文件,从而得到视音频的码流文件。

  int   size:data的大小

  int64_t pts:显示时间戳

  int64_t dts:解码时间戳

  int   stream_index:标识该AVPacket所属的视频/音频流。

》》》结构体关系

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 1). 红色字体的first_protocol first_iformat first_avcodec, 这三个不同的头指针,分别为ffmpeg支持 不同的数据源、不同格式以及不同编码的音视频数据提供了处理的可能。

 

 2). ffplay主要划分为四大部分: 数据源, 解复用, 解码, 显示播放. ffplay使用SDL库进行视频显示和声音播放,至于同步在ffplay中自个做的.

 

  首先, 谈谈数据源相应的数据结构: URLContext, ByteIOContext. 这两个与音视频数据相关, URLProtocol体现在功能函数上. 上图中, URLContext的 void *priv_data 指向了FILE结构体, 其实这是作者的一点点失误,ffmpeg使用的是c的底层io, 没有使用stdio. c底层io是不带缓存的, 所以加上了ByteIOContext为无缓冲io提供缓存, 避免频繁的进行i/o操作.

 

  其次, 解复用对应的数据结构: AVFormatContext中的void *priv_data字段, AVStream, AVStream中void *priv_data结合AVInputeFormat的使用, 从下一层的ByteIOContext的buffer中将音视频数据分离.

 

  最后, 解码对应的数据结构: AVCodecContext, AVCodec体现在功能函数上, 其中AVCodecContext的void *priv_data字段是特定的decodec.

 

  数据源 --> char *buffer --> 解复用 --> AVPacket(音频包, 视频包) --> 解码 --> AVFrame(video) / audio_buffer(audio).

 

 3). first_protocol将file, tcp, udp, rtp...数据当成协议看待, 各自均提供URLProtocol结构体实例以功能函数的形式进行体现. first_iformat将ffmpeg所支持的所有格式串连到一起, first_avcodec将ffmpeg支持的所有编码器串连到一起.

 

  三个指针链表是如何确定相应实例的呢?

 

  a. (first_protocol, argv[1]参数) 参数例如: file://pathname/filename 协议: file, 默认也为file; rtsp://ip_address/filename 协议:rtsp

 

  b. (first_iformat, is->iformat->read_probe())  

 

  c. (first_avcodec, is->iformat->read_head())

 

 

(4). avio_open2()

该函数用于打开FFmpeg的输入输出文件。avio_open2()的声明位于libavformat\avio.h文件中 int avio_open2(AVIOContext **s, const char *url, int flags,  const AVIOInterruptCB *int_cb, AVDictionary **options) 

  s:函数调用成功之后创建的AVIOContext结构体。
  url:输入输出协议的地址(文件也是一种“广义”的协议,对于文件来说就是文件的路径)。
  flags:打开地址的方式。AVIO_FLAG_READ:只读;AVIO_FLAG_WRITE:只写;AVIO_FLAG_READ_WRITE:读写。                                                

(5). avcodec_find_encoder()和avcodec_find_decoder() 

查找编码器 和解码器,实质就是遍历AVCodec链表并且获得符合条件的元素,声明位于libavcodec\avcodec.h:

  AVCodec *avcodec_find_encoder(enum AVCodecID id);

  AVCodec *avcodec_find_decoder(enum AVCodecID id);

 

 

 

(6). avcodec_open2()

初始化一个视音频编解码器的AVCodecContext。avcodec_open2()的声明位于libavcodec\avcodec.h

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

  avctx:需要初始化的AVCodecContext;
  codec:输入的AVCodec;
  options:一些选项。例如使用libx264编码的时候,“preset”,“tune”等都可以通过该参数设置

avcodec_open2() 函数的主要工作:

  1)为各种结构体分配内存(通过各种av_malloc()实现)
  2)将输入的AVDictionary形式的选项设置到AVCodecContext
  3)其他一些零零碎碎的检查,比如说检查编解码器是否处于“实验”阶段
  4)如果是编码器,检查输入参数是否符合编码器的要求
  5)调用AVCodec的init()初始化具体的解码器。

 

(7). avcodec_close()

该函数用于关闭编码器。avcodec_close()函数的声明位于libavcodec\avcodec.h

int avcodec_close(AVCodecContext *avctx);

 

1.3 源码——解码部分

(1). avformat_open_input()

打开媒体的过程开始于avformat_open_input(),完成:

1).输入输出结构体AVIOContext的初始化;

2).输入数据的协议(例如RTMP,或者file)的识别(通过一套评分机制):

  判断文件名的后缀  + 读取文件头的数据进行比对

使用获得最高分的文件协议对应的URLProtocol,通过函数指针的方式,与

FFMPEG连接(非专业用词);

3).剩下的就是调用该URLProtocol的函数进行open,read等操作了

 

(2). avformat_close_input()

用于打开一个AVFormatContext,一般情况下是和avformat_open_input()成对使用的;

avformat_close_input()的声明位于libavformat\avformat.h:        void avformat_close_input(AVFormatContext **s);

函数功能:

  1)调用AVInputFormat的read_close()方法关闭输入流
  2)调用avformat_free_context()释放AVFormatContext
  3)调用avio_close()关闭并且释放AVIOContext

 

(3). avformat_find_stream_info()

 

该函数可以读取一部分视音频数据并且获得一些相关的信息。avformat_find_stream_info()的声明位于libavformat\avformat.h:

int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);     函数正常执行后返回值大于等于0;

  c:输入的AVFormatContext
  options:额外的选项

功能:

该函数主要用于给每个媒体流(音频/视频)的AVStream结构体赋值。它其实已经实现了解码器的查找,解码器的打开,视音频帧的读取,视音频帧的解码等工作。换句话说,该函数实际上已经“走通”的解码的整个流程。下面看一下除了成员变量赋值之外,该函数的几个关键流程:

  1).查找解码器:find_decoder()
  2).打开解码器:avcodec_open2()
  3).读取完整的一帧压缩编码的数据:read_frame_internal() 注:av_read_frame()内部实际上就是调用的read_frame_internal()。
  4).解码一些压缩编码数据:try_decode_frame()

 

(4). av_read_frame()

读取码流中的音频若干帧或者视频一帧。例如,解码视频的时候,每解码一个视频帧,需要先调用 av_read_frame()获得一帧视频的压缩数据,然后才能对该数据进行解码(例如H.264中一帧压缩数据通常对应一个NAL)。

 先参考了其他人对av_read_frame()的解释,在此做一个参考:通过av_read_packet(***),读取一个包,需要说明的是此函数必须是包含整数帧的,不存在半帧的情况,以ts流为例,是读取一个完整的 PES包(一个完整pes包包含若干视频或音频es包),读取完毕后,通过av_parser_parse2(***)分析出视频一帧(或音频若干帧), 返回,下次进入循环的时候,如果上次的数据没有完全取完,则st = s->cur_st;不会是NULL,即再此进入av_parser_parse2(***)流程,而不是下面的 av_read_packet(**)流程,这样就保证了,如果读取一次包含了N帧视频数据(以视频为例),则调用 av_read_frame(***)N次都不会去读数据,而是返回第一次读取的数据,直到全部解析完毕。

 注意av_read_frame - 新版本的ffmpeg用的是av_read_frame,而老版本的是av_read_packet ,区别是av_read_packet读出的是包,它可能是半帧或多帧,不保证帧的完整性。av_read_frame对 av_read_packet进行了封装,使读出的数据总是完整的帧   

av_read_frame()的声明位于libavformat\avformat.h:   int av_read_frame(AVFormatContext *s, AVPacket *pkt);

  s:输入的AVFormatContext

  pkt:输出的AVPacket/* 

 

(5). avcodec_decodec_video2()

解码一帧视频数据。输入一个压缩编码的结构体AVPacket,输出一个解码后的结构体AVFrame。该函数的声明位于libavcodec\avcodec.h,

int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, const AVPacket *avpkt);

功能:

 1)对输入的字段进行了一系列的检查工作:例如宽高是否正确,输入是否为视频等等。

 2)通过ret = avctx->codec->decode(avctx, picture, got_picture_ptr,&tmp)这句代码,调用了相应AVCodec的decode()函数,完成了解码操作。      AVCodec的decode()方法是一个函数指针,指向了具体解码器的解码函数

   3)对得到的AVFrame的一些字段进行了赋值,例如宽高、像素格式等等。

 

(6). avformat_close_input()

关闭一个AVFormatContext,一般情况下是和avformat_open_input()成对使用的。声明位于libavformat\avformat.h

  void avformat_close_input(AVFormatContext   **s);

功能:

  1)调用AVInputFormat的read_close()方法关闭输入流
  2)调用avformat_free_context()释放AVFormatContext
  3)调用avio_close()关闭并且释放AVIOContext

 

1.4 源码——编码部分

(1). avformat_alloc_output_context2()

在基于FFmpeg的视音频编码器程序中,该函数通常是第一个调用的函数(除了组件注册函数av_register_all())。 avformat_alloc_output_context2()函数可以初始化一个用于输出的AVFormatContext结构体。它的声明位于 libavformat\avformat.h

int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat,  const char *format_name, const char *filename);
  ctx:函数调用成功之后创建的AVFormatContext结构体。
  oformat:指定AVFormatContext中的AVOutputFormat,用于确定输出格式。如果指定为NULL,可以设定后两个参数(format_name或者filename)由              FFmpeg猜测输出格式。
  PS:使用该参数需要自己手动获取AVOutputFormat,相对于使用后两个参数来说要麻烦一些。
  format_name:指定输出格式的名称。根据格式名称,FFmpeg会推测输出格式。输出格式可以是“flv”,“mkv”等等。
  filename:指定输出文件的名称。根据文件名称,FFmpeg会推测输出格式。文件名称可以是“xx.flv”,“yy.mkv”等等。

函数执行成功的话,其返回值大于等于0。

 

(2). avformat_write_header()

av_write_frame()用于写视频数据,avformat_write_header()用于写视频文件头,而av_write_trailer()用于写视频文件尾。

avformat_write_header()的声明位于libavformat\avformat.h ,int avformat_write_header(AVFormatContext *s, AVDictionary **options);

   s:用于输出的AVFormatContext;

options:额外的选项;           函数正常执行后返回值等于0。                                           

功能:

   1)调用init_muxer()初始化复用器
   2)调用AVOutputFormat的write_header()

 

(3). avcodec_encode_video2()

编码一帧视频数据。avcodec_encode_video2()函数的声明位于libavcodec\avcodec.h
int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr); 

avctx:编码器的AVCodecContext。
avpkt:编码输出的AVPacket。
frame:编码输入的AVFrame。
got_packet_ptr:成功编码一个AVPacket的时候设置为1。

函数返回0代表编码成功

 

(4).av_write_frame()

输出一帧视音频数据,它的声明位于libavformat\avformat.h:   int av_write_frame(AVFormatContext *s, AVPacket *pkt);

s:用于输出的AVFormatContext。
pkt:等待输出的AVPacket。

函数正常执行后返回值等于0。

 

(5). av_write_trailer()

av_write_trailer()用于输出文件尾,它的声明位于libavformat\avformat.h:  int av_write_trailer(AVFormatContext *s);

  它只需要指定一个参数,即用于输出的AVFormatContext。
函数正常执行后返回值等于0。

 

1.5 源码——其他部分

(1). av_log()日志输出系统

av_log()是FFmpeg中输出日志的函数。一般情况下FFmpeg类库的源代码中是不允许使用printf()这种的函数的,所有的输出一律使用av_log()。

av_log()的声明位于libavutil\log.h:  void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4); 

  1)函数最后一个参数是“…”。
  在C语言中,在函数参数数量不确定的情况下使用“…”来代表参数。例如printf()的原型定义如下:  int printf (const char*, ...);  

  2)它的声明后面有一个av_printf_format(3, 4)。有关这个地方的左右还没有深入研究,网上资料中说它的作用是按照printf()的格式检查av_log()的格式。

avcl:指定一个包含AVClass的结构体。
level:log的级别
fmt:和printf()一样。

由此可见,av_log()和printf()的不同主要在于前面多了两个参数。其中第一个参数指定该log所属的结构体,例如 AVFormatContext、AVCodecContext等等。第二个参数指定log的级别,源代码中定义了如下几个级别 AV_LOG_PANIC ,AV_LOG_FATAL,AV_LOG_ERROR,AV_LOG_WARNING,AV_LOG_INFO AV_LOG_VERBOSE,AV_LOG_DEBUG。 每个级别定义的数值代表了严重程度,数值越小代表越严重。默认的级别是AV_LOG_INFO。此外,还有一个级别不输出任何信息,即 AV_LOG_QUIET。当前系统存在着一个“Log级别”。所有严重程度高于该级别的Log信息都会输出出来。例如当前的Log级别是 AV_LOG_WARNING,则会输出AV_LOG_PANIC,AV_LOG_FATAL,AV_LOG_ERROR,AV_LOG_WARNING 级别的信息,而不会输出AV_LOG_INFO级别的信息。可以通过av_log_get_level()获得当前Log的级别,通过另一个函数 av_log_set_level()设置当前的Log级别。

 

(2). AVClass ,AVOption 结构体成员管理系统

AVOption ——描述结构体中的成员变量,它最主要的作用可以概括为两个字:“赋值”。一个AVOption结构体包含了变量名称,简短的帮助,取值等等信息。

AVClass——和AVOption有关的数据都存储在AVClass结构体中, 一个结构体若要支持AVOption ,第一个成员变量是指向AVclass结构体的指针

该AVClass中的成员变量option必须指向一个AVOption类型的静态数组。

 

AVOption:用来设置FFmpeg中变量的值的结构体AVOption的特点就在于它赋值时候的灵活性。AVOption可以使用字符串为任何类型的变量赋值。

统一使用字符串赋值。例如给int型变量qp设定值为20,通过 AVOption需要传递进去一个内容为“20”的字符串。
此外,AVOption中变量的名称也使用字符串来表示。结合上面提到的使用字符串赋值的特性,我们可以发现使用AVOption之后,

传递两个字符串(一个是变量的名称,一个是变量的值)就可以改变系统中变量的值。

AVClass:AVClass最主要的作用就是给结构体(例如AVFormatContext等)增加AVOption功能的支持。换句话说AVClass就是AVOption和目标结构体之间的“桥     梁”。AVClass要求必须声明为目标结构体的第一个量。 AVClass中有一个option数组用于存储目标结构体的所有的AVOption。

举个例子,AVFormatContext结构体,AVClass和AVOption之间

    图中AVFormatContext结构体的第一个变量为AVClass类型的指针av_class,它在AVFormatContext结构体初始化的时候,被赋值指向了全局静态变量av_format_context_class结构体(定义位于libavformat\options.c)。而 AVClass类型的av_format_context_class结构体中的option变量指向了全局静态数组 avformat_options(定义位于libavformat\options_table.h。

 

AVOption的几个成员变量:

name:名称。
help:简短的帮助。
offset:选项相对结构体首部地址的偏移量(这个很重要)。
type:选项的类型。              (AVOptionType类型的变量AVOptionType是一个枚举类型
default_val:选项的默认值,(union类型的变量)
min:选项的最小值。
max:选项的最大值。
flags:一些标记。
unit:该选项所属的逻辑单元,可以为空。

AVClass的几个成员变量:

  class_name:AVClass名称。
  item_name:函数,获取与AVClass相关联的结构体实例的名称。
  option:AVOption类型的数组(最重要)。
  version:完成该AVClass的时候的LIBAVUTIL_VERSION。
  category:AVClass的类型,是一个类型为AVClassCategory的枚举型变量。

 

(3). sws_getContext() 初始化一个SwsContext

图像处理(缩放,YUV/RGB格式转换)类库libswsscale:libswscale是一个主要用于处理图片像素数据的类库,可以完成图片像素格式的转换,图片的拉伸等工作

ibswscale常用的函数数量很少,一般情况下就3个:

sws_getContext():初始化一个SwsContext。

sws_scale():处理图像数据。

sws_freeContext():释放一个SwsContext。

其中sws_getContext()也可以用sws_getCachedContext()取代。

 


  libswscale处理数据有两条最主要的方式:unscaled和scaled。unscaled用于处理不需要拉伸的像素数据(属于比较特殊 的情况),scaled用于处理需要拉伸的像素数据。Unscaled只需要对图像像素格式进行转换;而Scaled则除了对像素格式进行转换之外,还需 要对图像进行缩放。Scaled方式可以分成以下几个步骤:

  • XXX to YUV Converter:首先将数据像素数据转换为8bitYUV格式;
  • Horizontal scaler:水平拉伸图像,并且转换为15bitYUV;
  • Vertical scaler:垂直拉伸图像;
  • Output converter:转换为输出像素格式。

 

 

 

sws_getContext()是初始化SwsContext的函数。sws_getContext()的声明位于libswscale\swscale.h:

    1. struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,  
    2.                                   int dstW, int dstH, enum AVPixelFormat dstFormat,  
    3.                                   int flags, SwsFilter *srcFilter,  
    4.                                   SwsFilter *dstFilter, const double *param);

srcH:源图像的高
srcFormat:源图像的像素格式
dstW:目标图像的宽
dstH:目标图像的高
dstFormat:目标图像的像素格式
flags:设定图像拉伸使用的算法   成功执行的话返回生成的SwsContext,否则返回NULL

 

(4). sws_scale()

用于转换像素的函数,声明位于:libswscale\swscale.

int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],

          const int srcStride[], int srcSliceY, int srcSliceH,  uint8_t *const dst[], const int dstStride[]);

 

(5). avdevice_register_all() 注册设备的函数

  在使用libavdevice之前,必须先运行avdevice_register_all()对设备进行注册,否则就会出错。 avdevice_register_all()的注册方式和av_register_all()、avcodec_register_all()这几个函数是类似的

  avdevice_register_all()调用3个函数进行设备组建的注册:REGISTER_INDEV(),REGISTER_OUTDEV(),REGISTER_INOUTDEV()。上述3个函数实际上是预定义的3个宏:
REGISTER_INDEV():注册输入设备。实际上调用了av_register_input_format()将输入设备注册成一个AVInputFormat。
REGISTER_OUTDEV():注册输出设备。实际上调用了av_register_output_format()将输出设备注册成一个AVOutputFormat。
REGISTER_INOUTDEV():注册输入设备和输出设备。实际上将上述两个宏定义合并了。

 

 

1.6  编译

(1).  Makefile  文件

FFmpeg中与Makefile相关的文件主要有以下几个:

  根目录Makefile:最基本的Makefile;

  config.mak:由configure生成的Makefile,保存Configure的设置信息

  libavXXXX/Makefile:每个类库的Makefile(仅仅设置了几个变量);

  library.mak:编译类库的Makefile(和libavXXXX/Makefile配合使用);
  common.mak:包含一些通用代码的Makefile;

 

XXX.c:C语言文件;
XXX.h:C语言文件用到的头文件;
XXX.o:C语言文件对应的目标文件;
XXX.d:C语言文件对应的依赖关系文件;

 

 

(2). Configure 脚本

Configure一方面用于检测FFmpeg的编译环境,另一方面根据用户配置的选项生成config.mak,config.h文件(可能还有config.asm),

Configure的整体流程可以分成以下几步:

Set Default Value:设置各个变量默认值;

Parse Options:解析输入的选项;

Check Compiler:检查编译器;

die_license_disabled():检查GPL等协议的设置情况;

Check:检查编译环境(数学函数,第三方类库等);

Echo info:控制台上打印配置信息;

Write basic info:向config.mak中写入一些基本信息; 

print_config():向config.h、config.mak、config.asm中写入所有配置信息;

print_enabled():向config.mak写入所有enabled的组件信息;

pkgconfig_generate():向libavXXX/libavXXX.pc中写入pkgconfig信息(XXX代表avcodec,avformat等);

 

 

 

 


 

 

 

 

 

 

posted @ 2015-06-09 13:14  zxqstrong  阅读(1374)  评论(0编辑  收藏  举报