AV1コード学習:関数encode_frameおよびaom_codec_encode

1.encode_frame関数

エンコード終了のaomenc.cのメイン関数では、エンコードプロセスループに入った後、ループ内のビデオの各フレームを読み取り、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_LIBYUV
      if (!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;
#else
      stream->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_LIBYUV
    if (!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;
#else
    stream->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関数

この関数の主な機能は、フレームをエンコードすることです。特定の「プレゼンテーション時間」にビデオフレームをエンコードします。プレゼンテーションのタイムスタンプ(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は、タイムベース単位で表されたタイムスタンプを示します。
  • 期間は、フレームの期間をタイムベースの単位で表示します。
  • フラグは、このフレームのフラグをエンコードするために使用されます。

戻り値:

  • 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_INIT
    res = ctx->iface->enc.encode(get_alg_priv(ctx), img, pts, duration, flags);
    FLOATING_POINT_RESTORE
  }

aom_codec_ctx_t構造体aom_codec_priv_tポインターを取得するget_alg_priv()関数による関数

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

コーデックのプライベートデータ構造。
コーデックの実装に固有のデータが含まれています。この構造は、アプリケーションに対して透過的ではありません。

おすすめ

転載: blog.csdn.net/BigDream123/article/details/109466387