av_register_all()的作用是:初始化所有组件,只有调用了该函数,才能使用复用器和编解码器,该接口内部的调用为:
(1).avcodec_register_all(),该接口内部执行步骤:
注册硬件加速器:REGISTER_HWACCEL()
注册音视频编码器:REGISTER_ENCODER()
注册音视频解码器:REGISTER_DECODER()
打包注册:REGISTER_ENCDEC()
注册解析器:REGISTER_PARSER()
(2).执行复用器和解复用器的注册:
注册复用器:REGISTER_MUXER()
注册解复用器:REGISTER_DEMUXER()
打包注册:REGISTER_MUXDEMUX()
av_malloc、av_free():av_malloc分配一个内存块,其对齐方式适合所有内存访问(包括 CPU 上可用的向量),av_free (void *ptr):释放已经使用av_malloc和av_realoc()f分配的内存空间,void * av_realoc(void *ptr,size_t size),扩prt内存的大小为size所示大小。
ffmpeg中的数据结构体有很多,常见的数据结构包含以下几个部分:
AVIOContext,URLProtocol,URLContext,主要用于存储音视频所使用的协议类型以及状态,URLProtocol主要用于
存储输入使用的封装格式,每种协议都会对应一种URLProtocal 结构。
AVFormatContext主要存储音视频封装中包含的信息,AVInputFormat:存储输入音频中使用的封装格式,每种音视频封装格式
都对应一种AVInputFormat结构。
每个AVstream存储一个视频/音频流的相关数据信息,每个AVStream对应一个AVCodecContext,存储该视频音频对应的使
用解码方式的相关数据,每个AVcodecContext中对应一个AVCodec,包含该视频呢或者音频所使用的解码器结构,每种解码器
对应一个AVCode结构。
视频结构存储一帧,而音频结构可以存储几帧,AVPacket存储解前的数据,而AVFrame存储解码后的数据。
unsigned char *buffer; // buffer起始地址
int buffer_size; // 可以读取或者写入的最大的buffer size
unsigned char *buf_ptr; // 当前正在读或写操作的buffer地址
unsigned char *buf_end; // 数据结束的buffer地址,如果读取函数返回的数据小于请求数据,buf_end可能小于buffer + buffer_size
void *opaque; // 一个私有指针,传递给read / write / seek / 等函数
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size); // 读取音视频数据的函数。
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size); // 写入音视频数据的函数
int64_t (*seek)(void *opaque, int64_t offset, int whence);
int64_t pos; // 当前buffer在文件中的位置
int must_flush; // 如果下一个seek应该刷新,则为true
int eof_reached; // 如果到达eof(end of file 文件尾),则为true
int write_flag; // 如果开放写,则为true
int (*read_pause)(void *opaque, int pause); // 暂停或恢复网络流媒体协议的播放
int64_t (*read_seek)(void *opaque, int stream_index,
int64_t timestamp, int flags); // 快进到指定timestamp
int seekable; // 如果为0,表示不可seek操作。其它值查看AVIO_SEEKABLE_XXX
int64_t maxsize; // max filesize,用于限制分配空间大小
int direct; // avio_seek是否直接调用底层的seek功能。
int64_t bytes_read; // 字节读取统计数据
int seek_count; // seek计数
int writeout_count; // 写入次数统计
int orig_buffer_size; // 原始buffer大小
const char *protocol_whitelist; // 允许协议白名单,以','分隔
const char *protocol_blacklist; // 不允许的协议黑名单,以','分隔
// 用于替换write_packet的回调函数。
int (*write_data_type)(void *opaque, uint8_t *buf, int buf_size,
enum AVIODataMarkerType type, int64_t time);
} AVIOContext;
①(*read_packet):读取音视频数据的函数。可以自行定义
②(*write_packet):写入音视频数据的函数。可以自行定义
③(*read_pause):暂停或恢复网络流媒体协议的播放 。可以自行定义
在解码的过程中,buffer中用于存储ffmpeg读入的数据,当打开一个文件时需要的先把数据从磁盘中读入buffer中,之后送给解码器使用。其
中的opaque指定了URLContext。
其中可以使用avio_alloc_context()对AVIOContext对象进行的初始化,当时用结束后需要调用的av_free()销毁对象就可以。
avio_alloc_context():可以构造AVIOContext对象,
AVIOContext* avio_alloc_context ( unsigned char * buffer, //指定字符串地址
int buffer_size, //指定缓冲区大小
int write_flag, //如果缓冲区应该是可写的,则设置为 1,否则设置为 0。
void * opaque, //指向特殊数据的不透明指针
int(*)(void *opaque, uint8_t *buf, int buf_size) read_packet, //用于重新填充的缓冲区的函数为NULL
int(*)(void *opaque, uint8_t *buf, int buf_size) write_packet, //用于写入缓冲区内容的函数可能是NULL
int64_t(*)(void *opaque, int64_t offset, int whence) seek //用于寻找指定字节的位置
)
其中opaque指向了URLContext结构,具体的结构如下所示:
typedef struct URLContext {
const AVClass *av_class; ///< information for av_log(). Set by url_open().
//指向相应URLProtocal
struct URLProtocol *prot;
int flags;
int is_streamed; /**< true if streamed (no seek possible), default = false */
int max_packet_size; /**< if non zero, the stream is packetized with this max packet size */
void *priv_data;//一般用来指向某种具体协议的上下文信息
char *filename; /**< specified URL */
int is_connected;
AVIOInterruptCB interrupt_callback;
} URLContext;
URLContext结构体中还有一个结构体URLProtocol。注:每种协议(rtp,rtmp,file等)对应一个URLProtocol。这个结构体也不在FFMPEG
提供的头文件中。从FFMPEG源代码中翻出其的定义:
URLProtocol ff_file_protocol = {
.name = "file",
.url_open = file_open,
.url_read = file_read,
.url_write = file_write,
.url_seek = file_seek,
.url_close = file_close,
.url_get_file_handle = file_get_handle,
.url_check = file_check,
};
URLProtocol ff_rtmp_protocol = {
.name = "rtmp",
.url_open = rtmp_open,
.url_read = rtmp_read,
.url_write = rtmp_write,
.url_close = rtmp_close,
.url_read_pause = rtmp_read_pause,
.url_read_seek = rtmp_read_seek,
.url_get_file_handle = rtmp_get_file_handle,
.priv_data_size = sizeof(RTMP),
.flags = URL_PROTOCOL_FLAG_NETWORK,
};
URLProtocol ff_udp_protocol = {
.name = "udp",
.url_open = udp_open,
.url_read = udp_read,
.url_write = udp_write,
.url_close = udp_close,
.url_get_file_handle = udp_get_file_handle,
.priv_data_size = sizeof(UDPContext),
.flags = URL_PROTOCOL_FLAG_NETWORK,
};
typedef struct AVInputFormat {
const char *name; // 输入格式的短名称
const char *long_name; // 格式的长名称(相对于短名称而言,更易于阅读)
/**
* Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS,
* AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH,
* AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS.
*/
int flags;
const char *extensions; // 如果定义了扩展,就不会进行格式探测。但因为该功能目前支持不够,不推荐使用
const struct AVCodecTag * const *codec_tag; // 见名知意
const AVClass *priv_class; ///< AVClass for the private context
const char *mime_type; // mime类型,它用于在探测时检查匹配的mime类型。
/* 此行下方的任何字段都不是公共API的一部分。 它们不能在libavformat之外使用,可以随意更改和删除。
* 应在上方添加新的公共字段。*/
struct AVInputFormat *next; // 用于链接下一个AVInputFormat
int raw_codec_id; // 原始demuxers将它们的解码器id保存在这里。
int priv_data_size; // 私有数据大小,可以用于确定需要分配多大的内存来容纳下这些数据。
/**
* 判断给定文件是否有可能被解析为此格式。 提供的缓冲区保证为AVPROBE_PADDING_SIZE字节大,因此除非您需 * 要更多,否则无需检查。
*/
int (*read_probe)(AVProbeData *);
/**
* 读取格式头,并初始化AVFormatContext结构体
* @return 0 表示操作成功
*/
int (*read_header)(struct AVFormatContext *);
/**
* 读取一个packet并存入pkt指针中。pts和flags会被同时设置。
* @return 0 表示操作成功, < 0 发生异常
* 当返回异常时,pkt可定没有allocated或者在函数返回之前被释放了。
*/
int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
// 关闭流,AVFormatContext和AVStreams并不会被这个函数释放。
int (*read_close)(struct AVFormatContext *);
/**
* 在stream_index的流中,使用一个给定的timestamp,seek到附近帧。
* @param stream_index 不能为-1
* @param flags 如果没有完全匹配,决定向前还是向后匹配。
* @return >= 0 成功
*/
int (*read_seek)(struct AVFormatContext *,
int stream_index, int64_t timestamp, int flags);
// 获取stream[stream_index]的下一个时间戳,如果发生异常返回AV_NOPTS_VALUE
int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index,
int64_t *pos, int64_t pos_limit);
// 开始或者恢复播放,只有在播放rtsp格式的网络格式才有意义。
int (*read_play)(struct AVFormatContext *);
int (*read_pause)(struct AVFormatContext *);// 暂停播放,只有在播放rtsp格式的网络格式才有意义。
/**
* 快进到指定的时间戳
* @param stream_index 需要快进操作的流
* @param ts 需要快进到的地方
* @param min_ts max_ts seek的区间,ts需要在这个范围中。
*/
int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
// 返回设备列表和其属性
int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
// 初始化设备能力子模块
int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
// 释放设备能力子模块
int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
} AVInputFormat;
AVPacket是存储压缩编码数据相关信息的结构体,
AVBufferRef * buf //buf是AVBufferRef类型指针,用来管理data指针引用的数据缓存
int64_t pts //显示时间戳
int64_t dts //解码时间戳
uint8_t * data //指向保存压缩数据的指针
int size //压缩数据的长度
int stream_index //Packets所在stream流的索引
int flags //标志,其中的最低位为1表示该数据是关键帧
AVPacketSideData * side_data //容器可以提供附加数据包
int side_data_elems //边缘数据元数的个数
int64_t duration //此数据包持续时间
int64_t pos //数据流媒体中存在的位置
void * opaque //for some private data of the user More...
AVBufferRef * opaque_ref // AVBufferRef for free use by the API user. More...
AVRational time_base //初始化时间
AVFrame用于存储原始数据(即非压缩数据,例如对视频来说是YUV,RGB,对音频来说是PCM),此外还包含了一些相关的信息。比如说,解码的时候存储了宏块类型表,QP表,运动矢量表等数据。
uint8_t * data [AV_NUM_DATA_POINTERS] //解码手的原始数据(YUV,RGB,PCM)
int linesize [AV_NUM_DATA_POINTERS] //data中一行数据的大小。
uint8_t ** extended_data //指向数据平面的指针,对于视屏应该指向data[],对于音频
int nb_samples //音频的一个frame中可能包换多少音频帧
int format //解码手原始数据类型
int key_frame //是否是关键帧
enum AVPictureType pict_type //帧类型(IBP)
AVRational sample_aspect_ratio //宽高比
int64_t pts //显示时间戳
int64_t pkt_dts
AVRational time_base
Time base for the timestamps in this frame. More...
int coded_picture_number //编码帧序号
int display_picture_number //显示帧序号
int quality //采样质量
void * opaque
for some private data of the user More...
int repeat_pict
When decoding, this signals how much the picture must be delayed. More...
int interlaced_frame
The content of the picture is interlaced. More...
int top_field_first
If the content is interlaced, is top field displayed first. More...
int palette_has_changed
Tell user application that palette has changed from previous frame. More...
int64_t reordered_opaque
reordered opaque 64 bits (generally an integer or a double precision float PTS but can be anything). More...
int sample_rate
Sample rate of the audio data. More...
attribute_deprecated uint64_t channel_layout
Channel layout of the audio data. More...
AVBufferRef * buf [AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame. More...
AVBufferRef ** extended_buf
For planar audio which requires more than AV_NUM_DATA_POINTERS AVBufferRef pointers, this array will hold all the references which cannot fit into AVFrame.buf. More...
int nb_extended_buf
Number of elements in extended_buf. More...
AVFrameSideData ** side_data
int nb_side_data
int flags
Frame flags, a combination of AV_FRAME_FLAGS. More...
enum AVColorRange color_range
MPEG vs JPEG YUV range. More...
enum AVColorPrimaries color_primaries
enum AVColorTransferCharacteristic color_trc
enum AVColorSpace colorspace
YUV colorspace type. More...
enum AVChromaLocation chroma_location
int64_t best_effort_timestamp
frame timestamp estimated using various heuristics, in stream time base More...
int64_t pkt_pos
reordered pos from the last AVPacket that has been input into the decoder More...
attribute_deprecated int64_t pkt_duration
duration of the corresponding packet, expressed in AVStream->time_base units, 0 if unknown. More...
AVDictionary * metadata
metadata. More...
int decode_error_flags
decode error flags of the frame, set to a combination of FF_DECODE_ERROR_xxx flags if the decoder produced a frame, but there were errors during the decoding. More...
attribute_deprecated int channels
number of audio channels, only used for audio. More...
int pkt_size
size of the corresponding packet containing the compressed frame. More...
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame. More...
AVBufferRef * opaque_ref
AVBufferRef for free use by the API user. More...
AVBufferRef * private_ref
AVBufferRef for internal use by a single libav* library. More...
AVChannelLayout ch_layout //音频的时间布局
int64_t duration //时间周期
avcodec_open:使用codec对象初始化AVCodecContext 对象,options 为初始化的AVCodec对象的的设置选项
int avcodec_open2 ( AVCodecContext * avctx, const AVCodec * codec, AVDictionary ** options )
avcodec_close:关闭给定的AVCodecContext并释放与其关联的所有数据,
int avodec_close(AVCodecContext *avctx)
avcodec_find_decoder():利用其参数的id查找已经注册的编码器的:
const AVCodec* avcodec_find_decoder ( enum AVCodecID id )
ID:表示编码器对应的解码器
avcodec_find_decoder_by_name():通过解码器的名字,返回AVcodec对象
const AVCodec* avcodec_find_decoder_by_name ( const char * name )
name:解码器对应的名
avcodec_find_encoder():利用其参数的id查找已经注册的编码器的:
const AVCodec* avcodec_find_encoder ( enum AVCodecID id )
ID:表示编码器对应的解码器
avcodec_find_encoder_by_name():通过解码器的名字,返回AVcodec对象
const AVCodec* avcodec_find_encoder_by_name ( const char * name )
name:解码器对应的名
avcodec_send_packet():提供原始数据包数据作为解码器的输入:
int avcodec_send_packet ( AVCodecContext * avctx, const AVPacket * avpkt )
avcodec_receive_frame():将从解码器队列中提取出一个frame
int avcodec_receive_frame ( AVCodecContext * avctx, AVFrame * frame)
avctx: 编码器队列
frame:这将设置为由解码器分配的参考计数视频或音频帧(取决于解码器类型)。请注意,该函数将始终在执行任何其他操作之前调用 av_frame_unref(frame)
avformat_open_input:打开输出的流和读取流的头部信息,编码器未打开状态,同时使用avformat_close_input()关闭流
int avformat_open_input ( AVFormatContext ** ps,const char * url,const AVInputFormat * fmt,AVDictionary ** options )
ps:函数调佣成功之后处理过的AVFormatContext结构体
url:打开的音视频流的URL
fmt:强制指定AVFormatContext中AVIputFormat的。这个参数一般情况下可以设置为NULL,这个FFmpeg可以自动检测AVInputformat
options:附加的一些选项,一般情况下可以设置为NULL
avformat_find_stream_info:读取音视频数据来获取一些相关信息
int avformat_find_stream_info ( AVFormatContext * ic , AVDictionary ** options )
ic:输入的上下文信息
AVDictionary:额外的选项
av_read_frame():读取流中视频中的一帧或者若干帧的音频数据
int av_read_frame ( AVFormatContext * s, AVPacket * pkt )
avformat_close_input():关闭输入流的上下文信息
void avformat_close_input ( AVFormatContext ** s )
s :输入流上下文信息
编码相关的API:在基于音视频编码器的应用程序中,avformat_alloc_output_context2()函数是通常使用的第一个调用的函数,除了使用的函数外还包括FFmpeg中常用的文件操作函数:av_write_frame():用于写视频数据,avformat_write_header():用于写视频的头文件信息,av_frame_tailer:用于写视频文件的尾部信息。
avformat_alloc_output_context2():通常用来输出的AVFormatContext的结构体
int avformat_alloc_output_context2 (AVFormatContext ** ctx, const AVOutputFormat * oformat,const char * format_name,const char * filename )
ctx:函数调用成功之后创造的AVFormatContext结构结构体;
oformat:用于确定输出的AVOutputFormat,用于确定输出的格式
format_name:支出输出格式的名称
filename:指出输出文件的名称
avformat_write_heder():分配流的私有数据而且写stream的header到一个输出的媒体文件中
int avformat_write_header ( AVFormatContext * s,AVDictionary ** options )
s:用于输出的AVFormatContext
options :额外的选项
avcodec_send_frame():为编码器提供未压缩的视频或者音频的AVFrame:
int avcodec_send_frame ( AVCodecContext * avctx,
const AVFrame * frame
)
avcodec_receive_packet():从编码器中获取的编码德剧,一旦成功,它将带回有压缩帧的AVPacket。
int avcodec_receive_packet ( AVCodecContext * avctx,AVPacket * avpkt )
avcodec_send_frame()/avcodec_receive_packet (),的使用说明:
【1】按照】pts递增的顺序想编码器中送入原始数据帧frame,编码器按照dts递增的顺序输出编码的packet,实际上编码器关注
输入的pts而不关注dts,他只关注的收到的frame,按照需求进行缓冲和编码
【2】:avcodec_receive_packet()输出Packet时,会设置packet.dts,从0开始,每次输出的packet的dts加1,这是视频层的dts,这是视
频层的dts,用户需要将转化为容器层的dts
【3】:avcodec_receive_packet输出packet时,packet.pts会拷贝对应的frame.pts,这是视屏层的pts用户需要将其转化为容器层的pts
【4】:avcodec_send_frame()发送NULL frame时,编码器会进入到fflush模式
【5】:avcodec_send_frame()发送第一个NULL返回成功,后续的NULL会返回AVERROR_EOF:
【6】:avcodec_send_frame()多次发送NULL并不会导致编码器缓冲区的内容消失,使用的avcodec_flush_buffer(),可以立即丢掉编
码器中的缓冲区的内容。因此编码完成后需要使用avcodec_send_frame(NULL)取完内容。
av_write_frame()/av_interleaved_write_frame():用于输出一帧流媒体数据
int av_write_frame ( AVFormatContext * s,AVPacket * pkt )
s:用于输出的AVFormatContext
pkt:等待输出AVPacket
av_write_trailer():用于输出文件的尾部
int av_write_trailer ( AVFormatContext * s )
libswscale:主要用于处理图片像素的数据库的类,可以完成图像格式的装换,图像的拉伸工作。
sws_getContex():返回和分配一个SwsContext对象,其原型可以表示为:
struct SwsContext* sws_getContext ( int srcW, //被转化原图像的宽度
int srcH, //被转化原图像的高度
enum AVPixelFormat srcFormat, //被转化原图像的格式(RGB,BGR,YUV)
int dstW, //转化指定原图像的高度
int dstH, // 转换后指定原图像的宽度
enum AVPixelFormat dstFormat, //转化后指定的原图像的格式
int flags, //转化使用的算法
SwsFilter * srcFilter, //输入使用的滤波器
SwsFilter * dstFilter, //输出使用的滤波器
const double * param // 调整使用的缩放器的额外参数
)
sws_scale():处理图像数据,主要用于做视频的像素格式金额分辨率的转化
int sws_scale ( struct SwsContext * c, //使用sws_getContext()创建的缩放上下文
const uint8_t *const srcSlice[], //包含指向源切片平面的指针的数组
const int srcStride[], //包含源图像每个平面的步幅的数组
int srcSliceY, //要处理的切片在源图像中的位置
int srcSliceH, //源切片的高度,即切片中的行数
uint8_t *const dst[], //包含指向目标图像平面的指针的数组
const int dstStride[] //包含目标图像每个平面的步幅的数组
)
**sws_freeContext():**释放一个SwsConntext()
重采样API,其可以实现以下功能:采样频率转化;声道格式化装换;样本格式装换。
1. 创建上下文环境;重采样上下文环境为SwrContext数据结构
2. 参数设置:转换的参数设置到SwrContext中
3. SwrContex他初始化:swr_init()
4. 分配样本的数据内存空间:使用av_sample_alloc_array_and_sameples,av_samples_allpc等工具
5. 开启重采样操作,通过swr_convert完成
6. 重采样完成后释放相关的资源
swr_alloc():创建SwrContext对象
av_opt_set_*():设置输入输出音频信息
swr_init():初始化SwrContext。
av_samples_alloc_array_and_samples():根据音频格式分配相应大小的内存空间
av_samples_alloc:根据音频格式分配相应大小的内存攻坚,用于装换过程对输出的内存大小进行调整。
swr_convert:进行重采样的装换
swr_alloc():分配一个 SwrContext对象
struct SwrContext* swr_alloc ( void )
int swr_alloc_set_opts2 ( struct SwrContext ** ps, // 如果可用,则指向现有的 Swr 上下文,如果不可用,则指向 NULL
AVChannelLayout * out_ch_layout, // 输出通道布局
enum AVSampleFormat out_sample_fmt, // 输出样本格式
int out_sample_rate, // 输出采样的频率
AVChannelLayout * in_ch_layout, // 输入通道布局
enum AVSampleFormat in_sample_fmt, // 输入样本格式
int in_sample_rate, // 输入采样平率
int log_offset, // 日志界别偏移
void * log_ctx // 父日志移动上下文
)
swr_init():参数设置好后必须调用swr_nit()对SwrContext对象激进型初始化
int swr_init ( struct SwrContext * s )
v_samples_alloc_array_and_samples()
av_find_input_format()::发现输入
const AVInputFormat* av_find_input_format ( const char * short_name )