进入函数encoder_encode,注意结构体AV1_COMP,基本上所有有关编码的具体信息都能从这里访问到,包括QP,POC等。
av1_receive_raw_frame会对一系列结构体和buffer进行初始化,包括lookahead结构体以及参考帧列表等,下一个函数入口是av1_get_compressed_data,若返回-1则指的是没有帧被编码,因为AV1有lag-in-frame,默认是19,也就是到第19帧才会开始编码第0帧。pass1的目的是加速二次编码,所以不会写入码流。
第二次编码时,frame_size不为0时,就会开始写码流。通过函数av1_write_obu_header完成,aom_wb_write_literal包含aom_wb_write_bit。
ps:volatile是一个类型修饰符(type specifier).volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
static aom_codec_err_t encoder_encode(aom_codec_alg_priv_t *ctx,
const aom_image_t *img,
aom_codec_pts_t pts,
unsigned long duration,
aom_enc_frame_flags_t enc_flags) {
const size_t kMinCompressedSize = 8192;
volatile aom_codec_err_t res = AOM_CODEC_OK;//用来标识编码是否有错误
AV1_COMP *const cpi = ctx->cpi;
const aom_rational64_t *const timestamp_ratio = &ctx->timestamp_ratio;
volatile aom_codec_pts_t ptsvol = pts;
if (cpi == NULL) return AOM_CODEC_INVALID_PARAM;
if (img != NULL) {
res = validate_img(ctx, img);
// TODO(jzern) the checks related to cpi's validity should be treated as a
// failure condition, encoder setup is done fully in init() currently.
if (res == AOM_CODEC_OK) {
size_t data_sz = ALIGN_POWER_OF_TWO(ctx->cfg.g_w, 5) *//使value与2的幂对齐
ALIGN_POWER_OF_TWO(ctx->cfg.g_h, 5) * get_image_bps(img);
if (data_sz < kMinCompressedSize) data_sz = kMinCompressedSize;
if (ctx->cx_data == NULL || ctx->cx_data_sz < data_sz) {
ctx->cx_data_sz = data_sz;
free(ctx->cx_data);
ctx->cx_data = (unsigned char *)malloc(ctx->cx_data_sz);
if (ctx->cx_data == NULL) {
return AOM_CODEC_MEM_ERROR;
}
}
}
}
if (ctx->oxcf.mode != GOOD && ctx->oxc