LCOV - code coverage report
Current view: top level - Codec - EbSegmentation.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 5 105 4.8 %
Date: 2019-11-25 17:38:06 Functions: 1 6 16.7 %

          Line data    Source code
       1             : /*
       2             : * Copyright(c) 2019 Intel Corporation
       3             : * SPDX - License - Identifier: BSD - 2 - Clause - Patent
       4             : */
       5             : 
       6             : /*
       7             : * Copyright (c) 2016, Alliance for Open Media. All rights reserved
       8             : *
       9             : * This source code is subject to the terms of the BSD 2 Clause License and
      10             : * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
      11             : * was not distributed with this source code in the LICENSE file, you can
      12             : * obtain it at www.aomedia.org/license/software. If the Alliance for Open
      13             : * Media Patent License 1.0 was not distributed with this source code in the
      14             : * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
      15             : */
      16             : 
      17             : #include "EbSegmentation.h"
      18             : #include "EbSegmentationParams.h"
      19             : #include "EbMotionEstimationContext.h"
      20             : 
      21             : const int segmentation_feature_signed[SEG_LVL_MAX] = {
      22             :         1, 1, 1, 1, 1, 0, 0, 0
      23             : };
      24             : 
      25             : const int segmentation_feature_bits[SEG_LVL_MAX] = {8, 6, 6, 6, 6, 3, 0, 0};
      26             : 
      27             : const int segmentation_feature_max[SEG_LVL_MAX] = {MAXQ,
      28             :                                                    MAX_LOOP_FILTER,
      29             :                                                    MAX_LOOP_FILTER,
      30             :                                                    MAX_LOOP_FILTER,
      31             :                                                    MAX_LOOP_FILTER,
      32             :                                                    7,
      33             :                                                    0,
      34             :                                                    0};
      35             : 
      36             : 
      37             : static const uint8_t q_index_to_quantizer[] = {
      38             :         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5,
      39             :         6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11,
      40             :         12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16,
      41             :         17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21,
      42             :         22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26,
      43             :         27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31,
      44             :         32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35, 36, 36, 36, 36,
      45             :         37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39, 40, 40, 40, 40, 41, 41, 41, 41,
      46             :         42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46,
      47             :         47, 47, 47, 47, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51,
      48             :         52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 56, 56, 56, 56,
      49             :         57, 57, 57, 57, 58, 58, 58, 58, 59, 59, 59, 59, 60, 60, 60, 60,
      50             :         61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 63
      51             : };
      52             : 
      53             : 
      54           0 : uint16_t get_variance_for_cu(const BlockGeom *blk_geom,
      55             :                              uint16_t *variance_ptr) {
      56             :     int index0, index1;
      57             :     //Assumes max CU size is 64
      58           0 :     switch (blk_geom->bsize) {
      59           0 :         case BLOCK_4X4:
      60             :         case BLOCK_4X8:
      61             :         case BLOCK_8X4:
      62             :         case BLOCK_8X8:
      63           0 :             index0 = index1 = ME_TIER_ZERO_PU_8x8_0 + ((blk_geom->origin_x >> 3) + blk_geom->origin_y);
      64           0 :             break;
      65             : 
      66           0 :         case BLOCK_8X16:
      67           0 :             index0 = ME_TIER_ZERO_PU_8x8_0 + ((blk_geom->origin_x >> 3) + blk_geom->origin_y);
      68           0 :             index1 = index0 + 1;
      69           0 :             break;
      70             : 
      71           0 :         case BLOCK_16X8:
      72           0 :             index0 = ME_TIER_ZERO_PU_8x8_0 + ((blk_geom->origin_x >> 3) + blk_geom->origin_y);
      73           0 :             index1 = index0 + blk_geom->origin_y;
      74           0 :             break;
      75             : 
      76           0 :         case BLOCK_4X16:
      77             :         case BLOCK_16X4:
      78             :         case BLOCK_16X16:
      79           0 :             index0 = index1 = ME_TIER_ZERO_PU_16x16_0 + ((blk_geom->origin_x >> 4) + (blk_geom->origin_y >> 2));
      80           0 :             break;
      81             : 
      82           0 :         case BLOCK_16X32:
      83           0 :             index0 = ME_TIER_ZERO_PU_16x16_0 + ((blk_geom->origin_x >> 4) + (blk_geom->origin_y >> 2));
      84           0 :             index1 = index0 + 1;
      85           0 :             break;
      86             : 
      87           0 :         case BLOCK_32X16:
      88           0 :             index0 = ME_TIER_ZERO_PU_16x16_0 + ((blk_geom->origin_x >> 4) + (blk_geom->origin_y >> 2));
      89           0 :             index1 = index0 + (blk_geom->origin_y >> 2);
      90           0 :             break;
      91             : 
      92           0 :         case BLOCK_8X32:
      93             :         case BLOCK_32X8:
      94             :         case BLOCK_32X32:
      95           0 :             index0 = index1 = ME_TIER_ZERO_PU_32x32_0 + ((blk_geom->origin_x >> 5) + (blk_geom->origin_y >> 4));
      96           0 :             break;
      97             : 
      98           0 :         case BLOCK_32X64:
      99           0 :             index0 = ME_TIER_ZERO_PU_32x32_0 + ((blk_geom->origin_x >> 5) + (blk_geom->origin_y >> 4));
     100           0 :             index1 = index0 + 1;
     101           0 :             break;
     102             : 
     103           0 :         case BLOCK_64X32:
     104           0 :             index0 = ME_TIER_ZERO_PU_32x32_0 + ((blk_geom->origin_x >> 5) + (blk_geom->origin_y >> 4));
     105           0 :             index1 = index0 + (blk_geom->origin_y >> 4);
     106           0 :             break;
     107             : 
     108           0 :         case BLOCK_64X64:
     109             :         case BLOCK_16X64:
     110             :         case BLOCK_64X16:
     111             :         default:
     112           0 :             index0 = index1 = 0;
     113           0 :             break;
     114             : 
     115             :     }
     116           0 :     return (variance_ptr[index0] + variance_ptr[index1]) >> 1;
     117             : 
     118             : }
     119             : 
     120           0 : void apply_segmentation_based_quantization(
     121             :         const BlockGeom *blk_geom,
     122             :         PictureControlSet *picture_control_set_ptr,
     123             :         LargestCodingUnit *sb_ptr,
     124             :         CodingUnit *cu_ptr) {
     125           0 :     uint16_t *variance_ptr = picture_control_set_ptr->parent_pcs_ptr->variance[sb_ptr->index];
     126           0 :     SegmentationParams *segmentation_params = &picture_control_set_ptr->parent_pcs_ptr->frm_hdr.segmentation_params;
     127           0 :     uint16_t variance = get_variance_for_cu(blk_geom, variance_ptr);
     128           0 :     for (int i = 0; i < MAX_SEGMENTS; i++) {
     129           0 :         if (variance <= segmentation_params->variance_bin_edge[i]) {
     130           0 :             cu_ptr->segment_id = i;
     131           0 :             break;
     132             :         }
     133             :     }
     134           0 :     int32_t q_index = picture_control_set_ptr->parent_pcs_ptr->frm_hdr.quantization_params.base_q_idx +
     135           0 :                       picture_control_set_ptr->parent_pcs_ptr->frm_hdr.segmentation_params.feature_data[cu_ptr->segment_id][SEG_LVL_ALT_Q];
     136           0 :     cu_ptr->qp = q_index_to_quantizer[q_index];
     137             : 
     138           0 : }
     139             : 
     140         120 : void setup_segmentation(
     141             :         PictureControlSet *picture_control_set_ptr,
     142             :         SequenceControlSet *sequence_control_set_ptr,
     143             :         RateControlLayerContext *rateControlLayerPtr)
     144             : {
     145         120 :     SegmentationParams *segmentation_params = &picture_control_set_ptr->parent_pcs_ptr->frm_hdr.segmentation_params;
     146         120 :     segmentation_params->segmentation_enabled = (EbBool)(sequence_control_set_ptr->static_config.enable_adaptive_quantization == 1);
     147         120 :     if (segmentation_params->segmentation_enabled) {
     148           0 :         int32_t segment_qps[MAX_SEGMENTS] = {0};
     149           0 :         segmentation_params->segmentation_update_data = 1; //always updating for now. Need to set this based on actual deltas
     150           0 :         segmentation_params->segmentation_update_map = 1;
     151           0 :         segmentation_params->segmentation_temporal_update = EB_FALSE; //!(picture_control_set_ptr->parent_pcs_ptr->av1FrameType == KEY_FRAME || picture_control_set_ptr->parent_pcs_ptr->av1FrameType == INTRA_ONLY_FRAME);
     152           0 :         find_segment_qps(segmentation_params, picture_control_set_ptr);
     153           0 :         temporally_update_qps(segment_qps, rateControlLayerPtr->prev_segment_qps,
     154           0 :                               segmentation_params->segmentation_temporal_update);
     155           0 :         for (int i = 0; i < MAX_SEGMENTS; i++)
     156           0 :             segmentation_params->feature_enabled[i][SEG_LVL_ALT_Q] = 1;
     157             : 
     158           0 :         calculate_segmentation_data(segmentation_params);
     159             :     }
     160             : 
     161         120 : }
     162             : 
     163           0 : void calculate_segmentation_data(SegmentationParams *segmentation_params) {
     164           0 :     for (int i = 0; i < MAX_SEGMENTS; i++) {
     165           0 :         for (int j = 0; j < SEG_LVL_MAX; j++) {
     166           0 :             if (segmentation_params->feature_enabled[i][j]) {
     167           0 :                 segmentation_params->last_active_seg_id = i;
     168           0 :                 if (j >= SEG_LVL_REF_FRAME) {
     169           0 :                     segmentation_params->seg_id_pre_skip = 1;
     170             :                 }
     171             :             }
     172             :         }
     173             :     }
     174           0 : }
     175             : 
     176           0 : void find_segment_qps(
     177             :         SegmentationParams *segmentation_params,
     178             :         PictureControlSet *picture_control_set_ptr) { //QP needs to be specified as qpindex, not qp.
     179             : 
     180             :     uint16_t *variancePtr;
     181           0 :     uint16_t min_var = UINT16_MAX, max_var = MIN_UNSIGNED_VALUE, avg_var = 0;
     182           0 :     float strength = 2;//to tune
     183             : 
     184             :     // get range of variance
     185           0 :     for (uint32_t lcuIdx = 0; lcuIdx < picture_control_set_ptr->sb_total_count; ++lcuIdx) {
     186           0 :         variancePtr = picture_control_set_ptr->parent_pcs_ptr->variance[lcuIdx];
     187           0 :         uint32_t var_index, local_avg = 0;
     188             :         // Loop over all 8x8s in a 64x64
     189           0 :         for (var_index = ME_TIER_ZERO_PU_8x8_0; var_index <= ME_TIER_ZERO_PU_8x8_63; var_index++) {
     190           0 :             max_var = MAX(max_var, variancePtr[var_index]);
     191           0 :             min_var = MIN(min_var, variancePtr[var_index]);
     192           0 :             local_avg += variancePtr[var_index];
     193             :         }
     194           0 :         avg_var += (local_avg >> 6);
     195             :     }
     196           0 :     avg_var /= picture_control_set_ptr->sb_total_count;
     197           0 :     avg_var = Log2f(avg_var);
     198             : 
     199             :     //get variance bin edges & QPs
     200           0 :     uint16_t min_var_log = Log2f(MAX(1, min_var));
     201           0 :     uint16_t max_var_log = Log2f(MAX(1, max_var));
     202           0 :     uint16_t step_size = (uint16_t)(max_var_log - min_var_log) <= MAX_SEGMENTS ? 1 : ROUND(
     203             :             ((max_var_log - min_var_log)) / MAX_SEGMENTS);
     204           0 :     uint16_t bin_edge = min_var_log + step_size;
     205           0 :     uint16_t bin_center = bin_edge >> 1;
     206             : 
     207           0 :     for (int i = 0; i < MAX_SEGMENTS; i++) {
     208           0 :         segmentation_params->variance_bin_edge[i] = POW2(bin_edge);
     209           0 :         segmentation_params->feature_data[i][SEG_LVL_ALT_Q] =
     210           0 :             ROUND((uint16_t)strength * (MAX(1, bin_center) - avg_var));
     211           0 :         bin_edge += step_size;
     212           0 :         bin_center += step_size;
     213             :     }
     214             : 
     215           0 : }
     216             : 
     217           0 : void temporally_update_qps(
     218             :         int32_t *segment_qp_ptr,
     219             :         int32_t *prev_segment_qp_ptr,
     220             :         EbBool temporal_update) {
     221           0 :     for (int i = 0; i < MAX_SEGMENTS; i++) {
     222           0 :         int32_t diff = segment_qp_ptr[i] - prev_segment_qp_ptr[i];
     223           0 :         prev_segment_qp_ptr[i] = segment_qp_ptr[i];
     224           0 :         segment_qp_ptr[i] = temporal_update ? diff : segment_qp_ptr[i];
     225             :     }
     226           0 : }

Generated by: LCOV version 1.14