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相关推荐

  1. AV1代码学习3:函数aom_codec_encode

    函数aom_codec_encode主要就是根据命令行参数--cpu-used来决定num_enc, 通常情况下,为了通测方便,--cpu-used都是设置为1. 提高--cpu-used的数值会加快 ...

  2. AV1代码学习:av1_foreach_transformed_block_in_plane函数

    在AV1中,进行预测变换都是基于Transform Block(变换块)进行的,变换块一共19种尺寸,并且其尺寸通常是小于或者等于编码块尺寸的,如下代码所示. enum {TX_4X4, // 4x4 ...

  3. AV1代码学习6:函数av1_encode和 av1_first_pass

    av1_encode没什么特别好说的,会把在av1_encode_strategy的参数(EncodeFrameInput和EncodeFrameParams)赋给结构体AV1_COMP和AV1_CO ...

  4. AV1代码学习6:tpl_model之一

    AV1的tpl_model是AV1的一个c文件,包含了一系列函数,其主要目的是为了利用lookahead design记录每个块的一些数据,包括失真等,在实际编码时利用这些数据建立模型,调整QP或者l ...

  5. 通过FFMPEG代码学习函数指针和指针函数

    2019独角兽企业重金招聘Python工程师标准>>> 函数指针和指针函数介绍 函数指针和指针函数一直在工作中会用到,现在mark下.部分内容是参考其他人的总结. 1. 函数指针是指 ...

  6. AV1代码学习6:tpl_model之二

    mode_estimation字面意思就是模式估计,实质上是对帧内和帧间的模式进行遍历.帧内预测选取了13种模式,主要是DC模式.角度模式和新加入的PAETH模式.帧间对7个参考帧进行遍历,寻找COS ...

  7. H.266代码学习:decompressCtu和xDecompressCU函数

    今天来学习一下JEM的decompressCtu和xDecompressCU函数.之前在 H.266代码学习:decodeCtu和xDecodeCU函数 学习了的学习中提到,decodeCtu和xDe ...

  8. HEVC代码学习42:estIntraPredLumaQT函数

    在之前的 HEVC代码学习37:帧内预测代码整体学习 中已经提到,estIntraPredLumaQT是亮度帧内预测的入口函数,下面将对该函数进行详细学习. estIntraPredLumaQT中完成 ...

  9. H.266/VVC-VTM代码学习27-VTM中编码器主函数逻辑

    H.266/VVC专栏传送 上一篇:H.266/VVC-VTM代码学习26-VTM中RDcost的计算与λ的设定(二) 下一篇:持续创作中- 目录 H.266/VVC专栏传送 前言 一.简介 二.代码 ...

最新文章

  1. Redis中五大数据结构的底层实现
  2. viewGroup 项目中使用
  3. ASP.NET Core 中间件之压缩、缓存
  4. 洛谷 P3383 【模板】线性筛素数
  5. 大学毕业出路利弊浅谈
  6. 华为云提供针对Nuget包管理器的缓存加速服务测试
  7. JBDC操作事务源码解析
  8. 中职计算机优质课课件ppt,中职优质课 交集课件.ppt
  9. plc secs通讯协议_一种SECSGEM通讯协议转换的方法与流程
  10. ICMP协议个人分析
  11. position的8种定位方式
  12. 阴历阳历的相互转换(支持1900~2100年) 1
  13. Fiddler报文分析-断点应用、模拟网络限速-HTTPS的 拦截
  14. 英文wiki技术基础问题查询的常见问题
  15. Scrum实践指南:一个可运行的Scrum是怎样的
  16. 基于Vue.js和Node.js的个人网盘系统——科技立项中期成果
  17. C++使用ADODB连接数据库
  18. 用c语言编写棋盘以及光标,C语言实习指导书.doc
  19. plc的毕业设计冷门题目_PLC毕业设计题目
  20. Java实现opendir的api_linux文件操作API

热门文章

  1. 如何在任意文件夹下打开cmd
  2. 元宇宙大投资-2、抓紧元宇宙本质
  3. 【计网第一章 概述】
  4. Python程序的错误:变量未定义(NameError: name ‘mesage’ is not defined.)
  5. 累计增量备份策略_RMAN增量备份中的差异增量和累积增量
  6. 后台删除数据一定要谨慎,再谨慎
  7. Spring是什么?一文带你快速入门Spring
  8. 2016首届对象存储技术及应用大会在京成功召开
  9. 电子地图的格式有哪些种类?
  10. 上海亚商投顾:沪指缩量调整跌超1% 新能源车产业链掀涨停潮