美文网首页
av1代码学习7---encode_with_recode_lo

av1代码学习7---encode_with_recode_lo

作者: 青吟乐 | 来源:发表于2020-06-23 10:59 被阅读0次

    1,函数功能

    该函数主要置量化相关的参数和分块信息后进行编码,编码之后会根据打包的码流大小判断是否谁需要重新编码(loop)。

    2,代码学习

    static int encode_with_recode_loop(AV1_COMP *cpi, size_t *size, uint8_t *dest) {
      AV1_COMMON *const cm = &cpi->common;
      RATE_CONTROL *const rc = &cpi->rc;
      const int allow_recode = (cpi->sf.recode_loop != DISALLOW_RECODE);
    
      set_size_independent_vars(cpi);
    
      cpi->source->buf_8bit_valid = 0;
    
      av1_setup_frame_size(cpi);
    
      int top_index = 0, bottom_index = 0;
      int q = 0, q_low = 0, q_high = 0;
      set_size_dependent_vars(cpi, &q, &bottom_index, &top_index);
      q_low = bottom_index;
      q_high = top_index;
    
      // Loop variables
      int loop_count = 0;
      int loop_at_this_size = 0;
      int loop = 0;
      int overshoot_seen = 0;
      int undershoot_seen = 0;
      int low_cr_seen = 0;
    
    #if CONFIG_COLLECT_COMPONENT_TIMING
      printf("\n Encoding a frame:");
    #endif
      do {//loop为1的话
        loop = 0;
        aom_clear_system_state();
    
        // if frame was scaled calculate global_motion_search again if already
        // done
        //帧的缩放做过了的话再次进行全局运动搜索(即全局运动搜索的标志位置0)
        if (loop_count > 0 && cpi->source && cpi->global_motion_search_done) {
          if (cpi->source->y_crop_width != cm->width ||
              cpi->source->y_crop_height != cm->height) {
            cpi->global_motion_search_done = 0;
          }
        }
        //帧缩放
        cpi->source =
            av1_scale_if_required(cm, cpi->unscaled_source, &cpi->scaled_source);
        //前一帧缩放
        if (cpi->unscaled_last_source != NULL) {
          cpi->last_source = av1_scale_if_required(cm, cpi->unscaled_last_source,
                                                   &cpi->scaled_last_source);
        }
        //关键帧或者只能帧内编码的时候
        if (!frame_is_intra_only(cm)) {
          if (loop_count > 0) {
            release_scaled_references(cpi);//释放帧间参考帧列表
          }
          scale_references(cpi);//量化参考帧列表
        }
        av1_set_quantizer(cm, q);
        av1_init_quantizer(cpi);
    
        av1_set_variance_partition_thresholds(cpi, q, 0);
    
        //printf("Frame %d/%d: q = %d, frame_type = %d superres_denom = %d\n",
        //        cm->current_frame.frame_number, cm->show_frame, q,
        //        cm->current_frame.frame_type, cm->superres_scale_denominator);
    
        if (loop_count == 0) {
          setup_frame(cpi);
        } else if (get_primary_ref_frame_buf(cm) == NULL) {
          // Base q-index may have changed, so we need to assign proper default coef
          // probs before every iteration.
          av1_default_coef_probs(cm);
          av1_setup_frame_contexts(cm);
        }
        //根据量化建立索引?
        if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
          av1_vaq_frame_setup(cpi);
        } else if (cpi->oxcf.aq_mode == COMPLEXITY_AQ) {
          av1_setup_in_frame_q_adj(cpi);
        } else if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && !allow_recode) {
          suppress_active_map(cpi);
          av1_cyclic_refresh_setup(cpi);
          apply_active_map(cpi);
        }
    
        if (cm->seg.enabled) {//如果分块的话
          if (!cm->seg.update_data && cm->prev_frame) {//前一帧存在并且划分未更新
            segfeatures_copy(&cm->seg, &cm->prev_frame->seg);//复制前一帧的划分给cm-seg
          } else {
            av1_calculate_segdata(&cm->seg);//前一帧不存在则计算当前的&cm->seg
          }
        } else {//不进行划分则直接申请cm->seg的空间
          memset(&cm->seg, 0, sizeof(cm->seg));
        }
        segfeatures_copy(&cm->cur_frame->seg, &cm->seg);//将cm->seg赋予当前帧的划分
    
        if (allow_recode) save_coding_context(cpi);
    #if CONFIG_COLLECT_COMPONENT_TIMING
        start_timing(cpi, av1_encode_frame_time);
    #endif
        // transform / motion compensation build reconstruction frame
        av1_encode_frame(cpi);//编码
    #if CONFIG_COLLECT_COMPONENT_TIMING
        end_timing(cpi, av1_encode_frame_time);
    #endif
    
        aom_clear_system_state();
    
        // Dummy pack of the bitstream using up to date stats to get an
        // accurate estimate of output frame size to determine if we need
        // to recode.,根据已经编码好的码流大小判断是否进行重新编码
        if (cpi->sf.recode_loop >= ALLOW_RECODE_KFARFGF) {
          restore_coding_context(cpi);
    
          finalize_encoded_frame(cpi);
          int largest_tile_id = 0;  // Output from bitstream: unused here
          if (av1_pack_bitstream(cpi, dest, size, &largest_tile_id) != AOM_CODEC_OK)
            return AOM_CODEC_ERROR;
    
          rc->projected_frame_size = (int)(*size) << 3;
          restore_coding_context(cpi);
        }
        //重新编码
        if (allow_recode) {
          // Update q and decide whether to do a recode loop
          recode_loop_update_q(cpi, &loop, &q, &q_low, &q_high, top_index,
                               bottom_index, &undershoot_seen, &overshoot_seen,
                               &low_cr_seen, loop_at_this_size);
        }
    
        // Special case for overlay frame.
        if (rc->is_src_frame_alt_ref &&
            rc->projected_frame_size < rc->max_frame_bandwidth)
          loop = 0;
    
        if (allow_recode && !cpi->sf.gm_disable_recode &&
            recode_loop_test_global_motion(cpi)) {
          loop = 1;
        }
    
        if (cpi->tpl_model_pass == 1) {
          assert(cpi->oxcf.enable_tpl_model == 2);
          av1_tpl_setup_forward_stats(cpi);
          cpi->tpl_model_pass = 0;
          loop = 1;
        }
    
        if (loop) {
          ++loop_count;
          ++loop_at_this_size;
    
    #if CONFIG_INTERNAL_STATS
          ++cpi->tot_recode_hits;
    #endif
        }
    #if CONFIG_COLLECT_COMPONENT_TIMING
        if (loop) printf("\n Recoding:");
    #endif
      } while (loop);
    
      return AOM_CODEC_OK;
    }
    

    相关文章

      网友评论

          本文标题:av1代码学习7---encode_with_recode_lo

          本文链接:https://www.haomeiwen.com/subject/ufvcfktx.html