AV1代码学习:函数encode_frame和aom_codec_encode
1.encode_frame函数
在编码端aomenc.c的main函数中,在进入编码过程循环后,循环读取视频的每一帧数据,然后通过encode_frame函数对每一帧进行编码。
encode_frame函数主要是进行一些当前帧进行放缩的工作,并启动计时器,然后调用aom_codec_encode函数进行编码。
static void encode_frame(struct stream_state *stream,struct AvxEncoderConfig *global, struct aom_image *img,unsigned int frames_in) {aom_codec_pts_t frame_start, next_frame_start; //起始时间戳struct aom_codec_enc_cfg *cfg = &stream->config.cfg;struct aom_usec_timer timer;frame_start =(cfg->g_timebase.den * (int64_t)(frames_in - 1) * global->framerate.den) /cfg->g_timebase.num / global->framerate.num;next_frame_start =(cfg->g_timebase.den * (int64_t)(frames_in)*global->framerate.den) /cfg->g_timebase.num / global->framerate.num;/* Scale if necessary */if (img) {if ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) &&(img->d_w != cfg->g_w || img->d_h != cfg->g_h)) {if (img->fmt != AOM_IMG_FMT_I42016) {fprintf(stderr, "%s can only scale 4:2:0 inputs\n", exec_name);exit(EXIT_FAILURE);}
#if CONFIG_LIBYUVif (!stream->img) {stream->img =aom_img_alloc(NULL, AOM_IMG_FMT_I42016, cfg->g_w, cfg->g_h, 16);}I420Scale_16((uint16_t *)img->planes[AOM_PLANE_Y], img->stride[AOM_PLANE_Y] / 2,(uint16_t *)img->planes[AOM_PLANE_U], img->stride[AOM_PLANE_U] / 2,(uint16_t *)img->planes[AOM_PLANE_V], img->stride[AOM_PLANE_V] / 2,img->d_w, img->d_h, (uint16_t *)stream->img->planes[AOM_PLANE_Y],stream->img->stride[AOM_PLANE_Y] / 2,(uint16_t *)stream->img->planes[AOM_PLANE_U],stream->img->stride[AOM_PLANE_U] / 2,(uint16_t *)stream->img->planes[AOM_PLANE_V],stream->img->stride[AOM_PLANE_V] / 2, stream->img->d_w,stream->img->d_h, kFilterBox);img = stream->img;
#elsestream->encoder.err = 1;ctx_exit_on_error(&stream->encoder,"Stream %d: Failed to encode frame.\n""libyuv is required for scaling but is currently ""disabled.\n""Be sure to specify -DCONFIG_LIBYUV=1 when running ""cmake.\n",stream->index);
#endif}}if (img && (img->d_w != cfg->g_w || img->d_h != cfg->g_h)) {if (img->fmt != AOM_IMG_FMT_I420 && img->fmt != AOM_IMG_FMT_YV12) {fprintf(stderr, "%s can only scale 4:2:0 8bpp inputs\n", exec_name);exit(EXIT_FAILURE);}
#if CONFIG_LIBYUVif (!stream->img)stream->img =aom_img_alloc(NULL, AOM_IMG_FMT_I420, cfg->g_w, cfg->g_h, 16);I420Scale(img->planes[AOM_PLANE_Y], img->stride[AOM_PLANE_Y],img->planes[AOM_PLANE_U], img->stride[AOM_PLANE_U],img->planes[AOM_PLANE_V], img->stride[AOM_PLANE_V], img->d_w, img->d_h,stream->img->planes[AOM_PLANE_Y], stream->img->stride[AOM_PLANE_Y],stream->img->planes[AOM_PLANE_U], stream->img->stride[AOM_PLANE_U],stream->img->planes[AOM_PLANE_V], stream->img->stride[AOM_PLANE_V],stream->img->d_w, stream->img->d_h, kFilterBox);img = stream->img;
#elsestream->encoder.err = 1;ctx_exit_on_error(&stream->encoder,"Stream %d: Failed to encode frame.\n""Scaling disabled in this configuration. \n""To enable, configure with --enable-libyuv\n",stream->index);
#endif}aom_usec_timer_start(&timer);aom_codec_encode(&stream->encoder, img, frame_start,(uint32_t)(next_frame_start - frame_start), 0);aom_usec_timer_mark(&timer);stream->cx_time += aom_usec_timer_elapsed(&timer);ctx_exit_on_error(&stream->encoder, "Stream %d: Failed to encode frame",stream->index);
}
2.aom_codec_encode函数
该函数主要作用是编码一帧。在给定的“presentation time.”对视频帧进行编码。演示时间戳(PTS)必须严格增加。
aom_codec_err_t aom_codec_encode(aom_codec_ctx_t *ctx, const aom_image_t *img,aom_codec_pts_t pts, unsigned long duration,aom_enc_frame_flags_t flags);
aom_codec_ctx_t 编解码器上下文结构,用户代码和编解码器之间的实际接口
所有编解码器必须完全支持此上下文结构。一般来说,这些数据应该被认为是编解码器算法的私有数据,而不是由调用应用程序操作或检查的。应用程序可以引用“name”成员来获得算法的可打印描述。
它存储编解码器的名称、指向初始化它的aom编解码器的指针、初始化标志、编码器或解码器的配置以及指向内部数据的指针。
typedef struct aom_codec_ctx {const char *name; /**< Printable interface name 可打印接口名称 */aom_codec_iface_t *iface; /**< Interface pointers 接口指针*/aom_codec_err_t err; /**< Last returned error 上次返回的错误*/const char *err_detail; /**< Detailed info, if available 详细信息(如果有) */aom_codec_flags_t init_flags; /**< Flags passed at init time 初始化时传递的标志*/union {/**< Decoder Configuration Pointer 解码器配置指针 */const struct aom_codec_dec_cfg *dec;/**< Encoder Configuration Pointer */const struct aom_codec_enc_cfg *enc;const void *raw;} config; /**< Configuration pointer aliasing union */aom_codec_priv_t *priv; /**< Algorithm private storage 算法专用存储 */
} aom_codec_ctx_t;
参数:
- ctx指向此实例上下文的ctx指针
- img要编码的img图像数据,为NULL表示刷新缓冲区。
- pts演示时间戳,以时基单位表示。
- duration显示帧的持续时间,以时基单位为单位。
- flags用于编码此帧的标志。
返回值:
- AOM_CODEC_OK:操作已完成,没有错误。
- AOM_CODEC_INCAPABLE:算法没有所需的功能。
- AOM_CODEC_INVALID_PARAM:应用程序提供的参数无效,图像格式不受支持,等等
当最后一帧已传递给编码器时,应继续调用此函数,并将img参数设置为NULL。这将向编码器发送流结束条件的信号,并允许它对任何保留的缓冲区进行编码。当调用aom_codec_encode()且aom_codec_get_cx_data()未返回任何数据时,编码完成。
该函数主要是调用encoder_encode进行编码。
aom_codec_err_t aom_codec_encode(aom_codec_ctx_t *ctx, const aom_image_t *img,aom_codec_pts_t pts, unsigned long duration,aom_enc_frame_flags_t flags) {aom_codec_err_t res = AOM_CODEC_OK;if (!ctx || (img && !duration))res = AOM_CODEC_INVALID_PARAM;else if (!ctx->iface || !ctx->priv)res = AOM_CODEC_ERROR;else if (!(ctx->iface->caps & AOM_CODEC_CAP_ENCODER))res = AOM_CODEC_INCAPABLE;else {/* Execute in a normalized floating point environment, if the platform* requires it.*/FLOATING_POINT_INITres = ctx->iface->enc.encode(get_alg_priv(ctx), img, pts, duration, flags);FLOATING_POINT_RESTORE}
该函数通过get_alg_priv()函数获取aom_codec_ctx_t结构体中的aom_codec_priv_t指针
static aom_codec_alg_priv_t *get_alg_priv(aom_codec_ctx_t *ctx) {return (aom_codec_alg_priv_t *)ctx->priv;
}
aom_codec_priv_t
编解码器私有数据结构。
包含编解码器实现专用的数据。此结构对应用程序不透明。
AV1代码学习:函数encode_frame和aom_codec_encode相关推荐
- AV1代码学习3:函数aom_codec_encode
函数aom_codec_encode主要就是根据命令行参数--cpu-used来决定num_enc, 通常情况下,为了通测方便,--cpu-used都是设置为1. 提高--cpu-used的数值会加快 ...
- AV1代码学习:av1_foreach_transformed_block_in_plane函数
在AV1中,进行预测变换都是基于Transform Block(变换块)进行的,变换块一共19种尺寸,并且其尺寸通常是小于或者等于编码块尺寸的,如下代码所示. enum {TX_4X4, // 4x4 ...
- AV1代码学习6:函数av1_encode和 av1_first_pass
av1_encode没什么特别好说的,会把在av1_encode_strategy的参数(EncodeFrameInput和EncodeFrameParams)赋给结构体AV1_COMP和AV1_CO ...
- AV1代码学习6:tpl_model之一
AV1的tpl_model是AV1的一个c文件,包含了一系列函数,其主要目的是为了利用lookahead design记录每个块的一些数据,包括失真等,在实际编码时利用这些数据建立模型,调整QP或者l ...
- 通过FFMPEG代码学习函数指针和指针函数
2019独角兽企业重金招聘Python工程师标准>>> 函数指针和指针函数介绍 函数指针和指针函数一直在工作中会用到,现在mark下.部分内容是参考其他人的总结. 1. 函数指针是指 ...
- AV1代码学习6:tpl_model之二
mode_estimation字面意思就是模式估计,实质上是对帧内和帧间的模式进行遍历.帧内预测选取了13种模式,主要是DC模式.角度模式和新加入的PAETH模式.帧间对7个参考帧进行遍历,寻找COS ...
- H.266代码学习:decompressCtu和xDecompressCU函数
今天来学习一下JEM的decompressCtu和xDecompressCU函数.之前在 H.266代码学习:decodeCtu和xDecodeCU函数 学习了的学习中提到,decodeCtu和xDe ...
- HEVC代码学习42:estIntraPredLumaQT函数
在之前的 HEVC代码学习37:帧内预测代码整体学习 中已经提到,estIntraPredLumaQT是亮度帧内预测的入口函数,下面将对该函数进行详细学习. estIntraPredLumaQT中完成 ...
- H.266/VVC-VTM代码学习27-VTM中编码器主函数逻辑
H.266/VVC专栏传送 上一篇:H.266/VVC-VTM代码学习26-VTM中RDcost的计算与λ的设定(二) 下一篇:持续创作中- 目录 H.266/VVC专栏传送 前言 一.简介 二.代码 ...
最新文章
- Redis中五大数据结构的底层实现
- viewGroup 项目中使用
- ASP.NET Core 中间件之压缩、缓存
- 洛谷 P3383 【模板】线性筛素数
- 大学毕业出路利弊浅谈
- 华为云提供针对Nuget包管理器的缓存加速服务测试
- JBDC操作事务源码解析
- 中职计算机优质课课件ppt,中职优质课 交集课件.ppt
- plc secs通讯协议_一种SECSGEM通讯协议转换的方法与流程
- ICMP协议个人分析
- position的8种定位方式
- 阴历阳历的相互转换(支持1900~2100年) 1
- Fiddler报文分析-断点应用、模拟网络限速-HTTPS的 拦截
- 英文wiki技术基础问题查询的常见问题
- Scrum实践指南:一个可运行的Scrum是怎样的
- 基于Vue.js和Node.js的个人网盘系统——科技立项中期成果
- C++使用ADODB连接数据库
- 用c语言编写棋盘以及光标,C语言实习指导书.doc
- plc的毕业设计冷门题目_PLC毕业设计题目
- Java实现opendir的api_linux文件操作API