Home | History | Annotate | Download | only in encoder
      1 /*
      2  *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include <limits.h>
     12 #include <math.h>
     13 
     14 #include "vp9/common/vp9_seg_common.h"
     15 
     16 #include "vp9/encoder/vp9_segmentation.h"
     17 
     18 static const double in_frame_q_adj_ratio[MAX_SEGMENTS] =
     19   {1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
     20 
     21 void vp9_setup_in_frame_q_adj(VP9_COMP *cpi) {
     22   VP9_COMMON *const cm = &cpi->common;
     23   struct segmentation *const seg = &cm->seg;
     24 
     25   // Make SURE use of floating point in this function is safe.
     26   vp9_clear_system_state();
     27 
     28   if (cm->frame_type == KEY_FRAME ||
     29       cpi->refresh_alt_ref_frame ||
     30       (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)) {
     31     int segment;
     32 
     33     // Clear down the segment map.
     34     vpx_memset(cpi->segmentation_map, 0, cm->mi_rows * cm->mi_cols);
     35 
     36     // Clear down the complexity map used for rd.
     37     vpx_memset(cpi->complexity_map, 0, cm->mi_rows * cm->mi_cols);
     38 
     39     vp9_enable_segmentation(seg);
     40     vp9_clearall_segfeatures(seg);
     41 
     42     // Select delta coding method.
     43     seg->abs_delta = SEGMENT_DELTADATA;
     44 
     45     // Segment 0 "Q" feature is disabled so it defaults to the baseline Q.
     46     vp9_disable_segfeature(seg, 0, SEG_LVL_ALT_Q);
     47 
     48     // Use some of the segments for in frame Q adjustment.
     49     for (segment = 1; segment < 2; segment++) {
     50       const int qindex_delta =
     51           vp9_compute_qdelta_by_rate(cpi,
     52                                      cm->base_qindex,
     53                                      in_frame_q_adj_ratio[segment]);
     54       vp9_enable_segfeature(seg, segment, SEG_LVL_ALT_Q);
     55       vp9_set_segdata(seg, segment, SEG_LVL_ALT_Q, qindex_delta);
     56     }
     57   }
     58 }
     59 
     60 // Select a segment for the current SB64
     61 void vp9_select_in_frame_q_segment(VP9_COMP *cpi,
     62                                       int mi_row, int mi_col,
     63                                       int output_enabled, int projected_rate) {
     64   VP9_COMMON *const cm = &cpi->common;
     65 
     66   const int mi_offset = mi_row * cm->mi_cols + mi_col;
     67   const int bw = num_8x8_blocks_wide_lookup[BLOCK_64X64];
     68   const int bh = num_8x8_blocks_high_lookup[BLOCK_64X64];
     69   const int xmis = MIN(cm->mi_cols - mi_col, bw);
     70   const int ymis = MIN(cm->mi_rows - mi_row, bh);
     71   int complexity_metric = 64;
     72   int x, y;
     73 
     74   unsigned char segment;
     75 
     76   if (!output_enabled) {
     77     segment = 0;
     78   } else {
     79     // Rate depends on fraction of a SB64 in frame (xmis * ymis / bw * bh).
     80     // It is converted to bits * 256 units.
     81     const int target_rate = (cpi->rc.sb64_target_rate * xmis * ymis * 256) /
     82                             (bw * bh);
     83 
     84     if (projected_rate < (target_rate / 4)) {
     85       segment = 1;
     86     } else {
     87       segment = 0;
     88     }
     89 
     90     if (target_rate > 0) {
     91       complexity_metric =
     92         clamp((int)((projected_rate * 64) / target_rate), 16, 255);
     93     }
     94   }
     95 
     96   // Fill in the entires in the segment map corresponding to this SB64.
     97   for (y = 0; y < ymis; y++) {
     98     for (x = 0; x < xmis; x++) {
     99       cpi->segmentation_map[mi_offset + y * cm->mi_cols + x] = segment;
    100       cpi->complexity_map[mi_offset + y * cm->mi_cols + x] =
    101         (unsigned char)complexity_metric;
    102     }
    103   }
    104 }
    105