模块:
算法
libavcodec - 编码解码器
libavdevice - 输入输出设备的支持
libavfilter - 视音频滤镜支持
libavformat - 视音频等格式的解析
libavutil - 工具库
libpostproc - 后期效果处理
libswscale - 图像颜色、尺寸转换数组
1. ffmpga代码简析缓存
1.2 源码——通用部分数据结构
(1). av_register_all (), avcodec_register_all ()tcp
avcodec_register_all() : 注册 hwaccel,encoder,decoder,parser,bitstream
av_register_all() : 注册 muxer,demuxer,protocol,在全部基于ffmpeg的应用程序中几乎第一个被调用的。只有调用了该函数,才能使用复用器,编码器等
avfilter_register_all() : 注册 滤镜filteride
(2).内存分配:av_malloc(),av_realloc(),av_mallocz(),av_calloc(),av_free(),av_freep()函数
内存操做常见函数位于 libavutil\mem.中:工具
av_malloc()——简单封装了系统的malloc(),并作错误检查工做;post
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*, ...);
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方式能够分红如下几个步骤:
sws_getContext()是初始化SwsContext的函数。sws_getContext()的声明位于libswscale\swscale.h:
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等);