xref: /aosp_15_r20/external/libvpx/vp9/common/vp9_thread_common.c (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker  *
4*fb1b10abSAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker  */
10*fb1b10abSAndroid Build Coastguard Worker 
11*fb1b10abSAndroid Build Coastguard Worker #include <assert.h>
12*fb1b10abSAndroid Build Coastguard Worker #include <limits.h>
13*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_config.h"
14*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/vpx_dsp_common.h"
15*fb1b10abSAndroid Build Coastguard Worker #include "vpx_mem/vpx_mem.h"
16*fb1b10abSAndroid Build Coastguard Worker #include "vpx_util/vpx_pthread.h"
17*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_entropymode.h"
18*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_thread_common.h"
19*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_reconinter.h"
20*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_loopfilter.h"
21*fb1b10abSAndroid Build Coastguard Worker 
22*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
mutex_lock(pthread_mutex_t * const mutex)23*fb1b10abSAndroid Build Coastguard Worker static INLINE void mutex_lock(pthread_mutex_t *const mutex) {
24*fb1b10abSAndroid Build Coastguard Worker   const int kMaxTryLocks = 4000;
25*fb1b10abSAndroid Build Coastguard Worker   int locked = 0;
26*fb1b10abSAndroid Build Coastguard Worker   int i;
27*fb1b10abSAndroid Build Coastguard Worker 
28*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < kMaxTryLocks; ++i) {
29*fb1b10abSAndroid Build Coastguard Worker     if (!pthread_mutex_trylock(mutex)) {
30*fb1b10abSAndroid Build Coastguard Worker       locked = 1;
31*fb1b10abSAndroid Build Coastguard Worker       break;
32*fb1b10abSAndroid Build Coastguard Worker     }
33*fb1b10abSAndroid Build Coastguard Worker   }
34*fb1b10abSAndroid Build Coastguard Worker 
35*fb1b10abSAndroid Build Coastguard Worker   if (!locked) pthread_mutex_lock(mutex);
36*fb1b10abSAndroid Build Coastguard Worker }
37*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_MULTITHREAD
38*fb1b10abSAndroid Build Coastguard Worker 
sync_read(VP9LfSync * const lf_sync,int r,int c)39*fb1b10abSAndroid Build Coastguard Worker static INLINE void sync_read(VP9LfSync *const lf_sync, int r, int c) {
40*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
41*fb1b10abSAndroid Build Coastguard Worker   const int nsync = lf_sync->sync_range;
42*fb1b10abSAndroid Build Coastguard Worker 
43*fb1b10abSAndroid Build Coastguard Worker   if (r && !(c & (nsync - 1))) {
44*fb1b10abSAndroid Build Coastguard Worker     pthread_mutex_t *const mutex = &lf_sync->mutex[r - 1];
45*fb1b10abSAndroid Build Coastguard Worker     mutex_lock(mutex);
46*fb1b10abSAndroid Build Coastguard Worker 
47*fb1b10abSAndroid Build Coastguard Worker     while (c > lf_sync->cur_sb_col[r - 1] - nsync) {
48*fb1b10abSAndroid Build Coastguard Worker       pthread_cond_wait(&lf_sync->cond[r - 1], mutex);
49*fb1b10abSAndroid Build Coastguard Worker     }
50*fb1b10abSAndroid Build Coastguard Worker     pthread_mutex_unlock(mutex);
51*fb1b10abSAndroid Build Coastguard Worker   }
52*fb1b10abSAndroid Build Coastguard Worker #else
53*fb1b10abSAndroid Build Coastguard Worker   (void)lf_sync;
54*fb1b10abSAndroid Build Coastguard Worker   (void)r;
55*fb1b10abSAndroid Build Coastguard Worker   (void)c;
56*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_MULTITHREAD
57*fb1b10abSAndroid Build Coastguard Worker }
58*fb1b10abSAndroid Build Coastguard Worker 
sync_write(VP9LfSync * const lf_sync,int r,int c,const int sb_cols)59*fb1b10abSAndroid Build Coastguard Worker static INLINE void sync_write(VP9LfSync *const lf_sync, int r, int c,
60*fb1b10abSAndroid Build Coastguard Worker                               const int sb_cols) {
61*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
62*fb1b10abSAndroid Build Coastguard Worker   const int nsync = lf_sync->sync_range;
63*fb1b10abSAndroid Build Coastguard Worker   int cur;
64*fb1b10abSAndroid Build Coastguard Worker   // Only signal when there are enough filtered SB for next row to run.
65*fb1b10abSAndroid Build Coastguard Worker   int sig = 1;
66*fb1b10abSAndroid Build Coastguard Worker 
67*fb1b10abSAndroid Build Coastguard Worker   if (c < sb_cols - 1) {
68*fb1b10abSAndroid Build Coastguard Worker     cur = c;
69*fb1b10abSAndroid Build Coastguard Worker     if (c % nsync) sig = 0;
70*fb1b10abSAndroid Build Coastguard Worker   } else {
71*fb1b10abSAndroid Build Coastguard Worker     cur = sb_cols + nsync;
72*fb1b10abSAndroid Build Coastguard Worker   }
73*fb1b10abSAndroid Build Coastguard Worker 
74*fb1b10abSAndroid Build Coastguard Worker   if (sig) {
75*fb1b10abSAndroid Build Coastguard Worker     mutex_lock(&lf_sync->mutex[r]);
76*fb1b10abSAndroid Build Coastguard Worker 
77*fb1b10abSAndroid Build Coastguard Worker     lf_sync->cur_sb_col[r] = cur;
78*fb1b10abSAndroid Build Coastguard Worker 
79*fb1b10abSAndroid Build Coastguard Worker     pthread_cond_signal(&lf_sync->cond[r]);
80*fb1b10abSAndroid Build Coastguard Worker     pthread_mutex_unlock(&lf_sync->mutex[r]);
81*fb1b10abSAndroid Build Coastguard Worker   }
82*fb1b10abSAndroid Build Coastguard Worker #else
83*fb1b10abSAndroid Build Coastguard Worker   (void)lf_sync;
84*fb1b10abSAndroid Build Coastguard Worker   (void)r;
85*fb1b10abSAndroid Build Coastguard Worker   (void)c;
86*fb1b10abSAndroid Build Coastguard Worker   (void)sb_cols;
87*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_MULTITHREAD
88*fb1b10abSAndroid Build Coastguard Worker }
89*fb1b10abSAndroid Build Coastguard Worker 
90*fb1b10abSAndroid Build Coastguard Worker // Implement row loopfiltering for each thread.
thread_loop_filter_rows(const YV12_BUFFER_CONFIG * const frame_buffer,VP9_COMMON * const cm,struct macroblockd_plane planes[MAX_MB_PLANE],int start,int stop,int y_only,VP9LfSync * const lf_sync)91*fb1b10abSAndroid Build Coastguard Worker static INLINE void thread_loop_filter_rows(
92*fb1b10abSAndroid Build Coastguard Worker     const YV12_BUFFER_CONFIG *const frame_buffer, VP9_COMMON *const cm,
93*fb1b10abSAndroid Build Coastguard Worker     struct macroblockd_plane planes[MAX_MB_PLANE], int start, int stop,
94*fb1b10abSAndroid Build Coastguard Worker     int y_only, VP9LfSync *const lf_sync) {
95*fb1b10abSAndroid Build Coastguard Worker   const int num_planes = y_only ? 1 : MAX_MB_PLANE;
96*fb1b10abSAndroid Build Coastguard Worker   const int sb_cols = mi_cols_aligned_to_sb(cm->mi_cols) >> MI_BLOCK_SIZE_LOG2;
97*fb1b10abSAndroid Build Coastguard Worker   const int num_active_workers = lf_sync->num_active_workers;
98*fb1b10abSAndroid Build Coastguard Worker   int mi_row, mi_col;
99*fb1b10abSAndroid Build Coastguard Worker   enum lf_path path;
100*fb1b10abSAndroid Build Coastguard Worker   if (y_only)
101*fb1b10abSAndroid Build Coastguard Worker     path = LF_PATH_444;
102*fb1b10abSAndroid Build Coastguard Worker   else if (planes[1].subsampling_y == 1 && planes[1].subsampling_x == 1)
103*fb1b10abSAndroid Build Coastguard Worker     path = LF_PATH_420;
104*fb1b10abSAndroid Build Coastguard Worker   else if (planes[1].subsampling_y == 0 && planes[1].subsampling_x == 0)
105*fb1b10abSAndroid Build Coastguard Worker     path = LF_PATH_444;
106*fb1b10abSAndroid Build Coastguard Worker   else
107*fb1b10abSAndroid Build Coastguard Worker     path = LF_PATH_SLOW;
108*fb1b10abSAndroid Build Coastguard Worker 
109*fb1b10abSAndroid Build Coastguard Worker   assert(num_active_workers > 0);
110*fb1b10abSAndroid Build Coastguard Worker 
111*fb1b10abSAndroid Build Coastguard Worker   for (mi_row = start; mi_row < stop;
112*fb1b10abSAndroid Build Coastguard Worker        mi_row += num_active_workers * MI_BLOCK_SIZE) {
113*fb1b10abSAndroid Build Coastguard Worker     MODE_INFO **const mi = cm->mi_grid_visible + mi_row * cm->mi_stride;
114*fb1b10abSAndroid Build Coastguard Worker     LOOP_FILTER_MASK *lfm = get_lfm(&cm->lf, mi_row, 0);
115*fb1b10abSAndroid Build Coastguard Worker 
116*fb1b10abSAndroid Build Coastguard Worker     for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MI_BLOCK_SIZE, ++lfm) {
117*fb1b10abSAndroid Build Coastguard Worker       const int r = mi_row >> MI_BLOCK_SIZE_LOG2;
118*fb1b10abSAndroid Build Coastguard Worker       const int c = mi_col >> MI_BLOCK_SIZE_LOG2;
119*fb1b10abSAndroid Build Coastguard Worker       int plane;
120*fb1b10abSAndroid Build Coastguard Worker 
121*fb1b10abSAndroid Build Coastguard Worker       sync_read(lf_sync, r, c);
122*fb1b10abSAndroid Build Coastguard Worker 
123*fb1b10abSAndroid Build Coastguard Worker       vp9_setup_dst_planes(planes, frame_buffer, mi_row, mi_col);
124*fb1b10abSAndroid Build Coastguard Worker 
125*fb1b10abSAndroid Build Coastguard Worker       vp9_adjust_mask(cm, mi_row, mi_col, lfm);
126*fb1b10abSAndroid Build Coastguard Worker 
127*fb1b10abSAndroid Build Coastguard Worker       vp9_filter_block_plane_ss00(cm, &planes[0], mi_row, lfm);
128*fb1b10abSAndroid Build Coastguard Worker       for (plane = 1; plane < num_planes; ++plane) {
129*fb1b10abSAndroid Build Coastguard Worker         switch (path) {
130*fb1b10abSAndroid Build Coastguard Worker           case LF_PATH_420:
131*fb1b10abSAndroid Build Coastguard Worker             vp9_filter_block_plane_ss11(cm, &planes[plane], mi_row, lfm);
132*fb1b10abSAndroid Build Coastguard Worker             break;
133*fb1b10abSAndroid Build Coastguard Worker           case LF_PATH_444:
134*fb1b10abSAndroid Build Coastguard Worker             vp9_filter_block_plane_ss00(cm, &planes[plane], mi_row, lfm);
135*fb1b10abSAndroid Build Coastguard Worker             break;
136*fb1b10abSAndroid Build Coastguard Worker           case LF_PATH_SLOW:
137*fb1b10abSAndroid Build Coastguard Worker             vp9_filter_block_plane_non420(cm, &planes[plane], mi + mi_col,
138*fb1b10abSAndroid Build Coastguard Worker                                           mi_row, mi_col);
139*fb1b10abSAndroid Build Coastguard Worker             break;
140*fb1b10abSAndroid Build Coastguard Worker         }
141*fb1b10abSAndroid Build Coastguard Worker       }
142*fb1b10abSAndroid Build Coastguard Worker 
143*fb1b10abSAndroid Build Coastguard Worker       sync_write(lf_sync, r, c, sb_cols);
144*fb1b10abSAndroid Build Coastguard Worker     }
145*fb1b10abSAndroid Build Coastguard Worker   }
146*fb1b10abSAndroid Build Coastguard Worker }
147*fb1b10abSAndroid Build Coastguard Worker 
148*fb1b10abSAndroid Build Coastguard Worker // Row-based multi-threaded loopfilter hook
loop_filter_row_worker(void * arg1,void * arg2)149*fb1b10abSAndroid Build Coastguard Worker static int loop_filter_row_worker(void *arg1, void *arg2) {
150*fb1b10abSAndroid Build Coastguard Worker   VP9LfSync *const lf_sync = (VP9LfSync *)arg1;
151*fb1b10abSAndroid Build Coastguard Worker   LFWorkerData *const lf_data = (LFWorkerData *)arg2;
152*fb1b10abSAndroid Build Coastguard Worker   thread_loop_filter_rows(lf_data->frame_buffer, lf_data->cm, lf_data->planes,
153*fb1b10abSAndroid Build Coastguard Worker                           lf_data->start, lf_data->stop, lf_data->y_only,
154*fb1b10abSAndroid Build Coastguard Worker                           lf_sync);
155*fb1b10abSAndroid Build Coastguard Worker   return 1;
156*fb1b10abSAndroid Build Coastguard Worker }
157*fb1b10abSAndroid Build Coastguard Worker 
loop_filter_rows_mt(YV12_BUFFER_CONFIG * frame,VP9_COMMON * cm,struct macroblockd_plane planes[MAX_MB_PLANE],int start,int stop,int y_only,VPxWorker * workers,int nworkers,VP9LfSync * lf_sync)158*fb1b10abSAndroid Build Coastguard Worker static void loop_filter_rows_mt(YV12_BUFFER_CONFIG *frame, VP9_COMMON *cm,
159*fb1b10abSAndroid Build Coastguard Worker                                 struct macroblockd_plane planes[MAX_MB_PLANE],
160*fb1b10abSAndroid Build Coastguard Worker                                 int start, int stop, int y_only,
161*fb1b10abSAndroid Build Coastguard Worker                                 VPxWorker *workers, int nworkers,
162*fb1b10abSAndroid Build Coastguard Worker                                 VP9LfSync *lf_sync) {
163*fb1b10abSAndroid Build Coastguard Worker   const VPxWorkerInterface *const winterface = vpx_get_worker_interface();
164*fb1b10abSAndroid Build Coastguard Worker   // Number of superblock rows and cols
165*fb1b10abSAndroid Build Coastguard Worker   const int sb_rows = mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2;
166*fb1b10abSAndroid Build Coastguard Worker   const int num_tile_cols = 1 << cm->log2_tile_cols;
167*fb1b10abSAndroid Build Coastguard Worker   // Limit the number of workers to prevent changes in frame dimensions from
168*fb1b10abSAndroid Build Coastguard Worker   // causing incorrect sync calculations when sb_rows < threads/tile_cols.
169*fb1b10abSAndroid Build Coastguard Worker   // Further restrict them by the number of tile columns should the user
170*fb1b10abSAndroid Build Coastguard Worker   // request more as this implementation doesn't scale well beyond that.
171*fb1b10abSAndroid Build Coastguard Worker   const int num_workers = VPXMIN(nworkers, VPXMIN(num_tile_cols, sb_rows));
172*fb1b10abSAndroid Build Coastguard Worker   int i;
173*fb1b10abSAndroid Build Coastguard Worker 
174*fb1b10abSAndroid Build Coastguard Worker   if (!lf_sync->sync_range || sb_rows != lf_sync->rows ||
175*fb1b10abSAndroid Build Coastguard Worker       num_workers > lf_sync->num_workers) {
176*fb1b10abSAndroid Build Coastguard Worker     vp9_loop_filter_dealloc(lf_sync);
177*fb1b10abSAndroid Build Coastguard Worker     vp9_loop_filter_alloc(lf_sync, cm, sb_rows, cm->width, num_workers);
178*fb1b10abSAndroid Build Coastguard Worker   }
179*fb1b10abSAndroid Build Coastguard Worker   lf_sync->num_active_workers = num_workers;
180*fb1b10abSAndroid Build Coastguard Worker 
181*fb1b10abSAndroid Build Coastguard Worker   // Initialize cur_sb_col to -1 for all SB rows.
182*fb1b10abSAndroid Build Coastguard Worker   memset(lf_sync->cur_sb_col, -1, sizeof(*lf_sync->cur_sb_col) * sb_rows);
183*fb1b10abSAndroid Build Coastguard Worker 
184*fb1b10abSAndroid Build Coastguard Worker   // Set up loopfilter thread data.
185*fb1b10abSAndroid Build Coastguard Worker   // The decoder is capping num_workers because it has been observed that using
186*fb1b10abSAndroid Build Coastguard Worker   // more threads on the loopfilter than there are cores will hurt performance
187*fb1b10abSAndroid Build Coastguard Worker   // on Android. This is because the system will only schedule the tile decode
188*fb1b10abSAndroid Build Coastguard Worker   // workers on cores equal to the number of tile columns. Then if the decoder
189*fb1b10abSAndroid Build Coastguard Worker   // tries to use more threads for the loopfilter, it will hurt performance
190*fb1b10abSAndroid Build Coastguard Worker   // because of contention. If the multithreading code changes in the future
191*fb1b10abSAndroid Build Coastguard Worker   // then the number of workers used by the loopfilter should be revisited.
192*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < num_workers; ++i) {
193*fb1b10abSAndroid Build Coastguard Worker     VPxWorker *const worker = &workers[i];
194*fb1b10abSAndroid Build Coastguard Worker     LFWorkerData *const lf_data = &lf_sync->lfdata[i];
195*fb1b10abSAndroid Build Coastguard Worker 
196*fb1b10abSAndroid Build Coastguard Worker     worker->hook = loop_filter_row_worker;
197*fb1b10abSAndroid Build Coastguard Worker     worker->data1 = lf_sync;
198*fb1b10abSAndroid Build Coastguard Worker     worker->data2 = lf_data;
199*fb1b10abSAndroid Build Coastguard Worker 
200*fb1b10abSAndroid Build Coastguard Worker     // Loopfilter data
201*fb1b10abSAndroid Build Coastguard Worker     vp9_loop_filter_data_reset(lf_data, frame, cm, planes);
202*fb1b10abSAndroid Build Coastguard Worker     lf_data->start = start + i * MI_BLOCK_SIZE;
203*fb1b10abSAndroid Build Coastguard Worker     lf_data->stop = stop;
204*fb1b10abSAndroid Build Coastguard Worker     lf_data->y_only = y_only;
205*fb1b10abSAndroid Build Coastguard Worker 
206*fb1b10abSAndroid Build Coastguard Worker     // Start loopfiltering
207*fb1b10abSAndroid Build Coastguard Worker     if (i == num_workers - 1) {
208*fb1b10abSAndroid Build Coastguard Worker       winterface->execute(worker);
209*fb1b10abSAndroid Build Coastguard Worker     } else {
210*fb1b10abSAndroid Build Coastguard Worker       winterface->launch(worker);
211*fb1b10abSAndroid Build Coastguard Worker     }
212*fb1b10abSAndroid Build Coastguard Worker   }
213*fb1b10abSAndroid Build Coastguard Worker 
214*fb1b10abSAndroid Build Coastguard Worker   // Wait till all rows are finished
215*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < num_workers; ++i) {
216*fb1b10abSAndroid Build Coastguard Worker     winterface->sync(&workers[i]);
217*fb1b10abSAndroid Build Coastguard Worker   }
218*fb1b10abSAndroid Build Coastguard Worker }
219*fb1b10abSAndroid Build Coastguard Worker 
vp9_loop_filter_frame_mt(YV12_BUFFER_CONFIG * frame,VP9_COMMON * cm,struct macroblockd_plane planes[MAX_MB_PLANE],int frame_filter_level,int y_only,int partial_frame,VPxWorker * workers,int num_workers,VP9LfSync * lf_sync)220*fb1b10abSAndroid Build Coastguard Worker void vp9_loop_filter_frame_mt(YV12_BUFFER_CONFIG *frame, VP9_COMMON *cm,
221*fb1b10abSAndroid Build Coastguard Worker                               struct macroblockd_plane planes[MAX_MB_PLANE],
222*fb1b10abSAndroid Build Coastguard Worker                               int frame_filter_level, int y_only,
223*fb1b10abSAndroid Build Coastguard Worker                               int partial_frame, VPxWorker *workers,
224*fb1b10abSAndroid Build Coastguard Worker                               int num_workers, VP9LfSync *lf_sync) {
225*fb1b10abSAndroid Build Coastguard Worker   int start_mi_row, end_mi_row, mi_rows_to_filter;
226*fb1b10abSAndroid Build Coastguard Worker 
227*fb1b10abSAndroid Build Coastguard Worker   if (!frame_filter_level) return;
228*fb1b10abSAndroid Build Coastguard Worker 
229*fb1b10abSAndroid Build Coastguard Worker   start_mi_row = 0;
230*fb1b10abSAndroid Build Coastguard Worker   mi_rows_to_filter = cm->mi_rows;
231*fb1b10abSAndroid Build Coastguard Worker   if (partial_frame && cm->mi_rows > 8) {
232*fb1b10abSAndroid Build Coastguard Worker     start_mi_row = cm->mi_rows >> 1;
233*fb1b10abSAndroid Build Coastguard Worker     start_mi_row &= 0xfffffff8;
234*fb1b10abSAndroid Build Coastguard Worker     mi_rows_to_filter = VPXMAX(cm->mi_rows / 8, 8);
235*fb1b10abSAndroid Build Coastguard Worker   }
236*fb1b10abSAndroid Build Coastguard Worker   end_mi_row = start_mi_row + mi_rows_to_filter;
237*fb1b10abSAndroid Build Coastguard Worker   vp9_loop_filter_frame_init(cm, frame_filter_level);
238*fb1b10abSAndroid Build Coastguard Worker 
239*fb1b10abSAndroid Build Coastguard Worker   loop_filter_rows_mt(frame, cm, planes, start_mi_row, end_mi_row, y_only,
240*fb1b10abSAndroid Build Coastguard Worker                       workers, num_workers, lf_sync);
241*fb1b10abSAndroid Build Coastguard Worker }
242*fb1b10abSAndroid Build Coastguard Worker 
vp9_lpf_mt_init(VP9LfSync * lf_sync,VP9_COMMON * cm,int frame_filter_level,int num_workers)243*fb1b10abSAndroid Build Coastguard Worker void vp9_lpf_mt_init(VP9LfSync *lf_sync, VP9_COMMON *cm, int frame_filter_level,
244*fb1b10abSAndroid Build Coastguard Worker                      int num_workers) {
245*fb1b10abSAndroid Build Coastguard Worker   const int sb_rows = mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2;
246*fb1b10abSAndroid Build Coastguard Worker 
247*fb1b10abSAndroid Build Coastguard Worker   if (!frame_filter_level) return;
248*fb1b10abSAndroid Build Coastguard Worker 
249*fb1b10abSAndroid Build Coastguard Worker   if (!lf_sync->sync_range || sb_rows != lf_sync->rows ||
250*fb1b10abSAndroid Build Coastguard Worker       num_workers > lf_sync->num_workers) {
251*fb1b10abSAndroid Build Coastguard Worker     vp9_loop_filter_dealloc(lf_sync);
252*fb1b10abSAndroid Build Coastguard Worker     vp9_loop_filter_alloc(lf_sync, cm, sb_rows, cm->width, num_workers);
253*fb1b10abSAndroid Build Coastguard Worker   }
254*fb1b10abSAndroid Build Coastguard Worker 
255*fb1b10abSAndroid Build Coastguard Worker   // Initialize cur_sb_col to -1 for all SB rows.
256*fb1b10abSAndroid Build Coastguard Worker   memset(lf_sync->cur_sb_col, -1, sizeof(*lf_sync->cur_sb_col) * sb_rows);
257*fb1b10abSAndroid Build Coastguard Worker 
258*fb1b10abSAndroid Build Coastguard Worker   lf_sync->corrupted = 0;
259*fb1b10abSAndroid Build Coastguard Worker 
260*fb1b10abSAndroid Build Coastguard Worker   memset(lf_sync->num_tiles_done, 0,
261*fb1b10abSAndroid Build Coastguard Worker          sizeof(*lf_sync->num_tiles_done) * sb_rows);
262*fb1b10abSAndroid Build Coastguard Worker   cm->lf_row = 0;
263*fb1b10abSAndroid Build Coastguard Worker }
264*fb1b10abSAndroid Build Coastguard Worker 
265*fb1b10abSAndroid Build Coastguard Worker // Set up nsync by width.
get_sync_range(int width)266*fb1b10abSAndroid Build Coastguard Worker static INLINE int get_sync_range(int width) {
267*fb1b10abSAndroid Build Coastguard Worker   // nsync numbers are picked by testing. For example, for 4k
268*fb1b10abSAndroid Build Coastguard Worker   // video, using 4 gives best performance.
269*fb1b10abSAndroid Build Coastguard Worker   if (width < 640)
270*fb1b10abSAndroid Build Coastguard Worker     return 1;
271*fb1b10abSAndroid Build Coastguard Worker   else if (width <= 1280)
272*fb1b10abSAndroid Build Coastguard Worker     return 2;
273*fb1b10abSAndroid Build Coastguard Worker   else if (width <= 4096)
274*fb1b10abSAndroid Build Coastguard Worker     return 4;
275*fb1b10abSAndroid Build Coastguard Worker   else
276*fb1b10abSAndroid Build Coastguard Worker     return 8;
277*fb1b10abSAndroid Build Coastguard Worker }
278*fb1b10abSAndroid Build Coastguard Worker 
279*fb1b10abSAndroid Build Coastguard Worker // Allocate memory for lf row synchronization
vp9_loop_filter_alloc(VP9LfSync * lf_sync,VP9_COMMON * cm,int rows,int width,int num_workers)280*fb1b10abSAndroid Build Coastguard Worker void vp9_loop_filter_alloc(VP9LfSync *lf_sync, VP9_COMMON *cm, int rows,
281*fb1b10abSAndroid Build Coastguard Worker                            int width, int num_workers) {
282*fb1b10abSAndroid Build Coastguard Worker   lf_sync->rows = rows;
283*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
284*fb1b10abSAndroid Build Coastguard Worker   {
285*fb1b10abSAndroid Build Coastguard Worker     int i;
286*fb1b10abSAndroid Build Coastguard Worker 
287*fb1b10abSAndroid Build Coastguard Worker     CHECK_MEM_ERROR(&cm->error, lf_sync->mutex,
288*fb1b10abSAndroid Build Coastguard Worker                     vpx_malloc(sizeof(*lf_sync->mutex) * rows));
289*fb1b10abSAndroid Build Coastguard Worker     if (lf_sync->mutex) {
290*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < rows; ++i) {
291*fb1b10abSAndroid Build Coastguard Worker         pthread_mutex_init(&lf_sync->mutex[i], NULL);
292*fb1b10abSAndroid Build Coastguard Worker       }
293*fb1b10abSAndroid Build Coastguard Worker     }
294*fb1b10abSAndroid Build Coastguard Worker 
295*fb1b10abSAndroid Build Coastguard Worker     CHECK_MEM_ERROR(&cm->error, lf_sync->cond,
296*fb1b10abSAndroid Build Coastguard Worker                     vpx_malloc(sizeof(*lf_sync->cond) * rows));
297*fb1b10abSAndroid Build Coastguard Worker     if (lf_sync->cond) {
298*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < rows; ++i) {
299*fb1b10abSAndroid Build Coastguard Worker         pthread_cond_init(&lf_sync->cond[i], NULL);
300*fb1b10abSAndroid Build Coastguard Worker       }
301*fb1b10abSAndroid Build Coastguard Worker     }
302*fb1b10abSAndroid Build Coastguard Worker 
303*fb1b10abSAndroid Build Coastguard Worker     CHECK_MEM_ERROR(&cm->error, lf_sync->lf_mutex,
304*fb1b10abSAndroid Build Coastguard Worker                     vpx_malloc(sizeof(*lf_sync->lf_mutex)));
305*fb1b10abSAndroid Build Coastguard Worker     pthread_mutex_init(lf_sync->lf_mutex, NULL);
306*fb1b10abSAndroid Build Coastguard Worker 
307*fb1b10abSAndroid Build Coastguard Worker     CHECK_MEM_ERROR(&cm->error, lf_sync->recon_done_mutex,
308*fb1b10abSAndroid Build Coastguard Worker                     vpx_malloc(sizeof(*lf_sync->recon_done_mutex) * rows));
309*fb1b10abSAndroid Build Coastguard Worker     if (lf_sync->recon_done_mutex) {
310*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < rows; ++i) {
311*fb1b10abSAndroid Build Coastguard Worker         pthread_mutex_init(&lf_sync->recon_done_mutex[i], NULL);
312*fb1b10abSAndroid Build Coastguard Worker       }
313*fb1b10abSAndroid Build Coastguard Worker     }
314*fb1b10abSAndroid Build Coastguard Worker 
315*fb1b10abSAndroid Build Coastguard Worker     CHECK_MEM_ERROR(&cm->error, lf_sync->recon_done_cond,
316*fb1b10abSAndroid Build Coastguard Worker                     vpx_malloc(sizeof(*lf_sync->recon_done_cond) * rows));
317*fb1b10abSAndroid Build Coastguard Worker     if (lf_sync->recon_done_cond) {
318*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < rows; ++i) {
319*fb1b10abSAndroid Build Coastguard Worker         pthread_cond_init(&lf_sync->recon_done_cond[i], NULL);
320*fb1b10abSAndroid Build Coastguard Worker       }
321*fb1b10abSAndroid Build Coastguard Worker     }
322*fb1b10abSAndroid Build Coastguard Worker   }
323*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_MULTITHREAD
324*fb1b10abSAndroid Build Coastguard Worker 
325*fb1b10abSAndroid Build Coastguard Worker   CHECK_MEM_ERROR(&cm->error, lf_sync->lfdata,
326*fb1b10abSAndroid Build Coastguard Worker                   vpx_malloc(num_workers * sizeof(*lf_sync->lfdata)));
327*fb1b10abSAndroid Build Coastguard Worker   lf_sync->num_workers = num_workers;
328*fb1b10abSAndroid Build Coastguard Worker   lf_sync->num_active_workers = lf_sync->num_workers;
329*fb1b10abSAndroid Build Coastguard Worker 
330*fb1b10abSAndroid Build Coastguard Worker   CHECK_MEM_ERROR(&cm->error, lf_sync->cur_sb_col,
331*fb1b10abSAndroid Build Coastguard Worker                   vpx_malloc(sizeof(*lf_sync->cur_sb_col) * rows));
332*fb1b10abSAndroid Build Coastguard Worker 
333*fb1b10abSAndroid Build Coastguard Worker   CHECK_MEM_ERROR(&cm->error, lf_sync->num_tiles_done,
334*fb1b10abSAndroid Build Coastguard Worker                   vpx_malloc(sizeof(*lf_sync->num_tiles_done) *
335*fb1b10abSAndroid Build Coastguard Worker                                  mi_cols_aligned_to_sb(cm->mi_rows) >>
336*fb1b10abSAndroid Build Coastguard Worker                              MI_BLOCK_SIZE_LOG2));
337*fb1b10abSAndroid Build Coastguard Worker 
338*fb1b10abSAndroid Build Coastguard Worker   // Set up nsync.
339*fb1b10abSAndroid Build Coastguard Worker   lf_sync->sync_range = get_sync_range(width);
340*fb1b10abSAndroid Build Coastguard Worker }
341*fb1b10abSAndroid Build Coastguard Worker 
342*fb1b10abSAndroid Build Coastguard Worker // Deallocate lf synchronization related mutex and data
vp9_loop_filter_dealloc(VP9LfSync * lf_sync)343*fb1b10abSAndroid Build Coastguard Worker void vp9_loop_filter_dealloc(VP9LfSync *lf_sync) {
344*fb1b10abSAndroid Build Coastguard Worker   assert(lf_sync != NULL);
345*fb1b10abSAndroid Build Coastguard Worker 
346*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
347*fb1b10abSAndroid Build Coastguard Worker   if (lf_sync->mutex != NULL) {
348*fb1b10abSAndroid Build Coastguard Worker     int i;
349*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < lf_sync->rows; ++i) {
350*fb1b10abSAndroid Build Coastguard Worker       pthread_mutex_destroy(&lf_sync->mutex[i]);
351*fb1b10abSAndroid Build Coastguard Worker     }
352*fb1b10abSAndroid Build Coastguard Worker     vpx_free(lf_sync->mutex);
353*fb1b10abSAndroid Build Coastguard Worker   }
354*fb1b10abSAndroid Build Coastguard Worker   if (lf_sync->cond != NULL) {
355*fb1b10abSAndroid Build Coastguard Worker     int i;
356*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < lf_sync->rows; ++i) {
357*fb1b10abSAndroid Build Coastguard Worker       pthread_cond_destroy(&lf_sync->cond[i]);
358*fb1b10abSAndroid Build Coastguard Worker     }
359*fb1b10abSAndroid Build Coastguard Worker     vpx_free(lf_sync->cond);
360*fb1b10abSAndroid Build Coastguard Worker   }
361*fb1b10abSAndroid Build Coastguard Worker   if (lf_sync->recon_done_mutex != NULL) {
362*fb1b10abSAndroid Build Coastguard Worker     int i;
363*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < lf_sync->rows; ++i) {
364*fb1b10abSAndroid Build Coastguard Worker       pthread_mutex_destroy(&lf_sync->recon_done_mutex[i]);
365*fb1b10abSAndroid Build Coastguard Worker     }
366*fb1b10abSAndroid Build Coastguard Worker     vpx_free(lf_sync->recon_done_mutex);
367*fb1b10abSAndroid Build Coastguard Worker   }
368*fb1b10abSAndroid Build Coastguard Worker 
369*fb1b10abSAndroid Build Coastguard Worker   if (lf_sync->lf_mutex != NULL) {
370*fb1b10abSAndroid Build Coastguard Worker     pthread_mutex_destroy(lf_sync->lf_mutex);
371*fb1b10abSAndroid Build Coastguard Worker     vpx_free(lf_sync->lf_mutex);
372*fb1b10abSAndroid Build Coastguard Worker   }
373*fb1b10abSAndroid Build Coastguard Worker   if (lf_sync->recon_done_cond != NULL) {
374*fb1b10abSAndroid Build Coastguard Worker     int i;
375*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < lf_sync->rows; ++i) {
376*fb1b10abSAndroid Build Coastguard Worker       pthread_cond_destroy(&lf_sync->recon_done_cond[i]);
377*fb1b10abSAndroid Build Coastguard Worker     }
378*fb1b10abSAndroid Build Coastguard Worker     vpx_free(lf_sync->recon_done_cond);
379*fb1b10abSAndroid Build Coastguard Worker   }
380*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_MULTITHREAD
381*fb1b10abSAndroid Build Coastguard Worker 
382*fb1b10abSAndroid Build Coastguard Worker   vpx_free(lf_sync->lfdata);
383*fb1b10abSAndroid Build Coastguard Worker   vpx_free(lf_sync->cur_sb_col);
384*fb1b10abSAndroid Build Coastguard Worker   vpx_free(lf_sync->num_tiles_done);
385*fb1b10abSAndroid Build Coastguard Worker   // clear the structure as the source of this call may be a resize in which
386*fb1b10abSAndroid Build Coastguard Worker   // case this call will be followed by an _alloc() which may fail.
387*fb1b10abSAndroid Build Coastguard Worker   vp9_zero(*lf_sync);
388*fb1b10abSAndroid Build Coastguard Worker }
389*fb1b10abSAndroid Build Coastguard Worker 
get_next_row(VP9_COMMON * cm,VP9LfSync * lf_sync)390*fb1b10abSAndroid Build Coastguard Worker static int get_next_row(VP9_COMMON *cm, VP9LfSync *lf_sync) {
391*fb1b10abSAndroid Build Coastguard Worker   int return_val = -1;
392*fb1b10abSAndroid Build Coastguard Worker   const int max_rows = cm->mi_rows;
393*fb1b10abSAndroid Build Coastguard Worker 
394*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
395*fb1b10abSAndroid Build Coastguard Worker   int cur_row;
396*fb1b10abSAndroid Build Coastguard Worker   const int tile_cols = 1 << cm->log2_tile_cols;
397*fb1b10abSAndroid Build Coastguard Worker 
398*fb1b10abSAndroid Build Coastguard Worker   pthread_mutex_lock(lf_sync->lf_mutex);
399*fb1b10abSAndroid Build Coastguard Worker   if (cm->lf_row < max_rows) {
400*fb1b10abSAndroid Build Coastguard Worker     cur_row = cm->lf_row >> MI_BLOCK_SIZE_LOG2;
401*fb1b10abSAndroid Build Coastguard Worker     return_val = cm->lf_row;
402*fb1b10abSAndroid Build Coastguard Worker     cm->lf_row += MI_BLOCK_SIZE;
403*fb1b10abSAndroid Build Coastguard Worker     if (cm->lf_row < max_rows) {
404*fb1b10abSAndroid Build Coastguard Worker       /* If this is not the last row, make sure the next row is also decoded.
405*fb1b10abSAndroid Build Coastguard Worker        * This is because the intra predict has to happen before loop filter */
406*fb1b10abSAndroid Build Coastguard Worker       cur_row += 1;
407*fb1b10abSAndroid Build Coastguard Worker     }
408*fb1b10abSAndroid Build Coastguard Worker   }
409*fb1b10abSAndroid Build Coastguard Worker   pthread_mutex_unlock(lf_sync->lf_mutex);
410*fb1b10abSAndroid Build Coastguard Worker 
411*fb1b10abSAndroid Build Coastguard Worker   if (return_val == -1) return return_val;
412*fb1b10abSAndroid Build Coastguard Worker 
413*fb1b10abSAndroid Build Coastguard Worker   pthread_mutex_lock(&lf_sync->recon_done_mutex[cur_row]);
414*fb1b10abSAndroid Build Coastguard Worker   if (lf_sync->num_tiles_done[cur_row] < tile_cols) {
415*fb1b10abSAndroid Build Coastguard Worker     pthread_cond_wait(&lf_sync->recon_done_cond[cur_row],
416*fb1b10abSAndroid Build Coastguard Worker                       &lf_sync->recon_done_mutex[cur_row]);
417*fb1b10abSAndroid Build Coastguard Worker   }
418*fb1b10abSAndroid Build Coastguard Worker   pthread_mutex_unlock(&lf_sync->recon_done_mutex[cur_row]);
419*fb1b10abSAndroid Build Coastguard Worker   pthread_mutex_lock(lf_sync->lf_mutex);
420*fb1b10abSAndroid Build Coastguard Worker   if (lf_sync->corrupted) {
421*fb1b10abSAndroid Build Coastguard Worker     int row = return_val >> MI_BLOCK_SIZE_LOG2;
422*fb1b10abSAndroid Build Coastguard Worker     pthread_mutex_lock(&lf_sync->mutex[row]);
423*fb1b10abSAndroid Build Coastguard Worker     lf_sync->cur_sb_col[row] = INT_MAX;
424*fb1b10abSAndroid Build Coastguard Worker     pthread_cond_signal(&lf_sync->cond[row]);
425*fb1b10abSAndroid Build Coastguard Worker     pthread_mutex_unlock(&lf_sync->mutex[row]);
426*fb1b10abSAndroid Build Coastguard Worker     return_val = -1;
427*fb1b10abSAndroid Build Coastguard Worker   }
428*fb1b10abSAndroid Build Coastguard Worker   pthread_mutex_unlock(lf_sync->lf_mutex);
429*fb1b10abSAndroid Build Coastguard Worker #else
430*fb1b10abSAndroid Build Coastguard Worker   (void)lf_sync;
431*fb1b10abSAndroid Build Coastguard Worker   if (cm->lf_row < max_rows) {
432*fb1b10abSAndroid Build Coastguard Worker     return_val = cm->lf_row;
433*fb1b10abSAndroid Build Coastguard Worker     cm->lf_row += MI_BLOCK_SIZE;
434*fb1b10abSAndroid Build Coastguard Worker   }
435*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_MULTITHREAD
436*fb1b10abSAndroid Build Coastguard Worker 
437*fb1b10abSAndroid Build Coastguard Worker   return return_val;
438*fb1b10abSAndroid Build Coastguard Worker }
439*fb1b10abSAndroid Build Coastguard Worker 
vp9_loopfilter_rows(LFWorkerData * lf_data,VP9LfSync * lf_sync)440*fb1b10abSAndroid Build Coastguard Worker void vp9_loopfilter_rows(LFWorkerData *lf_data, VP9LfSync *lf_sync) {
441*fb1b10abSAndroid Build Coastguard Worker   int mi_row;
442*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *cm = lf_data->cm;
443*fb1b10abSAndroid Build Coastguard Worker 
444*fb1b10abSAndroid Build Coastguard Worker   while ((mi_row = get_next_row(cm, lf_sync)) != -1 && mi_row < cm->mi_rows) {
445*fb1b10abSAndroid Build Coastguard Worker     lf_data->start = mi_row;
446*fb1b10abSAndroid Build Coastguard Worker     lf_data->stop = mi_row + MI_BLOCK_SIZE;
447*fb1b10abSAndroid Build Coastguard Worker 
448*fb1b10abSAndroid Build Coastguard Worker     thread_loop_filter_rows(lf_data->frame_buffer, lf_data->cm, lf_data->planes,
449*fb1b10abSAndroid Build Coastguard Worker                             lf_data->start, lf_data->stop, lf_data->y_only,
450*fb1b10abSAndroid Build Coastguard Worker                             lf_sync);
451*fb1b10abSAndroid Build Coastguard Worker   }
452*fb1b10abSAndroid Build Coastguard Worker }
453*fb1b10abSAndroid Build Coastguard Worker 
vp9_set_row(VP9LfSync * lf_sync,int num_tiles,int row,int is_last_row,int corrupted)454*fb1b10abSAndroid Build Coastguard Worker void vp9_set_row(VP9LfSync *lf_sync, int num_tiles, int row, int is_last_row,
455*fb1b10abSAndroid Build Coastguard Worker                  int corrupted) {
456*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
457*fb1b10abSAndroid Build Coastguard Worker   pthread_mutex_lock(lf_sync->lf_mutex);
458*fb1b10abSAndroid Build Coastguard Worker   lf_sync->corrupted |= corrupted;
459*fb1b10abSAndroid Build Coastguard Worker   pthread_mutex_unlock(lf_sync->lf_mutex);
460*fb1b10abSAndroid Build Coastguard Worker   pthread_mutex_lock(&lf_sync->recon_done_mutex[row]);
461*fb1b10abSAndroid Build Coastguard Worker   lf_sync->num_tiles_done[row] += 1;
462*fb1b10abSAndroid Build Coastguard Worker   if (num_tiles == lf_sync->num_tiles_done[row]) {
463*fb1b10abSAndroid Build Coastguard Worker     if (is_last_row) {
464*fb1b10abSAndroid Build Coastguard Worker       /* The last 2 rows wait on the last row to be done.
465*fb1b10abSAndroid Build Coastguard Worker        * So, we have to broadcast the signal in this case.
466*fb1b10abSAndroid Build Coastguard Worker        */
467*fb1b10abSAndroid Build Coastguard Worker       pthread_cond_broadcast(&lf_sync->recon_done_cond[row]);
468*fb1b10abSAndroid Build Coastguard Worker     } else {
469*fb1b10abSAndroid Build Coastguard Worker       pthread_cond_signal(&lf_sync->recon_done_cond[row]);
470*fb1b10abSAndroid Build Coastguard Worker     }
471*fb1b10abSAndroid Build Coastguard Worker   }
472*fb1b10abSAndroid Build Coastguard Worker   pthread_mutex_unlock(&lf_sync->recon_done_mutex[row]);
473*fb1b10abSAndroid Build Coastguard Worker #else
474*fb1b10abSAndroid Build Coastguard Worker   (void)lf_sync;
475*fb1b10abSAndroid Build Coastguard Worker   (void)num_tiles;
476*fb1b10abSAndroid Build Coastguard Worker   (void)row;
477*fb1b10abSAndroid Build Coastguard Worker   (void)is_last_row;
478*fb1b10abSAndroid Build Coastguard Worker   (void)corrupted;
479*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_MULTITHREAD
480*fb1b10abSAndroid Build Coastguard Worker }
481*fb1b10abSAndroid Build Coastguard Worker 
vp9_loopfilter_job(LFWorkerData * lf_data,VP9LfSync * lf_sync)482*fb1b10abSAndroid Build Coastguard Worker void vp9_loopfilter_job(LFWorkerData *lf_data, VP9LfSync *lf_sync) {
483*fb1b10abSAndroid Build Coastguard Worker   thread_loop_filter_rows(lf_data->frame_buffer, lf_data->cm, lf_data->planes,
484*fb1b10abSAndroid Build Coastguard Worker                           lf_data->start, lf_data->stop, lf_data->y_only,
485*fb1b10abSAndroid Build Coastguard Worker                           lf_sync);
486*fb1b10abSAndroid Build Coastguard Worker }
487*fb1b10abSAndroid Build Coastguard Worker 
488*fb1b10abSAndroid Build Coastguard Worker // Accumulate frame counts.
vp9_accumulate_frame_counts(FRAME_COUNTS * accum,const FRAME_COUNTS * counts,int is_dec)489*fb1b10abSAndroid Build Coastguard Worker void vp9_accumulate_frame_counts(FRAME_COUNTS *accum,
490*fb1b10abSAndroid Build Coastguard Worker                                  const FRAME_COUNTS *counts, int is_dec) {
491*fb1b10abSAndroid Build Coastguard Worker   int i, j, k, l, m;
492*fb1b10abSAndroid Build Coastguard Worker 
493*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < BLOCK_SIZE_GROUPS; i++)
494*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < INTRA_MODES; j++)
495*fb1b10abSAndroid Build Coastguard Worker       accum->y_mode[i][j] += counts->y_mode[i][j];
496*fb1b10abSAndroid Build Coastguard Worker 
497*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < INTRA_MODES; i++)
498*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < INTRA_MODES; j++)
499*fb1b10abSAndroid Build Coastguard Worker       accum->uv_mode[i][j] += counts->uv_mode[i][j];
500*fb1b10abSAndroid Build Coastguard Worker 
501*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < PARTITION_CONTEXTS; i++)
502*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < PARTITION_TYPES; j++)
503*fb1b10abSAndroid Build Coastguard Worker       accum->partition[i][j] += counts->partition[i][j];
504*fb1b10abSAndroid Build Coastguard Worker 
505*fb1b10abSAndroid Build Coastguard Worker   if (is_dec) {
506*fb1b10abSAndroid Build Coastguard Worker     int n;
507*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < TX_SIZES; i++)
508*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < PLANE_TYPES; j++)
509*fb1b10abSAndroid Build Coastguard Worker         for (k = 0; k < REF_TYPES; k++)
510*fb1b10abSAndroid Build Coastguard Worker           for (l = 0; l < COEF_BANDS; l++)
511*fb1b10abSAndroid Build Coastguard Worker             for (m = 0; m < COEFF_CONTEXTS; m++) {
512*fb1b10abSAndroid Build Coastguard Worker               accum->eob_branch[i][j][k][l][m] +=
513*fb1b10abSAndroid Build Coastguard Worker                   counts->eob_branch[i][j][k][l][m];
514*fb1b10abSAndroid Build Coastguard Worker               for (n = 0; n < UNCONSTRAINED_NODES + 1; n++)
515*fb1b10abSAndroid Build Coastguard Worker                 accum->coef[i][j][k][l][m][n] += counts->coef[i][j][k][l][m][n];
516*fb1b10abSAndroid Build Coastguard Worker             }
517*fb1b10abSAndroid Build Coastguard Worker   } else {
518*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < TX_SIZES; i++)
519*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < PLANE_TYPES; j++)
520*fb1b10abSAndroid Build Coastguard Worker         for (k = 0; k < REF_TYPES; k++)
521*fb1b10abSAndroid Build Coastguard Worker           for (l = 0; l < COEF_BANDS; l++)
522*fb1b10abSAndroid Build Coastguard Worker             for (m = 0; m < COEFF_CONTEXTS; m++)
523*fb1b10abSAndroid Build Coastguard Worker               accum->eob_branch[i][j][k][l][m] +=
524*fb1b10abSAndroid Build Coastguard Worker                   counts->eob_branch[i][j][k][l][m];
525*fb1b10abSAndroid Build Coastguard Worker     // In the encoder, coef is only updated at frame
526*fb1b10abSAndroid Build Coastguard Worker     // level, so not need to accumulate it here.
527*fb1b10abSAndroid Build Coastguard Worker     // for (n = 0; n < UNCONSTRAINED_NODES + 1; n++)
528*fb1b10abSAndroid Build Coastguard Worker     //   accum->coef[i][j][k][l][m][n] +=
529*fb1b10abSAndroid Build Coastguard Worker     //       counts->coef[i][j][k][l][m][n];
530*fb1b10abSAndroid Build Coastguard Worker   }
531*fb1b10abSAndroid Build Coastguard Worker 
532*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++)
533*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < SWITCHABLE_FILTERS; j++)
534*fb1b10abSAndroid Build Coastguard Worker       accum->switchable_interp[i][j] += counts->switchable_interp[i][j];
535*fb1b10abSAndroid Build Coastguard Worker 
536*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < INTER_MODE_CONTEXTS; i++)
537*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < INTER_MODES; j++)
538*fb1b10abSAndroid Build Coastguard Worker       accum->inter_mode[i][j] += counts->inter_mode[i][j];
539*fb1b10abSAndroid Build Coastguard Worker 
540*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < INTRA_INTER_CONTEXTS; i++)
541*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 2; j++)
542*fb1b10abSAndroid Build Coastguard Worker       accum->intra_inter[i][j] += counts->intra_inter[i][j];
543*fb1b10abSAndroid Build Coastguard Worker 
544*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < COMP_INTER_CONTEXTS; i++)
545*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 2; j++) accum->comp_inter[i][j] += counts->comp_inter[i][j];
546*fb1b10abSAndroid Build Coastguard Worker 
547*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < REF_CONTEXTS; i++)
548*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 2; j++)
549*fb1b10abSAndroid Build Coastguard Worker       for (k = 0; k < 2; k++)
550*fb1b10abSAndroid Build Coastguard Worker         accum->single_ref[i][j][k] += counts->single_ref[i][j][k];
551*fb1b10abSAndroid Build Coastguard Worker 
552*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < REF_CONTEXTS; i++)
553*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 2; j++) accum->comp_ref[i][j] += counts->comp_ref[i][j];
554*fb1b10abSAndroid Build Coastguard Worker 
555*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < TX_SIZE_CONTEXTS; i++) {
556*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < TX_SIZES; j++)
557*fb1b10abSAndroid Build Coastguard Worker       accum->tx.p32x32[i][j] += counts->tx.p32x32[i][j];
558*fb1b10abSAndroid Build Coastguard Worker 
559*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < TX_SIZES - 1; j++)
560*fb1b10abSAndroid Build Coastguard Worker       accum->tx.p16x16[i][j] += counts->tx.p16x16[i][j];
561*fb1b10abSAndroid Build Coastguard Worker 
562*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < TX_SIZES - 2; j++)
563*fb1b10abSAndroid Build Coastguard Worker       accum->tx.p8x8[i][j] += counts->tx.p8x8[i][j];
564*fb1b10abSAndroid Build Coastguard Worker   }
565*fb1b10abSAndroid Build Coastguard Worker 
566*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < TX_SIZES; i++)
567*fb1b10abSAndroid Build Coastguard Worker     accum->tx.tx_totals[i] += counts->tx.tx_totals[i];
568*fb1b10abSAndroid Build Coastguard Worker 
569*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < SKIP_CONTEXTS; i++)
570*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 2; j++) accum->skip[i][j] += counts->skip[i][j];
571*fb1b10abSAndroid Build Coastguard Worker 
572*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < MV_JOINTS; i++) accum->mv.joints[i] += counts->mv.joints[i];
573*fb1b10abSAndroid Build Coastguard Worker 
574*fb1b10abSAndroid Build Coastguard Worker   for (k = 0; k < 2; k++) {
575*fb1b10abSAndroid Build Coastguard Worker     nmv_component_counts *const comps = &accum->mv.comps[k];
576*fb1b10abSAndroid Build Coastguard Worker     const nmv_component_counts *const comps_t = &counts->mv.comps[k];
577*fb1b10abSAndroid Build Coastguard Worker 
578*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < 2; i++) {
579*fb1b10abSAndroid Build Coastguard Worker       comps->sign[i] += comps_t->sign[i];
580*fb1b10abSAndroid Build Coastguard Worker       comps->class0_hp[i] += comps_t->class0_hp[i];
581*fb1b10abSAndroid Build Coastguard Worker       comps->hp[i] += comps_t->hp[i];
582*fb1b10abSAndroid Build Coastguard Worker     }
583*fb1b10abSAndroid Build Coastguard Worker 
584*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < MV_CLASSES; i++) comps->classes[i] += comps_t->classes[i];
585*fb1b10abSAndroid Build Coastguard Worker 
586*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < CLASS0_SIZE; i++) {
587*fb1b10abSAndroid Build Coastguard Worker       comps->class0[i] += comps_t->class0[i];
588*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < MV_FP_SIZE; j++)
589*fb1b10abSAndroid Build Coastguard Worker         comps->class0_fp[i][j] += comps_t->class0_fp[i][j];
590*fb1b10abSAndroid Build Coastguard Worker     }
591*fb1b10abSAndroid Build Coastguard Worker 
592*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < MV_OFFSET_BITS; i++)
593*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < 2; j++) comps->bits[i][j] += comps_t->bits[i][j];
594*fb1b10abSAndroid Build Coastguard Worker 
595*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < MV_FP_SIZE; i++) comps->fp[i] += comps_t->fp[i];
596*fb1b10abSAndroid Build Coastguard Worker   }
597*fb1b10abSAndroid Build Coastguard Worker }
598