一、AVPacket的用法
1、直接使用
AVPacket packet;
...
av_read_frame(ifmt_ctx, &packet);
...
av_free_packet(&packet);
2、使用指针,则麻烦些:
//AVPacket *packet=(AVPacket *)av_malloc(sizeof(AVPacket));
//av_init_packet(packet);
//av_free(packet);
二、AVFrame的用法
AVFrame *pFrame=NULL;
pFrame=av_frame_alloc();
...
avcodec_decode_audio4(acodec_ctx, pFrame, &got_frame, &packet);
avcodec_decode_video2(vcodec_ctx, pFrame, &got_frame, &packet);
...
av_frame_free(&pFrame);
FFMPEG的对象AVFormatContext的pb字段指向一个AVIOContext。
1、直接使用
AVPacket packet;
...
av_read_frame(ifmt_ctx, &packet);
...
av_free_packet(&packet);
2、使用指针,则麻烦些:
//AVPacket *packet=(AVPacket *)av_malloc(sizeof(AVPacket));
//av_init_packet(packet);
//av_free(packet);
二、AVFrame的用法
AVFrame *pFrame=NULL;
pFrame=av_frame_alloc();
...
avcodec_decode_audio4(acodec_ctx, pFrame, &got_frame, &packet);
avcodec_decode_video2(vcodec_ctx, pFrame, &got_frame, &packet);
...
av_frame_free(&pFrame);
三、格式解析的架构
1、读写IO的聚合关系:
AVIOContext的opaque实际指向一个URLContext对象,这个对象封装了协议对象及协议操作对象,其中prot指向具体的协议操作对象,priv_data指向具体的协议对象。
URLProtocol为协议操作对象,针对每种协议,会有一个这样的对象,每个协议操作对象和一个协议对象关联,比如,文件操作对象为ff_file_protocol,它关联的结构体是FileContext。
int (*read_probe)(AVProbeData *);
int (*read_header)(struct AVFormatContext *, AVFormatParameters *ap);//读取解码codecid
int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
int (*read_close)(struct AVFormatContext *);
int (*read_play)(struct AVFormatContext *);
int (*read_pause)(struct AVFormatContext *);
const struct AVCodecTag * const *codec_tag;
int (*read_seek2)(struct AVFormatContext *s,int stream_index,int64_t min_ts,int64_t ts, int64_t max_ts, int flags);
URLProtocol为协议操作对象,针对每种协议,会有一个这样的对象,每个协议操作对象和一个协议对象关联,比如,文件操作对象为ff_file_protocol,它关联的结构体是FileContext。
AVIOContext -> URLContext ->URLProtocol
| | |+(IO函数)
| |+(url具体路径,流属性等参数)
|+(缓冲),opaque是URLContext
URLProtocol自己以链表方式来初始化。提供如下的直接读写的函数指针:
{
int (*url_open)(URLContext *h, const char *url, int flags);
int (*url_read)(URLContext *h, unsigned char *buf, int size);
int (*url_write)(URLContext *h, const unsigned char *buf, int size);
int64_t (*url_seek)(URLContext *h, int64_t pos, int whence);
int (*url_close)(URLContext *h);
int (*url_open)(URLContext *h, const char *url, int flags);
int (*url_read)(URLContext *h, unsigned char *buf, int size);
int (*url_write)(URLContext *h, const unsigned char *buf, int size);
int64_t (*url_seek)(URLContext *h, int64_t pos, int whence);
int (*url_close)(URLContext *h);
};
AVIOContext的如下三个函数指针,提供缓存读写功能,就是在avio_alloc_context()中初始化的,可以用户自己实现:
{
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);
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size);
int64_t (*seek)(void *opaque, int64_t offset, int whence);
};
2、Demuxer 和 muxer
A、demuxer:AVInputFormat(链表)
AVInputFormat包含以下主要播放读取相关的函数指针:
{
int priv_data_size; //具体文件容器格式对应的 Context 的大小,如:avicontext
int (*read_probe)(AVProbeData *);
int (*read_header)(struct AVFormatContext *, AVFormatParameters *ap);//读取解码codecid
int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
int (*read_close)(struct AVFormatContext *);
int (*read_play)(struct AVFormatContext *);
int (*read_pause)(struct AVFormatContext *);
const struct AVCodecTag * const *codec_tag;
int (*read_seek2)(struct AVFormatContext *s,int stream_index,int64_t min_ts,int64_t ts, int64_t max_ts, int flags);
};
B、muxer:AVOutputFormat(链表)
AVOutputFormat 包含以下介质写入相关的函数指针:
{
int (*write_header)(struct AVFormatContext *);
int (*write_packet)(struct AVFormatContext *,AVPacket *pkt);
int (*write_trailer)(struct AVFormatContext *);
int (*write_packet)(struct AVFormatContext *,AVPacket *pkt);
int (*write_trailer)(struct AVFormatContext *);
}
C、综合上下文:AVFormatContext
AVFormatContext主要有如下内容:
{
struct AVInputFormat *iformat; //指向具体的 demuxer
struct AVOutputFormat *oformat; //指向具体的 muxer
void *priv_data; //具体文件容器格式的 Context 如:avicontext
AVIOContext *pb; //广义的输入输出;
unsigned int nb_streams; //打开的文件容器中流的数量
AVStream **streams; //每个流的相关描述
struct AVOutputFormat *oformat; //指向具体的 muxer
void *priv_data; //具体文件容器格式的 Context 如:avicontext
AVIOContext *pb; //广义的输入输出;
unsigned int nb_streams; //打开的文件容器中流的数量
AVStream **streams; //每个流的相关描述
};
四、编解码的架构
1、流与codec的聚合关系:
AVStream -> AVCodecContext -> AVCodec
A、AVCodec
B、AVCodecContext
AVCodecContext保存 AVCodec指针和与 codec相关数据,
如 video的 width,height,audio 的 sample rate 等。
二个变量对于 encoder/decoder 的匹配最为重要:
enum CodecType codec_type; // CODEC_TYPE_xxx: CODEC_TYPE_VIDEO,CODEC_TYPE_AUDIO
enum CodecID codec_id; // CODEC_ID_xxx: CODEC_ID_H264
如 video的 width,height,audio 的 sample rate 等。
二个变量对于 encoder/decoder 的匹配最为重要:
enum CodecType codec_type; // CODEC_TYPE_xxx: CODEC_TYPE_VIDEO,CODEC_TYPE_AUDIO
enum CodecID codec_id; // CODEC_ID_xxx: CODEC_ID_H264
C、AVStream
2、解码流程:
A、在 av_open_input_stream()中:
调用 AVInputFormat 的 read_header()中读文件头信息时,会读出数据流的CodecID,即确定了他的解码器 Codec。
B、使用如下二个函数,根据传入的 CodecID,找到匹配的encoder和decoder。 :
B、使用如下二个函数,根据传入的 CodecID,找到匹配的encoder和decoder。 :
AVCodec *avcodec_find_encoder(enum CodecID id)
AVCodec *avcodec_find_decoder(enum CodecID id)
C、codec结果分别存储在如下结构体的变量中:
AVInputStream->AVStream *st->AVCodecContext *codec->struct AVCodec *codec
AVOutputStream->AVStream *st->AVCodecContext *codec->struct AVCodec *codec
AVCodec *avcodec_find_decoder(enum CodecID id)
C、codec结果分别存储在如下结构体的变量中:
AVInputStream->AVStream *st->AVCodecContext *codec->struct AVCodec *codec
AVOutputStream->AVStream *st->AVCodecContext *codec->struct AVCodec *codec
D、打开codec