从代码角度解析av1 超分辨率模式

简介

av1 超分辨率功能允许以较低的分辨率对帧进行编码,然后在编码后循环恢复过程中对其进行超分辨率(其实就是采样上来)解析

目前的使用方法

在命令行中,主要使用superres-mode 命令开启 0-不开启,1-固定分辨率开启,2-随机分辨率开启,开启后有一个superres-denominator 代表一个分母,superres-kf-denominator代表关键帧的分母,具体的分辨率由8/分母决定。

代码过程

1、命令参数中读入

首先从aomenc中,将命令行读入config中,如下所示


2、导入cpi->oxcf

在av1_cx_iface.c文件中,用set_encoder_config()方法,这个方法读取所有配置文件信息,下面的代码只给出了需要的超分辨率信息,superres_cfg 是配置文件oxcf的对应superres_cfg的别名SuperResCfg *const superres_cfg = &oxcf->superres_cfg;

if (extra_cfg->lossless || cfg->large_scale_tile) {
    disable_superres(superres_cfg);
  } else {
    superres_cfg->superres_mode = cfg->rc_superres_mode;
    superres_cfg->superres_scale_denominator =
        (uint8_t)cfg->rc_superres_denominator;
    superres_cfg->superres_kf_scale_denominator =
        (uint8_t)cfg->rc_superres_kf_denominator;
    superres_cfg->superres_qthresh = cfg->rc_superres_qthresh;
    superres_cfg->superres_kf_qthresh = cfg->rc_superres_kf_qthresh;
    if (superres_cfg->superres_mode == AOM_SUPERRES_FIXED &&
        superres_cfg->superres_scale_denominator == SCALE_NUMERATOR &&
        superres_cfg->superres_kf_scale_denominator == SCALE_NUMERATOR) {
      disable_superres(superres_cfg);
    }
    if (superres_cfg->superres_mode == AOM_SUPERRES_QTHRESH &&
        superres_cfg->superres_qthresh == 255 &&
        superres_cfg->superres_kf_qthresh == 255) {
      disable_superres(superres_cfg);
    }
  }

  superres_cfg->enable_superres =
      (superres_cfg->superres_mode != AOM_SUPERRES_NONE) &&
      extra_cfg->enable_superres;
  if (!superres_cfg->enable_superres) {
    disable_superres(superres_cfg);
  }
3、设置帧大小

这里的起始位置是av1_setup_frame_size()这个函数,在superres_scale.c
中,在encoder.c的预处理环节被用到,根据之前的superres设置,设置帧的大小
下面具体说一下,calculate_next_size_params这个函数主要是进行一些初始化的设置,但对于superres模式来讲,在这个函数中将我们命令行的分母拿到了,存在了rsz.superres_demo中。这里注意,在第一次编码,也就是av1_first_pass()时,相关的信息就已经处理好了

void av1_setup_frame_size(AV1_COMP *cpi) {
  AV1_COMMON *cm = &cpi->common;
  // Reset superres params from previous frame.
  cm->superres_scale_denominator = SCALE_NUMERATOR;
  const size_params_type rsz = calculate_next_size_params(cpi);
  setup_frame_size_from_params(cpi, &rsz);

  assert(av1_is_min_tile_width_satisfied(cm));
}

cm->superres_scale_denominator = SCALE_NUMERATOR是给定一个分子,用来控制分辨率。这里是8
而后主要根据setup_frame_size_from_params(cpi, &rsz);这个函数来计算和设置帧的大小

其中cm中也要设置分母,先从rsz中获取到分母,然后用av1_calculate_scaled_superres_size(&encode_width, &encode_height,
                                     rsz->superres_denom);去计算超分辨率后的帧大小,最后用av1_set_frame_siz()方法进行申请空间和图像的下采样。

static void setup_frame_size_from_params(AV1_COMP *cpi,
                                         const size_params_type *rsz) {
  int encode_width = rsz->resize_width;
  int encode_height = rsz->resize_height;

  AV1_COMMON *cm = &cpi->common;
  cm->superres_upscaled_width = encode_width;
  cm->superres_upscaled_height = encode_height;
  cm->superres_scale_denominator = rsz->superres_denom;
  printf("\n%d,%d\n", encode_width, encode_height);
  //计算超分辨率模式的大小
  av1_calculate_scaled_superres_size(&encode_width, &encode_height,
                                     rsz->superres_denom);
  printf("\n%d,%d\n", encode_width, encode_height);
  
  av1_set_frame_size(cpi, encode_width, encode_height);
}```

#####5、滤波后还原过程

你可能感兴趣的:(从代码角度解析av1 超分辨率模式)