ffmpeg的编程笔记2 -帧数据处理流程解析

一、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);


三、格式解析的架构


1、读写IO的聚合关系:
     FFMPEG的对象AVFormatContext的pb字段指向一个AVIOContext。
     AVIOContext的opaque实际指向一个URLContext对象,这个对象封装了协议对象及协议操作对象,其中prot指向具体的协议操作对象,priv_data指向具体的协议对象。

     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); 
};

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); 
};


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 *); 
}

C、综合上下文:AVFormatContext
AVFormatContext主要有如下内容:
{
   struct AVInputFormat *iformat;   //指向具体的 demuxer
   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 

C、AVStream



2、解码流程:

A、在 av_open_input_stream()中:
     调用 AVInputFormat 的 read_header()中读文件头信息时,会读出数据流的CodecID,即确定了他的解码器 Codec。

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

D、打开codec



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值