【AV1代码研究二】从main到编码一个SB----aomenc的函数调用结构

【AV1代码研究二】从main到编码一个SB----aomenc的函数调用结构

  • 从main函数到编码一个SB
    • main
    • encode_frame
    • aom_codec_encode
    • encoder_encode
    • av1_get_compressed_data
    • av1_encode_strategy
    • denoise_and_encode
    • av1_encode
    • encode_frame_to_data_rate
    • encode_with_recode_loop_and_filter
    • encode_with_recode_loop
    • av1_encode_frame
    • encode_frame_internal
    • encode_tiles
    • av1_encode_tile
    • av1_encode_sb_row
    • encode_sb_row
    • encode_nonrd_sb
    • encode_rd_sb

从main函数到编码一个SB

本文对main函数向下至编码一个SB之间的函数以图示作记录和简单说明每个函数的作用(身为一个底层码农还是先往下跳关注底层编码一个SB的算法和函数,上层函数的坑先浅挖,后续有时间再填上)。下图显示了AV1参考软件----AOM解决方案中aom_enc项目的函数调用结构(从main函数到处理一个SB)。图中可以看到从main函数到编码一个SB的函数要经过15层调用,目前确实不太有空仔细学习、分析这中间的每个函数,由于时间仓促难免有些描述错漏,若有读者发现还望不吝指出。
【AV1代码研究二】从main到编码一个SB----aomenc的函数调用结构_第1张图片

main

main函数的介绍请看【AV1代码研究一】万事开头难——aomenc main函数分析。

encode_frame

完成记录编码时长功能,当视频配置尺寸与输入视频尺寸不一致时会对输入视频进行缩放(只支持缩放Y:U:V 4:2:0格式的视频)。

aom_codec_encode

该函数调用encoder_encode()完成多尺度分辨率的编码,如有需要编码3个分辨率,则按level 2-level 1-level 0的顺序依次进行编码。(坑注:待确认哪个level的分辨率最大。)

encoder_encode

该函数中完成检查profile与编码图像格式的兼容性,初始化av1_lookahead等功能,然后调用av1_get_compressed_data编码一帧图像得到压缩后的码流,并在需要时将OBU以annexb的形式写出(av1_convert_sect5obus_to_annexb())。

av1_get_compressed_data

该函数调用av1_encode_strategy()进行编码,完成后计算重建图像的PSNR。同时会通过函数av1_init_level_info()初始化一些level 信息。

av1_encode_strategy

该函数涉及编码策略相关的功能,如比特分配、编码速度配置等。同时完成参考帧的填充和选取,此后调用denoise_and_encode()完成编码,编码后更新参考帧map和码流控制相关信息(update_rc_counts())。

denoise_and_encode

从函数名可以看出该函数会实施降噪操作,通过函数av1_estimate_noise_from_single_plane()使用soble梯度算子评估噪声程度。若噪声程度、帧类型(要求为KEY_FRAME)和其他一些条件成立,则会对该帧进行时域滤波。时域滤波通过av1_temporal_filter()完成。 此后调用函数av1_encode()进行编码。

av1_encode

这个函数比较简单,进行一些参数赋值后调用encode_frame_to_data_rate()进行编码。

encode_frame_to_data_rate

该函数首先会根据refresh_frame_flags刷新一下参考帧buffer,然后调用函数encode_with_recode_loop_and_filter()进行编码和滤波。注意若有超分辨率图像编码的话,则会调用encode_with_and_without_superres()。编码完成后再次刷新参考帧buffer,及进行rc相关的更新(av1_rc_postencode_update())。

encode_with_recode_loop_and_filter

该函数主要调用encode_with_recode_loop()进行编码,编码完成后调用loopfilter_frame()进行滤波,并通过av1_pack_bitstream()将码流pack好。最后计算sse和rate。
av1_pack_bitstream()函数会生成包括Sequence Header OBU、Metadata OBU、Frame Header OBU、Tile Group OBU在内的数据。

encode_with_recode_loop

该函数首先设置超分辨率图像尺寸相关的信息,然后决策是否使用屏幕内容编码的工具。接着设置量化相关的参数和基于方差进行分块的一些门限值。最终调用av1_encode_frame()进行下一步编码。编码完成后会“虚假”地打包一次码流,用码流的大小判断是否需要重新编码,若允许的话会再次调用av1_encode_frame()进行编码。

av1_encode_frame

进行一些和参考帧相关的处理后调用encode_frame_internal()进行真正的编码。

encode_frame_internal

初始化量化器,初始化率失真决策和运动估计相关的常量。如果当前帧是INTER_FRAME的话会计算两个方向局运动信息。最后根据多线程配置的不同分别选择av1_encode_tiles_row_mt()、av1_encode_tiles_mt()、encode_tiles()进行tile级的编码。

encode_tiles

根据图像划分tile的情况,调用av1_encode_tile()完成每个tile的编码。

av1_encode_tile

初始化above context后调用*av1_encode_sb_row()*完成每个SB行的编码。

av1_encode_sb_row

主要调用av1_encode_sb_row()进行真正的SB行的编码。

encode_sb_row

首先初始化left context,如何按顺序编码当前SB行的每个SB。根据配置的不同分别选择encode_nonrd_sb()、encode_rd_sb()进行编码。encode_nonrd_sb()、encode_rd_sb()这两个函数后文仅进行简单描述,会另起文章分析,毕竟已经到编码每个SB的底层过程了。

encode_nonrd_sb

从函数名看是使用非rd决策的编码方法,函数内部涉及方差、固定分块等内容。

encode_rd_sb

函数内部根据partition_search_type的不同取值对应不同的处理方式:FIXED_PARTITION、VAR_BASED_PARTITION通过递归调用rd_use_partition()进行划分和模式决策;SEARCH_PARTITION 则通过rd_pick_partition进行划分及模式决策。

你可能感兴趣的:(AV1代码学习)