Home | History | Annotate | Download | only in common
      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 "./vpx_config.h"
     12 #include "vpx_dsp/vpx_dsp_common.h"
     13 #include "vpx_mem/vpx_mem.h"
     14 #include "vp9/common/vp9_entropymode.h"
     15 #include "vp9/common/vp9_thread_common.h"
     16 #include "vp9/common/vp9_reconinter.h"
     17 #include "vp9/common/vp9_loopfilter.h"
     18 
     19 #if CONFIG_MULTITHREAD
     20 static INLINE void mutex_lock(pthread_mutex_t *const mutex) {
     21   const int kMaxTryLocks = 4000;
     22   int locked = 0;
     23   int i;
     24 
     25   for (i = 0; i < kMaxTryLocks; ++i) {
     26     if (!pthread_mutex_trylock(mutex)) {
     27       locked = 1;
     28       break;
     29     }
     30   }
     31 
     32   if (!locked) pthread_mutex_lock(mutex);
     33 }
     34 #endif  // CONFIG_MULTITHREAD
     35 
     36 static INLINE void sync_read(VP9LfSync *const lf_sync, int r, int c) {
     37 #if CONFIG_MULTITHREAD
     38   const int nsync = lf_sync->sync_range;
     39 
     40   if (r && !(c & (nsync - 1))) {
     41     pthread_mutex_t *const mutex = &lf_sync->mutex_[r - 1];
     42     mutex_lock(mutex);
     43 
     44     while (c > lf_sync->cur_sb_col[r - 1] - nsync) {
     45       pthread_cond_wait(&lf_sync->cond_[r - 1], mutex);
     46     }
     47     pthread_mutex_unlock(mutex);
     48   }
     49 #else
     50   (void)lf_sync;
     51   (void)r;
     52   (void)c;
     53 #endif  // CONFIG_MULTITHREAD
     54 }
     55 
     56 static INLINE void sync_write(VP9LfSync *const lf_sync, int r, int c,
     57                               const int sb_cols) {
     58 #if CONFIG_MULTITHREAD
     59   const int nsync = lf_sync->sync_range;
     60   int cur;
     61   // Only signal when there are enough filtered SB for next row to run.
     62   int sig = 1;
     63 
     64   if (c < sb_cols - 1) {
     65     cur = c;
     66     if (c % nsync) sig = 0;
     67   } else {
     68     cur = sb_cols + nsync;
     69   }
     70 
     71   if (sig) {
     72     mutex_lock(&lf_sync->mutex_[r]);
     73 
     74     lf_sync->cur_sb_col[r] = cur;
     75 
     76     pthread_cond_signal(&lf_sync->cond_[r]);
     77     pthread_mutex_unlock(&lf_sync->mutex_[r]);
     78   }
     79 #else
     80   (void)lf_sync;
     81   (void)r;
     82   (void)c;
     83   (void)sb_cols;
     84 #endif  // CONFIG_MULTITHREAD
     85 }
     86 
     87 // Implement row loopfiltering for each thread.
     88 static INLINE void thread_loop_filter_rows(
     89     const YV12_BUFFER_CONFIG *const frame_buffer, VP9_COMMON *const cm,
     90     struct macroblockd_plane planes[MAX_MB_PLANE], int start, int stop,
     91     int y_only, VP9LfSync *const lf_sync) {
     92   const int num_planes = y_only ? 1 : MAX_MB_PLANE;
     93   const int sb_cols = mi_cols_aligned_to_sb(cm->mi_cols) >> MI_BLOCK_SIZE_LOG2;
     94   int mi_row, mi_col;
     95   enum lf_path path;
     96   if (y_only)
     97     path = LF_PATH_444;
     98   else if (planes[1].subsampling_y == 1 && planes[1].subsampling_x == 1)
     99     path = LF_PATH_420;
    100   else if (planes[1].subsampling_y == 0 && planes[1].subsampling_x == 0)
    101     path = LF_PATH_444;
    102   else
    103     path = LF_PATH_SLOW;
    104 
    105   for (mi_row = start; mi_row < stop;
    106        mi_row += lf_sync->num_workers * MI_BLOCK_SIZE) {
    107     MODE_INFO **const mi = cm->mi_grid_visible + mi_row * cm->mi_stride;
    108     LOOP_FILTER_MASK *lfm = get_lfm(&cm->lf, mi_row, 0);
    109 
    110     for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MI_BLOCK_SIZE, ++lfm) {
    111       const int r = mi_row >> MI_BLOCK_SIZE_LOG2;
    112       const int c = mi_col >> MI_BLOCK_SIZE_LOG2;
    113       int plane;
    114 
    115       sync_read(lf_sync, r, c);
    116 
    117       vp9_setup_dst_planes(planes, frame_buffer, mi_row, mi_col);
    118 
    119       vp9_adjust_mask(cm, mi_row, mi_col, lfm);
    120 
    121       vp9_filter_block_plane_ss00(cm, &planes[0], mi_row, lfm);
    122       for (plane = 1; plane < num_planes; ++plane) {
    123         switch (path) {
    124           case LF_PATH_420:
    125             vp9_filter_block_plane_ss11(cm, &planes[plane], mi_row, lfm);
    126             break;
    127           case LF_PATH_444:
    128             vp9_filter_block_plane_ss00(cm, &planes[plane], mi_row, lfm);
    129             break;
    130           case LF_PATH_SLOW:
    131             vp9_filter_block_plane_non420(cm, &planes[plane], mi + mi_col,
    132                                           mi_row, mi_col);
    133             break;
    134         }
    135       }
    136 
    137       sync_write(lf_sync, r, c, sb_cols);
    138     }
    139   }
    140 }
    141 
    142 // Row-based multi-threaded loopfilter hook
    143 static int loop_filter_row_worker(VP9LfSync *const lf_sync,
    144                                   LFWorkerData *const lf_data) {
    145   thread_loop_filter_rows(lf_data->frame_buffer, lf_data->cm, lf_data->planes,
    146                           lf_data->start, lf_data->stop, lf_data->y_only,
    147                           lf_sync);
    148   return 1;
    149 }
    150 
    151 static void loop_filter_rows_mt(YV12_BUFFER_CONFIG *frame, VP9_COMMON *cm,
    152                                 struct macroblockd_plane planes[MAX_MB_PLANE],
    153                                 int start, int stop, int y_only,
    154                                 VPxWorker *workers, int nworkers,
    155                                 VP9LfSync *lf_sync) {
    156   const VPxWorkerInterface *const winterface = vpx_get_worker_interface();
    157   // Number of superblock rows and cols
    158   const int sb_rows = mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2;
    159   // Decoder may allocate more threads than number of tiles based on user's
    160   // input.
    161   const int tile_cols = 1 << cm->log2_tile_cols;
    162   const int num_workers = VPXMIN(nworkers, tile_cols);
    163   int i;
    164 
    165   if (!lf_sync->sync_range || sb_rows != lf_sync->rows ||
    166       num_workers > lf_sync->num_workers) {
    167     vp9_loop_filter_dealloc(lf_sync);
    168     vp9_loop_filter_alloc(lf_sync, cm, sb_rows, cm->width, num_workers);
    169   }
    170 
    171   // Initialize cur_sb_col to -1 for all SB rows.
    172   memset(lf_sync->cur_sb_col, -1, sizeof(*lf_sync->cur_sb_col) * sb_rows);
    173 
    174   // Set up loopfilter thread data.
    175   // The decoder is capping num_workers because it has been observed that using
    176   // more threads on the loopfilter than there are cores will hurt performance
    177   // on Android. This is because the system will only schedule the tile decode
    178   // workers on cores equal to the number of tile columns. Then if the decoder
    179   // tries to use more threads for the loopfilter, it will hurt performance
    180   // because of contention. If the multithreading code changes in the future
    181   // then the number of workers used by the loopfilter should be revisited.
    182   for (i = 0; i < num_workers; ++i) {
    183     VPxWorker *const worker = &workers[i];
    184     LFWorkerData *const lf_data = &lf_sync->lfdata[i];
    185 
    186     worker->hook = (VPxWorkerHook)loop_filter_row_worker;
    187     worker->data1 = lf_sync;
    188     worker->data2 = lf_data;
    189 
    190     // Loopfilter data
    191     vp9_loop_filter_data_reset(lf_data, frame, cm, planes);
    192     lf_data->start = start + i * MI_BLOCK_SIZE;
    193     lf_data->stop = stop;
    194     lf_data->y_only = y_only;
    195 
    196     // Start loopfiltering
    197     if (i == num_workers - 1) {
    198       winterface->execute(worker);
    199     } else {
    200       winterface->launch(worker);
    201     }
    202   }
    203 
    204   // Wait till all rows are finished
    205   for (i = 0; i < num_workers; ++i) {
    206     winterface->sync(&workers[i]);
    207   }
    208 }
    209 
    210 void vp9_loop_filter_frame_mt(YV12_BUFFER_CONFIG *frame, VP9_COMMON *cm,
    211                               struct macroblockd_plane planes[MAX_MB_PLANE],
    212                               int frame_filter_level, int y_only,
    213                               int partial_frame, VPxWorker *workers,
    214                               int num_workers, VP9LfSync *lf_sync) {
    215   int start_mi_row, end_mi_row, mi_rows_to_filter;
    216 
    217   if (!frame_filter_level) return;
    218 
    219   start_mi_row = 0;
    220   mi_rows_to_filter = cm->mi_rows;
    221   if (partial_frame && cm->mi_rows > 8) {
    222     start_mi_row = cm->mi_rows >> 1;
    223     start_mi_row &= 0xfffffff8;
    224     mi_rows_to_filter = VPXMAX(cm->mi_rows / 8, 8);
    225   }
    226   end_mi_row = start_mi_row + mi_rows_to_filter;
    227   vp9_loop_filter_frame_init(cm, frame_filter_level);
    228 
    229   loop_filter_rows_mt(frame, cm, planes, start_mi_row, end_mi_row, y_only,
    230                       workers, num_workers, lf_sync);
    231 }
    232 
    233 // Set up nsync by width.
    234 static INLINE int get_sync_range(int width) {
    235   // nsync numbers are picked by testing. For example, for 4k
    236   // video, using 4 gives best performance.
    237   if (width < 640)
    238     return 1;
    239   else if (width <= 1280)
    240     return 2;
    241   else if (width <= 4096)
    242     return 4;
    243   else
    244     return 8;
    245 }
    246 
    247 // Allocate memory for lf row synchronization
    248 void vp9_loop_filter_alloc(VP9LfSync *lf_sync, VP9_COMMON *cm, int rows,
    249                            int width, int num_workers) {
    250   lf_sync->rows = rows;
    251 #if CONFIG_MULTITHREAD
    252   {
    253     int i;
    254 
    255     CHECK_MEM_ERROR(cm, lf_sync->mutex_,
    256                     vpx_malloc(sizeof(*lf_sync->mutex_) * rows));
    257     if (lf_sync->mutex_) {
    258       for (i = 0; i < rows; ++i) {
    259         pthread_mutex_init(&lf_sync->mutex_[i], NULL);
    260       }
    261     }
    262 
    263     CHECK_MEM_ERROR(cm, lf_sync->cond_,
    264                     vpx_malloc(sizeof(*lf_sync->cond_) * rows));
    265     if (lf_sync->cond_) {
    266       for (i = 0; i < rows; ++i) {
    267         pthread_cond_init(&lf_sync->cond_[i], NULL);
    268       }
    269     }
    270   }
    271 #endif  // CONFIG_MULTITHREAD
    272 
    273   CHECK_MEM_ERROR(cm, lf_sync->lfdata,
    274                   vpx_malloc(num_workers * sizeof(*lf_sync->lfdata)));
    275   lf_sync->num_workers = num_workers;
    276 
    277   CHECK_MEM_ERROR(cm, lf_sync->cur_sb_col,
    278                   vpx_malloc(sizeof(*lf_sync->cur_sb_col) * rows));
    279 
    280   // Set up nsync.
    281   lf_sync->sync_range = get_sync_range(width);
    282 }
    283 
    284 // Deallocate lf synchronization related mutex and data
    285 void vp9_loop_filter_dealloc(VP9LfSync *lf_sync) {
    286   if (lf_sync != NULL) {
    287 #if CONFIG_MULTITHREAD
    288     int i;
    289 
    290     if (lf_sync->mutex_ != NULL) {
    291       for (i = 0; i < lf_sync->rows; ++i) {
    292         pthread_mutex_destroy(&lf_sync->mutex_[i]);
    293       }
    294       vpx_free(lf_sync->mutex_);
    295     }
    296     if (lf_sync->cond_ != NULL) {
    297       for (i = 0; i < lf_sync->rows; ++i) {
    298         pthread_cond_destroy(&lf_sync->cond_[i]);
    299       }
    300       vpx_free(lf_sync->cond_);
    301     }
    302 #endif  // CONFIG_MULTITHREAD
    303     vpx_free(lf_sync->lfdata);
    304     vpx_free(lf_sync->cur_sb_col);
    305     // clear the structure as the source of this call may be a resize in which
    306     // case this call will be followed by an _alloc() which may fail.
    307     vp9_zero(*lf_sync);
    308   }
    309 }
    310 
    311 // Accumulate frame counts.
    312 void vp9_accumulate_frame_counts(FRAME_COUNTS *accum,
    313                                  const FRAME_COUNTS *counts, int is_dec) {
    314   int i, j, k, l, m;
    315 
    316   for (i = 0; i < BLOCK_SIZE_GROUPS; i++)
    317     for (j = 0; j < INTRA_MODES; j++)
    318       accum->y_mode[i][j] += counts->y_mode[i][j];
    319 
    320   for (i = 0; i < INTRA_MODES; i++)
    321     for (j = 0; j < INTRA_MODES; j++)
    322       accum->uv_mode[i][j] += counts->uv_mode[i][j];
    323 
    324   for (i = 0; i < PARTITION_CONTEXTS; i++)
    325     for (j = 0; j < PARTITION_TYPES; j++)
    326       accum->partition[i][j] += counts->partition[i][j];
    327 
    328   if (is_dec) {
    329     int n;
    330     for (i = 0; i < TX_SIZES; i++)
    331       for (j = 0; j < PLANE_TYPES; j++)
    332         for (k = 0; k < REF_TYPES; k++)
    333           for (l = 0; l < COEF_BANDS; l++)
    334             for (m = 0; m < COEFF_CONTEXTS; m++) {
    335               accum->eob_branch[i][j][k][l][m] +=
    336                   counts->eob_branch[i][j][k][l][m];
    337               for (n = 0; n < UNCONSTRAINED_NODES + 1; n++)
    338                 accum->coef[i][j][k][l][m][n] += counts->coef[i][j][k][l][m][n];
    339             }
    340   } else {
    341     for (i = 0; i < TX_SIZES; i++)
    342       for (j = 0; j < PLANE_TYPES; j++)
    343         for (k = 0; k < REF_TYPES; k++)
    344           for (l = 0; l < COEF_BANDS; l++)
    345             for (m = 0; m < COEFF_CONTEXTS; m++)
    346               accum->eob_branch[i][j][k][l][m] +=
    347                   counts->eob_branch[i][j][k][l][m];
    348     // In the encoder, coef is only updated at frame
    349     // level, so not need to accumulate it here.
    350     // for (n = 0; n < UNCONSTRAINED_NODES + 1; n++)
    351     //   accum->coef[i][j][k][l][m][n] +=
    352     //       counts->coef[i][j][k][l][m][n];
    353   }
    354 
    355   for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++)
    356     for (j = 0; j < SWITCHABLE_FILTERS; j++)
    357       accum->switchable_interp[i][j] += counts->switchable_interp[i][j];
    358 
    359   for (i = 0; i < INTER_MODE_CONTEXTS; i++)
    360     for (j = 0; j < INTER_MODES; j++)
    361       accum->inter_mode[i][j] += counts->inter_mode[i][j];
    362 
    363   for (i = 0; i < INTRA_INTER_CONTEXTS; i++)
    364     for (j = 0; j < 2; j++)
    365       accum->intra_inter[i][j] += counts->intra_inter[i][j];
    366 
    367   for (i = 0; i < COMP_INTER_CONTEXTS; i++)
    368     for (j = 0; j < 2; j++) accum->comp_inter[i][j] += counts->comp_inter[i][j];
    369 
    370   for (i = 0; i < REF_CONTEXTS; i++)
    371     for (j = 0; j < 2; j++)
    372       for (k = 0; k < 2; k++)
    373         accum->single_ref[i][j][k] += counts->single_ref[i][j][k];
    374 
    375   for (i = 0; i < REF_CONTEXTS; i++)
    376     for (j = 0; j < 2; j++) accum->comp_ref[i][j] += counts->comp_ref[i][j];
    377 
    378   for (i = 0; i < TX_SIZE_CONTEXTS; i++) {
    379     for (j = 0; j < TX_SIZES; j++)
    380       accum->tx.p32x32[i][j] += counts->tx.p32x32[i][j];
    381 
    382     for (j = 0; j < TX_SIZES - 1; j++)
    383       accum->tx.p16x16[i][j] += counts->tx.p16x16[i][j];
    384 
    385     for (j = 0; j < TX_SIZES - 2; j++)
    386       accum->tx.p8x8[i][j] += counts->tx.p8x8[i][j];
    387   }
    388 
    389   for (i = 0; i < TX_SIZES; i++)
    390     accum->tx.tx_totals[i] += counts->tx.tx_totals[i];
    391 
    392   for (i = 0; i < SKIP_CONTEXTS; i++)
    393     for (j = 0; j < 2; j++) accum->skip[i][j] += counts->skip[i][j];
    394 
    395   for (i = 0; i < MV_JOINTS; i++) accum->mv.joints[i] += counts->mv.joints[i];
    396 
    397   for (k = 0; k < 2; k++) {
    398     nmv_component_counts *const comps = &accum->mv.comps[k];
    399     const nmv_component_counts *const comps_t = &counts->mv.comps[k];
    400 
    401     for (i = 0; i < 2; i++) {
    402       comps->sign[i] += comps_t->sign[i];
    403       comps->class0_hp[i] += comps_t->class0_hp[i];
    404       comps->hp[i] += comps_t->hp[i];
    405     }
    406 
    407     for (i = 0; i < MV_CLASSES; i++) comps->classes[i] += comps_t->classes[i];
    408 
    409     for (i = 0; i < CLASS0_SIZE; i++) {
    410       comps->class0[i] += comps_t->class0[i];
    411       for (j = 0; j < MV_FP_SIZE; j++)
    412         comps->class0_fp[i][j] += comps_t->class0_fp[i][j];
    413     }
    414 
    415     for (i = 0; i < MV_OFFSET_BITS; i++)
    416       for (j = 0; j < 2; j++) comps->bits[i][j] += comps_t->bits[i][j];
    417 
    418     for (i = 0; i < MV_FP_SIZE; i++) comps->fp[i] += comps_t->fp[i];
    419   }
    420 }
    421