av_register_all()
调用了avcodec_register_all()。avcodec_register_all()注册了和编解码器有关的组件:硬件加速器,解码器,编码器,Parser,Bitstream Filter。av_register_all()除了调用avcodec_register_all()之外,还注册了复用器,解复用器,协议处理器。
AVFormatContext:统领全局的基本结构体。主要用于处理封装格式(FLV/MKV/RMVB等)。
AVIOContext:输入输出对应的结构体,用于输入输出(读写文件,RTMP协议等)。
AVStream,AVCodecContext:视音频流对应的结构体,用于视音频编解码。
AVFrame:存储非压缩的数据(视频对应RGB/YUV像素数据,音频对应PCM采样数据)
AVPacket:存储压缩数据(视频对应H.264等码流数据,音频对应AAC/MP3等码流数据)
1. int avformat_open_input(AVFormatContext **ps, const char *filename,
2. AVInputFormat *fmt, AVDictionary **options)
函数用于打开多媒体数据并且获得一些相关的信息。
来自 <http://blog.csdn.net/leixiaohua1020/article/details/44064715>
ps:函数调用成功之后处理过的AVFormatContext结构体。
file:打开的视音频流的URL。
fmt:强制指定AVFormatContext中AVInputFormat的。这个参数一般情况下可以设置为NULL,这样FFmpeg可以自动检测AVInputFormat。
dictionay:附加的一些选项,一般情况下可以设置为NULL。
函数执行成功的话,其返回值大于等于0。
来自 <http://blog.csdn.net/leixiaohua1020/article/details/44064715>
3. int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
该函数可以读取一部分视音频数据并且获得一些相关的信息。
来自 <http://blog.csdn.net/leixiaohua1020/article/details/44084321>
ic:输入的AVFormatContext。
options:额外的选项,目前没有深入研究过。
函数正常执行后返回值大于等于0。
来自 <http://blog.csdn.net/leixiaohua1020/article/details/44084321>
4. AVCodec *avcodec_find_encoder(enum AVCodecID id);
函数的参数是一个编码器的ID,返回查找到的编码器(没有找到就返回NULL)。
5. AVCodec *avcodec_find_decoder(enum AVCodecID id);
函数的参数是一个解码器的ID,返回查找到的解码器(没有找到就返回NULL)。
其实这两个函数的实质就是遍历AVCodec链表并且获得符合条件的元素。
6. int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
该函数用于初始化一个视音频编解码器的AVCodecContext
avctx:需要初始化的AVCodecContext。
codec:输入的AVCodec
options:一些选项。例如使用libx264编码的时候,“preset”,“tune”等都可以通过该参数设置。
7. int av_read_frame(AVFormatContext *s, AVPacket *pkt);
读取码流中的音频若干帧或者视频一帧。例如,解码视频的时候,每解码一个视频帧,需要先调用 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次都不会去读数据,而是返回第一次读取的数据,直到全部解析完毕。
s:输入的AVFormatContext
pkt:输出的AVPacket
如果返回0则说明读取正常。
再次调用本函数之前,必须使用av_free_packet释放pkt所占用的资源。
8. int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
int *got_picture_ptr,
const AVPacket *avpkt);
作用是解码一帧视频数据。输入一个压缩编码的结构体AVPacket,输出一个解码后的结构体AVFrame。
int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, int*got_frame_ptr, AVPacket *avpkt);
解码一个音频帧。输入数据在AVPacket结构中,输出数据在frame中,got_frame_ptr表示是否有数据输出。
9. int avcodec_close(AVCodecContext *avctx);
avctx就是需要关闭的编码器的AVCodecContext
void avformat_close_input(AVFormatContext **s);
函数用于关闭一个AVFormatContext,一般情况下是和avformat_open_input()成对使用的。
intavformat_network_init(void);
载socket库以及网络加密协议相关的库,为后续使用网络相关提供支持
打开网络流的话,前面要加上函数avformat_network_init()
10.void av_dump_format(AVFormatContext *ic,
int index,
const char *url,
int is_output);
是一个手工调试的函数,能使我们看到pFormatCtx->streams里面有什么内容。一般接下来我们使用av_find_stream_info()函数,它的作用是为pFormatCtx->streams填充上正确的信息。
11. typedef struct AVPacket
12.{
13. int64_t pts;
14. int64_t dts;
15. int64_t pos;
16. uint8_t *data;//数据首地址
17. int size;
18. int stream_index;
19. int flags;//flags为标志域,1表示该数据是一个关键帧
20. void(*destruct)(struct AVPacket*);//释放数据缓冲区的函数指针
21.} AVPacket;
每一个包是一个完整的数据帧,来暂存解复用之后、解码之前的媒体数据(一个音/视频帧、一个字幕包等)及附加信息(解码时间戳、显示时间戳、时长等)
AVPacket本身只是个容器,它data成员引用实际的数据缓冲区。这个缓冲区通常是由av_new_packet创建的,但也可能由 FFMPEG的API创建(如av_read_frame)。当某个AVPacket结构的数据缓冲区不再被使用时,要需要通过调用av_free_packet释放
22. void av_init_packet(AVPacket *pkt)
23. int av_new_packet(AVPacket *pkt, int size)
来自 <http://blog.csdn.net/vintionnee/article/details/17734223>
24. int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples,
25. enum AVSampleFormat sample_fmt, int align)
音频一般是采用成PCM格式,而计算PCM格式音频尺寸,就需要如下几个参数。
通道数,采样频率,采用格式。
通道数:个人理解,就是同时有个几个设备在进行音频的采样,最少为1,一般通道数越多,音质越好。
采样频率:(也称为采样速度或者采样频率)定义了每秒从连续信号中提取并组成离散信号的采样个数,它用赫兹(Hz)来表示。
采用位数:既然采样频率表示每秒采样的个数,那么如何描述每个采样点呢?用什么方法独立每个采样点值的区别呢?也就是如何度量每个采样点,而这正是采样格式出现的意义。通常使用16bit,也就是2的16次方,共有65536个不同的度量值,这样采样位数越高,音频度量化的就越精细,音质同样也就越高。
所以音频所占用字节数 = 通道数 * 采用频率(Hz) * 采用位数(byte)
而在ffmpeg里面就使用av_sample_get_buffer_size来计算音频占用的字节数。
来自 <http://blog.csdn.net/oldmtn/article/details/48048687>
将avcodec_alloc_frame() 替换为 av_frame_alloc()。
来自 <http://blog.csdn.net/davebobo/article/details/51123917>