前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >6.AVCodecContext和AVCodec

6.AVCodecContext和AVCodec

作者头像
诺谦
发布2020-09-10 15:08:23
1.2K0
发布2020-09-10 15:08:23
举报
文章被收录于专栏:Linux驱动Linux驱动

AVCodecContext

AVCodecContext 结构表示程序运行的当前 Codec 使用的上下文,着重于所有 Codec 共有的属性(并且是在程序运行时才能确定其值)和关联其他结构的字段。

  • extradata 和 extradata_size 两个成员表述了相应 Codec 使用的私有数据;
  • codec成员关联相应的编解码器;
  • priv_data 成员关联各个具体编解码器独有的属性 context,与 AVCodec 结构中的 priv_data_size 配对使用。
代码语言:javascript
复制
typedef struct AVCodecContext
{
enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */
const struct AVCodec *codec; //指向相应的解码器,如: ff_h264_decoder
enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */
void *priv_data;//指向具体相应的解码器的 context,如 H264Context
 
int bit_rate;
int frame_number;
 
int thread_count; //编解码时的线程数量,由用户设置,与CPU核心数有关,最佳效果一般设置为CPU核心数*2.
 
AVRational time_base; //时间的基准单位
 
unsigned char *extradata;//扩展数据,如 mov 格式-> audio trak ->aac -> esds 格式中的附加解码信息、H.264解码器的存储SPS,PPS信息等.
 
int extradata_size;//扩展数据的 size
 
int width, height; //视频的原始的宽度与高度,仅针对视频
 
enum PixelFormat pix_fmt;//视频一帧图像的格式,如 YUV420
 
 
int sample_rate; //采样率(仅音频)。
int channels;   //声道数(仅音频)。 
enum AVSampleFormat sample_fmt; //音频采样格式,编码:由用户设置。解码:由libavcodec设置。 
int frame_size;  //音频帧中每个声道的采样数。编码:由libavcodec在avcodec_open2()中设置。 解码:可以由一些解码器设置以指示恒定的帧大小. 
int frame_number;  //帧计数器,由libavcodec设置。解码:从解码器返回的帧的总数。编码:到目前为止传递给编码器的帧的总数。 
uint64_t channel_layout;  //音频声道布局。编码:由用户设置。解码:由用户设置,可能被libavcodec覆盖。 
enum AVAudioServiceType audio_service_type;  //音频流传输的服务类型。编码:由用户设置。解码:由libavcodec设置。
int bits_per_sample;
int block_align;
 
//公共操作函数
int (*alloc_frame)(AVCodecContext *avctx, AVFrame *frame);
int (*start_frame)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size);
int (*decode_params)(AVCodecContext *avctx, int type, const uint8_t *buf, uint32_t buf_size);
int (*decode_slice)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size);
int (*end_frame)(AVCodecContext *avctx);
}AVCodecContext;

其中codec成员结构体为AVCodec.

AVCodec

AVCodec 是类似 COM 接口的数据结构,表示音视频编解码器,着重于功能函数.

  • next 成员用于把所有支持的编解码器连接成链表,便于遍历查找;
  • id 确定唯 一编 解 码器 ;
  • priv_data_size 表示具 体 的 Codec 对应的 Context 结构大 小 .
代码语言:javascript
复制
typedef struct AVCodec
{
 
const char *name;// 标示 Codec 的名字, 比如, "h264" "h263" 等。
const char *long_name; //表示Codec的长名字,比如h264的长名字为"H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"
enum AVMediaType type; // 标示 Codec 的类型,有 video , audio ,字幕等类型。
enum AVCodecID id; // 标示 Codec 的 ID,有 AV_CODEC_ID_H264等。
 
int priv_data_size; // 标示具体的 Codec 对应的 Context 的 size,比如h264的等于sizeof(H264Context)
 
struct AVCodec *next; //以链表的形式指向下一个Codec(ID+1)
 
// 以下标示 Codec 对外提供的操作,每一种解码器都会实现这些操作。
int(*init)(AVCodecContext*);
int(*encode)(AVCodecContext *, uint8_t *buf, int buf_size, void *data);
int(*close)(AVCodecContext*);
int(*decode)(AVCodecContext *, void *outdata, int *outdata_size, uint8_t *buf, int buf_size);
 
}AVCodec;

H264 的主要结构的初始化如下:

代码语言:javascript
复制
AVCodec ff_h264_decoder = {
.name = "h264",
.long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_H264,
.priv_data_size = sizeof(H264Context),
.init = h264_decode_init,
.close = h264_decode_end,
.decode = h264_decode_frame,
.capabilities = /*AV_CODEC_CAP_DRAW_HORIZ_BAND |*/ AV_CODEC_CAP_DR1 |
AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS |
AV_CODEC_CAP_FRAME_THREADS,
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING |
FF_CODEC_CAP_ALLOCATE_PROGRESS | FF_CODEC_CAP_INIT_CLEANUP,
.flush = h264_decode_flush,
.update_thread_context = ONLY_IF_THREADS_ENABLED(ff_h264_update_thread_context),
.profiles = NULL_IF_CONFIG_SMALL(ff_h264_profiles),
.priv_class = &h264_class,
}

打开一个视频解码器示例

代码语言:javascript
复制
videoStream = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);//获取视频流

AVCodec *vcodec = avcodec_find_decoder(ic->streams[videoStream]->codecpar->codec_id);//获取codec

AVCodecContext *vc = avcodec_alloc_context3(vcodec); //构造AVCodecContext ,并将vcodec填入AVCodecContext中

avcodec_parameters_to_context(vc, ic->streams[videoStream]->codecpar); //初始化AVCodecContext

int ret = avcodec_open2(vc, NULL,NULL); //打开解码器,由于之前调用avcodec_alloc_context3(vcodec)初始化了vc,那么codec(第2个参数)可以填NULL
 
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-09-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档