Coverage Report

Created: 2026-10-28 08:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvpx/vp8/decoder/threading.c
Line
Count
Source
1
/*
2
 *  Copyright (c) 2010 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 "vp8_rtcd.h"
13
#if !defined(_WIN32) && CONFIG_OS_SUPPORT == 1
14
#include <unistd.h>
15
#endif
16
#include "onyxd_int.h"
17
#include "vpx_mem/vpx_mem.h"
18
#include "vpx_util/vpx_pthread.h"
19
#include "vp8/common/common.h"
20
#include "vp8/common/threading.h"
21
#include "vp8/common/loopfilter.h"
22
#include "vp8/common/extend.h"
23
#include "vpx_ports/vpx_timer.h"
24
#include "decoderthreading.h"
25
#include "detokenize.h"
26
#include "vp8/common/reconintra4x4.h"
27
#include "vp8/common/reconinter.h"
28
#include "vp8/common/reconintra.h"
29
#include "vp8/common/setupintrarecon.h"
30
#if CONFIG_ERROR_CONCEALMENT
31
#include "error_concealment.h"
32
#endif
33
34
#define CALLOC_ARRAY(p, n) \
35
0
  CHECK_MEM_ERROR(&pbi->common.error, (p), vpx_calloc(sizeof(*(p)), (n)))
36
#define CALLOC_ARRAY_ALIGNED(p, n, algn)                       \
37
0
  do {                                                         \
38
0
    CHECK_MEM_ERROR(&pbi->common.error, (p),                   \
39
0
                    vpx_memalign((algn), sizeof(*(p)) * (n))); \
40
0
    memset((p), 0, (n) * sizeof(*(p)));                        \
41
0
  } while (0)
42
43
static void setup_decoding_thread_data(VP8D_COMP *pbi, MACROBLOCKD *xd,
44
0
                                       MB_ROW_DEC *mbrd, int count) {
45
0
  VP8_COMMON *const pc = &pbi->common;
46
0
  int i;
47
48
0
  for (i = 0; i < count; ++i) {
49
0
    MACROBLOCKD *mbd = &mbrd[i].mbd;
50
51
    // The worker MACROBLOCKDs persist across frames, so reset the per-frame
52
    // error state in line with the main thread (see vp8_decode_frame()).
53
    // This should only be done for keyframes or when error concealment
54
    // is active.
55
0
    if (pc->frame_type == KEY_FRAME || pbi->ec_active) {
56
0
      mbd->corrupted = 0;
57
0
    }
58
0
    mbd->error_info.error_code = 0;
59
60
0
    mbd->subpixel_predict = xd->subpixel_predict;
61
0
    mbd->subpixel_predict8x4 = xd->subpixel_predict8x4;
62
0
    mbd->subpixel_predict8x8 = xd->subpixel_predict8x8;
63
0
    mbd->subpixel_predict16x16 = xd->subpixel_predict16x16;
64
65
0
    mbd->frame_type = pc->frame_type;
66
0
    mbd->pre = xd->pre;
67
0
    mbd->dst = xd->dst;
68
69
0
    mbd->segmentation_enabled = xd->segmentation_enabled;
70
0
    mbd->mb_segment_abs_delta = xd->mb_segment_abs_delta;
71
0
    memcpy(mbd->segment_feature_data, xd->segment_feature_data,
72
0
           sizeof(xd->segment_feature_data));
73
74
    /*signed char ref_lf_deltas[MAX_REF_LF_DELTAS];*/
75
0
    memcpy(mbd->ref_lf_deltas, xd->ref_lf_deltas, sizeof(xd->ref_lf_deltas));
76
    /*signed char mode_lf_deltas[MAX_MODE_LF_DELTAS];*/
77
0
    memcpy(mbd->mode_lf_deltas, xd->mode_lf_deltas, sizeof(xd->mode_lf_deltas));
78
    /*unsigned char mode_ref_lf_delta_enabled;
79
    unsigned char mode_ref_lf_delta_update;*/
80
0
    mbd->mode_ref_lf_delta_enabled = xd->mode_ref_lf_delta_enabled;
81
0
    mbd->mode_ref_lf_delta_update = xd->mode_ref_lf_delta_update;
82
83
0
    mbd->current_bc = &pbi->mbc[0];
84
85
0
    memcpy(mbd->dequant_y1_dc, xd->dequant_y1_dc, sizeof(xd->dequant_y1_dc));
86
0
    memcpy(mbd->dequant_y1, xd->dequant_y1, sizeof(xd->dequant_y1));
87
0
    memcpy(mbd->dequant_y2, xd->dequant_y2, sizeof(xd->dequant_y2));
88
0
    memcpy(mbd->dequant_uv, xd->dequant_uv, sizeof(xd->dequant_uv));
89
90
0
    mbd->fullpixel_mask = ~0;
91
92
0
    if (pc->full_pixel) mbd->fullpixel_mask = ~7;
93
0
  }
94
95
0
  for (i = 0; i < pc->mb_rows; ++i)
96
0
    vpx_atomic_store_release(&pbi->mt_current_mb_col[i], -1);
97
0
}
98
99
static void mt_decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
100
0
                                 unsigned int mb_idx) {
101
0
  MB_PREDICTION_MODE mode;
102
0
  int i;
103
#if CONFIG_ERROR_CONCEALMENT
104
  int corruption_detected = 0;
105
#else
106
0
  (void)mb_idx;
107
0
#endif
108
109
0
  if (xd->mode_info_context->mbmi.mb_skip_coeff) {
110
0
    vp8_reset_mb_tokens_context(xd);
111
0
  } else if (!vp8dx_bool_error(xd->current_bc)) {
112
0
    int eobtotal;
113
0
    eobtotal = vp8_decode_mb_tokens(pbi, xd);
114
115
    /* Special case:  Force the loopfilter to skip when eobtotal is zero */
116
0
    xd->mode_info_context->mbmi.mb_skip_coeff = (eobtotal == 0);
117
0
  }
118
119
0
  mode = xd->mode_info_context->mbmi.mode;
120
121
0
  if (xd->segmentation_enabled) vp8_mb_init_dequantizer(pbi, xd);
122
123
#if CONFIG_ERROR_CONCEALMENT
124
125
  if (pbi->ec_active) {
126
    int throw_residual;
127
    /* When we have independent partitions we can apply residual even
128
     * though other partitions within the frame are corrupt.
129
     */
130
    throw_residual =
131
        (!pbi->independent_partitions && pbi->frame_corrupt_residual);
132
    throw_residual = (throw_residual || vp8dx_bool_error(xd->current_bc));
133
134
    if ((mb_idx >= pbi->mvs_corrupt_from_mb || throw_residual)) {
135
      /* MB with corrupt residuals or corrupt mode/motion vectors.
136
       * Better to use the predictor as reconstruction.
137
       */
138
      pbi->frame_corrupt_residual = 1;
139
      memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
140
141
      corruption_detected = 1;
142
143
      /* force idct to be skipped for B_PRED and use the
144
       * prediction only for reconstruction
145
       * */
146
      memset(xd->eobs, 0, 25);
147
    }
148
  }
149
#endif
150
151
  /* do prediction */
152
0
  if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
153
0
    vp8_build_intra_predictors_mbuv_s(
154
0
        xd, xd->recon_above[1], xd->recon_above[2], xd->recon_left[1],
155
0
        xd->recon_left[2], xd->recon_left_stride[1], xd->dst.u_buffer,
156
0
        xd->dst.v_buffer, xd->dst.uv_stride);
157
158
0
    if (mode != B_PRED) {
159
0
      vp8_build_intra_predictors_mby_s(
160
0
          xd, xd->recon_above[0], xd->recon_left[0], xd->recon_left_stride[0],
161
0
          xd->dst.y_buffer, xd->dst.y_stride);
162
0
    } else {
163
0
      short *DQC = xd->dequant_y1;
164
0
      int dst_stride = xd->dst.y_stride;
165
166
      /* clear out residual eob info */
167
0
      if (xd->mode_info_context->mbmi.mb_skip_coeff) memset(xd->eobs, 0, 25);
168
169
0
      intra_prediction_down_copy(xd, xd->recon_above[0] + 16);
170
171
0
      for (i = 0; i < 16; ++i) {
172
0
        BLOCKD *b = &xd->block[i];
173
0
        unsigned char *dst = xd->dst.y_buffer + b->offset;
174
0
        B_PREDICTION_MODE b_mode = xd->mode_info_context->bmi[i].as_mode;
175
0
        unsigned char *Above;
176
0
        unsigned char *yleft;
177
0
        int left_stride;
178
0
        unsigned char top_left;
179
180
        /*Caution: For some b_mode, it needs 8 pixels (4 above + 4
181
         * above-right).*/
182
0
        if (i < 4 && pbi->common.filter_level) {
183
0
          Above = xd->recon_above[0] + b->offset;
184
0
        } else {
185
0
          Above = dst - dst_stride;
186
0
        }
187
188
0
        if (i % 4 == 0 && pbi->common.filter_level) {
189
0
          yleft = xd->recon_left[0] + i;
190
0
          left_stride = 1;
191
0
        } else {
192
0
          yleft = dst - 1;
193
0
          left_stride = dst_stride;
194
0
        }
195
196
0
        if ((i == 4 || i == 8 || i == 12) && pbi->common.filter_level) {
197
0
          top_left = *(xd->recon_left[0] + i - 1);
198
0
        } else {
199
0
          top_left = Above[-1];
200
0
        }
201
202
0
        vp8_intra4x4_predict(Above, yleft, left_stride, b_mode, dst, dst_stride,
203
0
                             top_left);
204
205
0
        if (xd->eobs[i]) {
206
0
          if (xd->eobs[i] > 1) {
207
0
            vp8_dequant_idct_add(b->qcoeff, DQC, dst, dst_stride);
208
0
          } else {
209
0
            vp8_dc_only_idct_add(b->qcoeff[0] * DQC[0], dst, dst_stride, dst,
210
0
                                 dst_stride);
211
0
            memset(b->qcoeff, 0, 2 * sizeof(b->qcoeff[0]));
212
0
          }
213
0
        }
214
0
      }
215
0
    }
216
0
  } else {
217
0
    vp8_build_inter_predictors_mb(xd);
218
0
  }
219
220
#if CONFIG_ERROR_CONCEALMENT
221
  if (corruption_detected) {
222
    return;
223
  }
224
#endif
225
226
0
  if (!xd->mode_info_context->mbmi.mb_skip_coeff) {
227
    /* dequantization and idct */
228
0
    if (mode != B_PRED) {
229
0
      short *DQC = xd->dequant_y1;
230
231
0
      if (mode != SPLITMV) {
232
0
        BLOCKD *b = &xd->block[24];
233
234
        /* do 2nd order transform on the dc block */
235
0
        if (xd->eobs[24] > 1) {
236
0
          vp8_dequantize_b(b, xd->dequant_y2);
237
238
0
          vp8_short_inv_walsh4x4(&b->dqcoeff[0], xd->qcoeff);
239
0
          memset(b->qcoeff, 0, 16 * sizeof(b->qcoeff[0]));
240
0
        } else {
241
0
          b->dqcoeff[0] = (short)(b->qcoeff[0] * xd->dequant_y2[0]);
242
0
          vp8_short_inv_walsh4x4_1(&b->dqcoeff[0], xd->qcoeff);
243
0
          memset(b->qcoeff, 0, 2 * sizeof(b->qcoeff[0]));
244
0
        }
245
246
        /* override the dc dequant constant in order to preserve the
247
         * dc components
248
         */
249
0
        DQC = xd->dequant_y1_dc;
250
0
      }
251
252
0
      vp8_dequant_idct_add_y_block(xd->qcoeff, DQC, xd->dst.y_buffer,
253
0
                                   xd->dst.y_stride, xd->eobs);
254
0
    }
255
256
0
    vp8_dequant_idct_add_uv_block(xd->qcoeff + 16 * 16, xd->dequant_uv,
257
0
                                  xd->dst.u_buffer, xd->dst.v_buffer,
258
0
                                  xd->dst.uv_stride, xd->eobs + 16);
259
0
  }
260
0
}
261
262
static void mt_decode_mb_rows(VP8D_COMP *pbi, MACROBLOCKD *xd,
263
0
                              int start_mb_row) {
264
0
  const vpx_atomic_int *last_row_current_mb_col;
265
0
  vpx_atomic_int *current_mb_col;
266
0
  int mb_row;
267
0
  VP8_COMMON *pc = &pbi->common;
268
0
  const int nsync = pbi->sync_range;
269
0
  const vpx_atomic_int first_row_no_sync_above =
270
0
      VPX_ATOMIC_INIT(pc->mb_cols + nsync);
271
0
  int num_part = 1 << pbi->common.multi_token_partition;
272
0
  int last_mb_row = start_mb_row;
273
274
0
  YV12_BUFFER_CONFIG *yv12_fb_new = pbi->dec_fb_ref[INTRA_FRAME];
275
0
  YV12_BUFFER_CONFIG *yv12_fb_lst = pbi->dec_fb_ref[LAST_FRAME];
276
277
0
  int recon_y_stride = yv12_fb_new->y_stride;
278
0
  int recon_uv_stride = yv12_fb_new->uv_stride;
279
280
0
  unsigned char *ref_buffer[MAX_REF_FRAMES][3];
281
0
  unsigned char *dst_buffer[3];
282
0
  int i;
283
0
  int ref_fb_corrupted[MAX_REF_FRAMES];
284
285
0
  ref_fb_corrupted[INTRA_FRAME] = 0;
286
287
0
  for (i = 1; i < MAX_REF_FRAMES; ++i) {
288
0
    YV12_BUFFER_CONFIG *this_fb = pbi->dec_fb_ref[i];
289
290
0
    ref_buffer[i][0] = this_fb->y_buffer;
291
0
    ref_buffer[i][1] = this_fb->u_buffer;
292
0
    ref_buffer[i][2] = this_fb->v_buffer;
293
294
0
    ref_fb_corrupted[i] = this_fb->corrupted;
295
0
  }
296
297
0
  dst_buffer[0] = yv12_fb_new->y_buffer;
298
0
  dst_buffer[1] = yv12_fb_new->u_buffer;
299
0
  dst_buffer[2] = yv12_fb_new->v_buffer;
300
301
0
  xd->up_available = (start_mb_row != 0);
302
303
0
  xd->mode_info_context = pc->mi + pc->mode_info_stride * start_mb_row;
304
0
  xd->mode_info_stride = pc->mode_info_stride;
305
306
0
  for (mb_row = start_mb_row; mb_row < pc->mb_rows;
307
0
       mb_row += (pbi->decoding_thread_count + 1)) {
308
0
    int recon_yoffset, recon_uvoffset;
309
0
    int mb_col;
310
0
    int filter_level;
311
0
    loop_filter_info_n *lfi_n = &pc->lf_info;
312
313
    /* save last row processed by this thread */
314
0
    last_mb_row = mb_row;
315
    /* select bool coder for current partition */
316
0
    xd->current_bc = &pbi->mbc[mb_row % num_part];
317
318
0
    if (mb_row > 0) {
319
0
      last_row_current_mb_col = &pbi->mt_current_mb_col[mb_row - 1];
320
0
    } else {
321
0
      last_row_current_mb_col = &first_row_no_sync_above;
322
0
    }
323
324
0
    current_mb_col = &pbi->mt_current_mb_col[mb_row];
325
326
0
    recon_yoffset = mb_row * recon_y_stride * 16;
327
0
    recon_uvoffset = mb_row * recon_uv_stride * 8;
328
329
    /* reset contexts */
330
0
    xd->above_context = pc->above_context;
331
0
    memset(xd->left_context, 0, sizeof(ENTROPY_CONTEXT_PLANES));
332
333
0
    xd->left_available = 0;
334
335
0
    xd->mb_to_top_edge = -((mb_row * 16) << 3);
336
0
    xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;
337
338
0
    if (pbi->common.filter_level) {
339
0
      xd->recon_above[0] = pbi->mt_yabove_row[mb_row] + 0 * 16 + 32;
340
0
      xd->recon_above[1] = pbi->mt_uabove_row[mb_row] + 0 * 8 + 16;
341
0
      xd->recon_above[2] = pbi->mt_vabove_row[mb_row] + 0 * 8 + 16;
342
343
0
      xd->recon_left[0] = pbi->mt_yleft_col[mb_row];
344
0
      xd->recon_left[1] = pbi->mt_uleft_col[mb_row];
345
0
      xd->recon_left[2] = pbi->mt_vleft_col[mb_row];
346
347
      /* TODO: move to outside row loop */
348
0
      xd->recon_left_stride[0] = 1;
349
0
      xd->recon_left_stride[1] = 1;
350
0
    } else {
351
0
      xd->recon_above[0] = dst_buffer[0] + recon_yoffset;
352
0
      xd->recon_above[1] = dst_buffer[1] + recon_uvoffset;
353
0
      xd->recon_above[2] = dst_buffer[2] + recon_uvoffset;
354
355
0
      xd->recon_left[0] = xd->recon_above[0] - 1;
356
0
      xd->recon_left[1] = xd->recon_above[1] - 1;
357
0
      xd->recon_left[2] = xd->recon_above[2] - 1;
358
359
0
      xd->recon_above[0] -= xd->dst.y_stride;
360
0
      xd->recon_above[1] -= xd->dst.uv_stride;
361
0
      xd->recon_above[2] -= xd->dst.uv_stride;
362
363
      /* TODO: move to outside row loop */
364
0
      xd->recon_left_stride[0] = xd->dst.y_stride;
365
0
      xd->recon_left_stride[1] = xd->dst.uv_stride;
366
367
0
      setup_intra_recon_left(xd->recon_left[0], xd->recon_left[1],
368
0
                             xd->recon_left[2], xd->dst.y_stride,
369
0
                             xd->dst.uv_stride);
370
0
    }
371
372
0
    for (mb_col = 0; mb_col < pc->mb_cols; ++mb_col) {
373
0
      if (((mb_col - 1) % nsync) == 0) {
374
0
        vpx_atomic_store_release(current_mb_col, mb_col - 1);
375
0
      }
376
377
0
      if (mb_row && !(mb_col & (nsync - 1))) {
378
0
        vp8_atomic_spin_wait(mb_col, last_row_current_mb_col, nsync);
379
0
      }
380
381
      /* Distance of MB to the various image edges.
382
       * These are specified to 8th pel as they are always
383
       * compared to values that are in 1/8th pel units.
384
       */
385
0
      xd->mb_to_left_edge = -((mb_col * 16) << 3);
386
0
      xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
387
388
#if CONFIG_ERROR_CONCEALMENT
389
      {
390
        int corrupt_residual =
391
            (!pbi->independent_partitions && pbi->frame_corrupt_residual) ||
392
            vp8dx_bool_error(xd->current_bc);
393
        if (pbi->ec_active &&
394
            (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) &&
395
            corrupt_residual) {
396
          /* We have an intra block with corrupt
397
           * coefficients, better to conceal with an inter
398
           * block.
399
           * Interpolate MVs from neighboring MBs
400
           *
401
           * Note that for the first mb with corrupt
402
           * residual in a frame, we might not discover
403
           * that before decoding the residual. That
404
           * happens after this check, and therefore no
405
           * inter concealment will be done.
406
           */
407
          vp8_interpolate_motion(xd, mb_row, mb_col, pc->mb_rows, pc->mb_cols);
408
        }
409
      }
410
#endif
411
412
0
      xd->dst.y_buffer = dst_buffer[0] + recon_yoffset;
413
0
      xd->dst.u_buffer = dst_buffer[1] + recon_uvoffset;
414
0
      xd->dst.v_buffer = dst_buffer[2] + recon_uvoffset;
415
416
      /* propagate errors from reference frames */
417
0
      xd->corrupted |= ref_fb_corrupted[xd->mode_info_context->mbmi.ref_frame];
418
419
0
      if (xd->corrupted) {
420
        // Move current decoding marcoblock to the end of row for all rows
421
        // assigned to this thread, such that other threads won't be waiting.
422
0
        for (; mb_row < pc->mb_rows;
423
0
             mb_row += (pbi->decoding_thread_count + 1)) {
424
0
          current_mb_col = &pbi->mt_current_mb_col[mb_row];
425
0
          vpx_atomic_store_release(current_mb_col, pc->mb_cols + nsync);
426
0
        }
427
0
        vpx_internal_error(&xd->error_info, VPX_CODEC_CORRUPT_FRAME,
428
0
                           "Corrupted reference frame");
429
0
      }
430
431
0
      if (xd->mode_info_context->mbmi.ref_frame >= LAST_FRAME) {
432
0
        const MV_REFERENCE_FRAME ref = xd->mode_info_context->mbmi.ref_frame;
433
0
        xd->pre.y_buffer = ref_buffer[ref][0] + recon_yoffset;
434
0
        xd->pre.u_buffer = ref_buffer[ref][1] + recon_uvoffset;
435
0
        xd->pre.v_buffer = ref_buffer[ref][2] + recon_uvoffset;
436
0
      } else {
437
        // ref_frame is INTRA_FRAME, pre buffer should not be used.
438
0
        xd->pre.y_buffer = 0;
439
0
        xd->pre.u_buffer = 0;
440
0
        xd->pre.v_buffer = 0;
441
0
      }
442
0
      mt_decode_macroblock(pbi, xd, 0);
443
444
0
      xd->left_available = 1;
445
446
      /* check if the boolean decoder has suffered an error */
447
0
      xd->corrupted |= vp8dx_bool_error(xd->current_bc);
448
449
0
      xd->recon_above[0] += 16;
450
0
      xd->recon_above[1] += 8;
451
0
      xd->recon_above[2] += 8;
452
453
0
      if (!pbi->common.filter_level) {
454
0
        xd->recon_left[0] += 16;
455
0
        xd->recon_left[1] += 8;
456
0
        xd->recon_left[2] += 8;
457
0
      }
458
459
0
      if (pbi->common.filter_level) {
460
0
        int skip_lf = (xd->mode_info_context->mbmi.mode != B_PRED &&
461
0
                       xd->mode_info_context->mbmi.mode != SPLITMV &&
462
0
                       xd->mode_info_context->mbmi.mb_skip_coeff);
463
464
0
        const int mode_index =
465
0
            lfi_n->mode_lf_lut[xd->mode_info_context->mbmi.mode];
466
0
        const int seg = xd->mode_info_context->mbmi.segment_id;
467
0
        const int ref_frame = xd->mode_info_context->mbmi.ref_frame;
468
469
0
        filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
470
471
0
        if (mb_row != pc->mb_rows - 1) {
472
          /* Save decoded MB last row data for next-row decoding */
473
0
          memcpy((pbi->mt_yabove_row[mb_row + 1] + 32 + mb_col * 16),
474
0
                 (xd->dst.y_buffer + 15 * recon_y_stride), 16);
475
0
          memcpy((pbi->mt_uabove_row[mb_row + 1] + 16 + mb_col * 8),
476
0
                 (xd->dst.u_buffer + 7 * recon_uv_stride), 8);
477
0
          memcpy((pbi->mt_vabove_row[mb_row + 1] + 16 + mb_col * 8),
478
0
                 (xd->dst.v_buffer + 7 * recon_uv_stride), 8);
479
0
        }
480
481
        /* save left_col for next MB decoding */
482
0
        if (mb_col != pc->mb_cols - 1) {
483
0
          MODE_INFO *next = xd->mode_info_context + 1;
484
485
0
          if (next->mbmi.ref_frame == INTRA_FRAME) {
486
0
            for (i = 0; i < 16; ++i) {
487
0
              pbi->mt_yleft_col[mb_row][i] =
488
0
                  xd->dst.y_buffer[i * recon_y_stride + 15];
489
0
            }
490
0
            for (i = 0; i < 8; ++i) {
491
0
              pbi->mt_uleft_col[mb_row][i] =
492
0
                  xd->dst.u_buffer[i * recon_uv_stride + 7];
493
0
              pbi->mt_vleft_col[mb_row][i] =
494
0
                  xd->dst.v_buffer[i * recon_uv_stride + 7];
495
0
            }
496
0
          }
497
0
        }
498
499
        /* loopfilter on this macroblock. */
500
0
        if (filter_level) {
501
0
          if (pc->filter_type == NORMAL_LOOPFILTER) {
502
0
            loop_filter_info lfi;
503
0
            FRAME_TYPE frame_type = pc->frame_type;
504
0
            const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
505
0
            lfi.mblim = lfi_n->mblim[filter_level];
506
0
            lfi.blim = lfi_n->blim[filter_level];
507
0
            lfi.lim = lfi_n->lim[filter_level];
508
0
            lfi.hev_thr = lfi_n->hev_thr[hev_index];
509
510
0
            if (mb_col > 0)
511
0
              vp8_loop_filter_mbv(xd->dst.y_buffer, xd->dst.u_buffer,
512
0
                                  xd->dst.v_buffer, recon_y_stride,
513
0
                                  recon_uv_stride, &lfi);
514
515
0
            if (!skip_lf)
516
0
              vp8_loop_filter_bv(xd->dst.y_buffer, xd->dst.u_buffer,
517
0
                                 xd->dst.v_buffer, recon_y_stride,
518
0
                                 recon_uv_stride, &lfi);
519
520
            /* don't apply across umv border */
521
0
            if (mb_row > 0)
522
0
              vp8_loop_filter_mbh(xd->dst.y_buffer, xd->dst.u_buffer,
523
0
                                  xd->dst.v_buffer, recon_y_stride,
524
0
                                  recon_uv_stride, &lfi);
525
526
0
            if (!skip_lf)
527
0
              vp8_loop_filter_bh(xd->dst.y_buffer, xd->dst.u_buffer,
528
0
                                 xd->dst.v_buffer, recon_y_stride,
529
0
                                 recon_uv_stride, &lfi);
530
0
          } else {
531
0
            if (mb_col > 0)
532
0
              vp8_loop_filter_simple_mbv(xd->dst.y_buffer, recon_y_stride,
533
0
                                         lfi_n->mblim[filter_level]);
534
535
0
            if (!skip_lf)
536
0
              vp8_loop_filter_simple_bv(xd->dst.y_buffer, recon_y_stride,
537
0
                                        lfi_n->blim[filter_level]);
538
539
            /* don't apply across umv border */
540
0
            if (mb_row > 0)
541
0
              vp8_loop_filter_simple_mbh(xd->dst.y_buffer, recon_y_stride,
542
0
                                         lfi_n->mblim[filter_level]);
543
544
0
            if (!skip_lf)
545
0
              vp8_loop_filter_simple_bh(xd->dst.y_buffer, recon_y_stride,
546
0
                                        lfi_n->blim[filter_level]);
547
0
          }
548
0
        }
549
0
      }
550
551
0
      recon_yoffset += 16;
552
0
      recon_uvoffset += 8;
553
554
0
      ++xd->mode_info_context; /* next mb */
555
556
0
      xd->above_context++;
557
0
    }
558
559
    /* adjust to the next row of mbs */
560
0
    if (pbi->common.filter_level) {
561
0
      if (mb_row != pc->mb_rows - 1) {
562
0
        int lasty = yv12_fb_lst->y_width + VP8BORDERINPIXELS;
563
0
        int lastuv = (yv12_fb_lst->y_width >> 1) + (VP8BORDERINPIXELS >> 1);
564
565
0
        for (i = 0; i < 4; ++i) {
566
0
          pbi->mt_yabove_row[mb_row + 1][lasty + i] =
567
0
              pbi->mt_yabove_row[mb_row + 1][lasty - 1];
568
0
          pbi->mt_uabove_row[mb_row + 1][lastuv + i] =
569
0
              pbi->mt_uabove_row[mb_row + 1][lastuv - 1];
570
0
          pbi->mt_vabove_row[mb_row + 1][lastuv + i] =
571
0
              pbi->mt_vabove_row[mb_row + 1][lastuv - 1];
572
0
        }
573
0
      }
574
0
    } else {
575
0
      vp8_extend_mb_row(yv12_fb_new, xd->dst.y_buffer + 16,
576
0
                        xd->dst.u_buffer + 8, xd->dst.v_buffer + 8);
577
0
    }
578
579
    /* last MB of row is ready just after extension is done */
580
0
    vpx_atomic_store_release(current_mb_col, mb_col + nsync);
581
582
0
    ++xd->mode_info_context; /* skip prediction column */
583
0
    xd->up_available = 1;
584
585
    /* since we have multithread */
586
0
    xd->mode_info_context += xd->mode_info_stride * pbi->decoding_thread_count;
587
0
  }
588
589
  /* signal end of decoding of current thread for current frame */
590
0
  if (last_mb_row + (int)pbi->decoding_thread_count + 1 >= pc->mb_rows)
591
0
    vp8_sem_post(&pbi->h_event_end_decoding);
592
0
}
593
594
0
static THREADFN thread_decoding_proc(void *p_data) {
595
0
  int ithread = ((DECODETHREAD_DATA *)p_data)->ithread;
596
0
  VP8D_COMP *pbi = (VP8D_COMP *)(((DECODETHREAD_DATA *)p_data)->ptr1);
597
0
  MB_ROW_DEC *mbrd = (MB_ROW_DEC *)(((DECODETHREAD_DATA *)p_data)->ptr2);
598
0
  ENTROPY_CONTEXT_PLANES mb_row_left_context;
599
600
0
  while (1) {
601
0
    if (vpx_atomic_load_acquire(&pbi->b_multithreaded_rd) == 0) break;
602
603
0
    if (vp8_sem_wait(&pbi->h_event_start_decoding[ithread]) == 0) {
604
0
      if (vpx_atomic_load_acquire(&pbi->b_multithreaded_rd) == 0) {
605
0
        break;
606
0
      } else {
607
0
        MACROBLOCKD *xd = &mbrd->mbd;
608
0
        xd->left_context = &mb_row_left_context;
609
0
        if (setjmp(xd->error_info.jmp)) {
610
0
          xd->error_info.setjmp = 0;
611
          // Signal the end of decoding for current thread.
612
0
          vp8_sem_post(&pbi->h_event_end_decoding);
613
0
          continue;
614
0
        }
615
0
        xd->error_info.setjmp = 1;
616
0
        mt_decode_mb_rows(pbi, xd, ithread + 1);
617
0
        xd->error_info.setjmp = 0;
618
0
      }
619
0
    }
620
0
  }
621
622
0
  return THREAD_EXIT_SUCCESS;
623
0
}
624
625
7.14k
void vp8_decoder_create_threads(VP8D_COMP *pbi) {
626
7.14k
  int core_count = 0;
627
7.14k
  unsigned int ithread;
628
629
7.14k
  vpx_atomic_init(&pbi->b_multithreaded_rd, 0);
630
7.14k
  pbi->allocated_decoding_thread_count = 0;
631
632
  /* limit decoding threads to the max number of token partitions */
633
7.14k
  core_count = (pbi->max_threads > 8) ? 8 : pbi->max_threads;
634
635
  /* limit decoding threads to the available cores */
636
7.14k
  if (core_count > pbi->common.processor_core_count) {
637
0
    core_count = pbi->common.processor_core_count;
638
0
  }
639
640
7.14k
  if (core_count > 1) {
641
0
    vpx_atomic_init(&pbi->b_multithreaded_rd, 1);
642
0
    pbi->decoding_thread_count = core_count - 1;
643
644
0
    CALLOC_ARRAY(pbi->h_decoding_thread, pbi->decoding_thread_count);
645
0
    CALLOC_ARRAY(pbi->h_event_start_decoding, pbi->decoding_thread_count);
646
0
    CALLOC_ARRAY_ALIGNED(pbi->mb_row_di, pbi->decoding_thread_count, 32);
647
0
    CALLOC_ARRAY(pbi->de_thread_data, pbi->decoding_thread_count);
648
649
0
    if (vp8_sem_init(&pbi->h_event_end_decoding, 0, 0)) {
650
0
      vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,
651
0
                         "Failed to initialize semaphore");
652
0
    }
653
654
0
    for (ithread = 0; ithread < pbi->decoding_thread_count; ++ithread) {
655
0
      if (vp8_sem_init(&pbi->h_event_start_decoding[ithread], 0, 0)) break;
656
657
0
      vp8_setup_block_dptrs(&pbi->mb_row_di[ithread].mbd);
658
659
0
      pbi->de_thread_data[ithread].ithread = ithread;
660
0
      pbi->de_thread_data[ithread].ptr1 = (void *)pbi;
661
0
      pbi->de_thread_data[ithread].ptr2 = (void *)&pbi->mb_row_di[ithread];
662
663
0
      if (pthread_create(&pbi->h_decoding_thread[ithread], 0,
664
0
                         thread_decoding_proc, &pbi->de_thread_data[ithread])) {
665
0
        vp8_sem_destroy(&pbi->h_event_start_decoding[ithread]);
666
0
        break;
667
0
      }
668
0
    }
669
670
0
    pbi->allocated_decoding_thread_count = ithread;
671
0
    if (pbi->allocated_decoding_thread_count !=
672
0
        (int)pbi->decoding_thread_count) {
673
      /* the remainder of cleanup cases will be handled in
674
       * vp8_decoder_remove_threads(). */
675
0
      if (pbi->allocated_decoding_thread_count == 0) {
676
0
        vp8_sem_destroy(&pbi->h_event_end_decoding);
677
0
      }
678
0
      vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,
679
0
                         "Failed to create threads");
680
0
    }
681
0
  }
682
7.14k
}
683
684
0
void vp8mt_de_alloc_temp_buffers(VP8D_COMP *pbi, int mb_rows) {
685
0
  int i;
686
687
0
  vpx_free(pbi->mt_current_mb_col);
688
0
  pbi->mt_current_mb_col = NULL;
689
690
  /* Free above_row buffers. */
691
0
  if (pbi->mt_yabove_row) {
692
0
    for (i = 0; i < mb_rows; ++i) {
693
0
      vpx_free(pbi->mt_yabove_row[i]);
694
0
      pbi->mt_yabove_row[i] = NULL;
695
0
    }
696
0
    vpx_free(pbi->mt_yabove_row);
697
0
    pbi->mt_yabove_row = NULL;
698
0
  }
699
700
0
  if (pbi->mt_uabove_row) {
701
0
    for (i = 0; i < mb_rows; ++i) {
702
0
      vpx_free(pbi->mt_uabove_row[i]);
703
0
      pbi->mt_uabove_row[i] = NULL;
704
0
    }
705
0
    vpx_free(pbi->mt_uabove_row);
706
0
    pbi->mt_uabove_row = NULL;
707
0
  }
708
709
0
  if (pbi->mt_vabove_row) {
710
0
    for (i = 0; i < mb_rows; ++i) {
711
0
      vpx_free(pbi->mt_vabove_row[i]);
712
0
      pbi->mt_vabove_row[i] = NULL;
713
0
    }
714
0
    vpx_free(pbi->mt_vabove_row);
715
0
    pbi->mt_vabove_row = NULL;
716
0
  }
717
718
  /* Free left_col buffers. */
719
0
  if (pbi->mt_yleft_col) {
720
0
    for (i = 0; i < mb_rows; ++i) {
721
0
      vpx_free(pbi->mt_yleft_col[i]);
722
0
      pbi->mt_yleft_col[i] = NULL;
723
0
    }
724
0
    vpx_free(pbi->mt_yleft_col);
725
0
    pbi->mt_yleft_col = NULL;
726
0
  }
727
728
0
  if (pbi->mt_uleft_col) {
729
0
    for (i = 0; i < mb_rows; ++i) {
730
0
      vpx_free(pbi->mt_uleft_col[i]);
731
0
      pbi->mt_uleft_col[i] = NULL;
732
0
    }
733
0
    vpx_free(pbi->mt_uleft_col);
734
0
    pbi->mt_uleft_col = NULL;
735
0
  }
736
737
0
  if (pbi->mt_vleft_col) {
738
0
    for (i = 0; i < mb_rows; ++i) {
739
0
      vpx_free(pbi->mt_vleft_col[i]);
740
0
      pbi->mt_vleft_col[i] = NULL;
741
0
    }
742
0
    vpx_free(pbi->mt_vleft_col);
743
0
    pbi->mt_vleft_col = NULL;
744
0
  }
745
0
}
746
747
0
void vp8mt_alloc_temp_buffers(VP8D_COMP *pbi, int width, int prev_mb_rows) {
748
0
  VP8_COMMON *const pc = &pbi->common;
749
0
  int i;
750
0
  int uv_width;
751
752
0
  if (vpx_atomic_load_acquire(&pbi->b_multithreaded_rd)) {
753
0
    vp8mt_de_alloc_temp_buffers(pbi, prev_mb_rows);
754
755
    /* our internal buffers are always multiples of 16 */
756
0
    if ((width & 0xf) != 0) width += 16 - (width & 0xf);
757
758
0
    if (width < 640) {
759
0
      pbi->sync_range = 1;
760
0
    } else if (width <= 1280) {
761
0
      pbi->sync_range = 8;
762
0
    } else if (width <= 2560) {
763
0
      pbi->sync_range = 16;
764
0
    } else {
765
0
      pbi->sync_range = 32;
766
0
    }
767
768
0
    uv_width = width >> 1;
769
770
    /* Allocate a vpx_atomic_int for each mb row. */
771
0
    CHECK_MEM_ERROR(&pc->error, pbi->mt_current_mb_col,
772
0
                    vpx_malloc(sizeof(*pbi->mt_current_mb_col) * pc->mb_rows));
773
0
    for (i = 0; i < pc->mb_rows; ++i)
774
0
      vpx_atomic_init(&pbi->mt_current_mb_col[i], 0);
775
776
    /* Allocate memory for above_row buffers. */
777
0
    CALLOC_ARRAY(pbi->mt_yabove_row, pc->mb_rows);
778
0
    for (i = 0; i < pc->mb_rows; ++i) {
779
0
      CHECK_MEM_ERROR(&pc->error, pbi->mt_yabove_row[i],
780
0
                      vpx_memalign(16, sizeof(unsigned char) *
781
0
                                           (width + (VP8BORDERINPIXELS << 1))));
782
0
      vp8_zero_array(pbi->mt_yabove_row[i], width + (VP8BORDERINPIXELS << 1));
783
0
    }
784
785
0
    CALLOC_ARRAY(pbi->mt_uabove_row, pc->mb_rows);
786
0
    for (i = 0; i < pc->mb_rows; ++i) {
787
0
      CHECK_MEM_ERROR(&pc->error, pbi->mt_uabove_row[i],
788
0
                      vpx_memalign(16, sizeof(unsigned char) *
789
0
                                           (uv_width + VP8BORDERINPIXELS)));
790
0
      vp8_zero_array(pbi->mt_uabove_row[i], uv_width + VP8BORDERINPIXELS);
791
0
    }
792
793
0
    CALLOC_ARRAY(pbi->mt_vabove_row, pc->mb_rows);
794
0
    for (i = 0; i < pc->mb_rows; ++i) {
795
0
      CHECK_MEM_ERROR(&pc->error, pbi->mt_vabove_row[i],
796
0
                      vpx_memalign(16, sizeof(unsigned char) *
797
0
                                           (uv_width + VP8BORDERINPIXELS)));
798
0
      vp8_zero_array(pbi->mt_vabove_row[i], uv_width + VP8BORDERINPIXELS);
799
0
    }
800
801
    /* Allocate memory for left_col buffers. */
802
0
    CALLOC_ARRAY(pbi->mt_yleft_col, pc->mb_rows);
803
0
    for (i = 0; i < pc->mb_rows; ++i)
804
0
      CHECK_MEM_ERROR(&pc->error, pbi->mt_yleft_col[i],
805
0
                      vpx_calloc(sizeof(unsigned char) * 16, 1));
806
807
0
    CALLOC_ARRAY(pbi->mt_uleft_col, pc->mb_rows);
808
0
    for (i = 0; i < pc->mb_rows; ++i)
809
0
      CHECK_MEM_ERROR(&pc->error, pbi->mt_uleft_col[i],
810
0
                      vpx_calloc(sizeof(unsigned char) * 8, 1));
811
812
0
    CALLOC_ARRAY(pbi->mt_vleft_col, pc->mb_rows);
813
0
    for (i = 0; i < pc->mb_rows; ++i)
814
0
      CHECK_MEM_ERROR(&pc->error, pbi->mt_vleft_col[i],
815
0
                      vpx_calloc(sizeof(unsigned char) * 8, 1));
816
0
  }
817
0
}
818
819
7.14k
void vp8_decoder_remove_threads(VP8D_COMP *pbi) {
820
  /* shutdown MB Decoding thread; */
821
7.14k
  if (vpx_atomic_load_acquire(&pbi->b_multithreaded_rd)) {
822
0
    int i;
823
0
    vpx_atomic_store_release(&pbi->b_multithreaded_rd, 0);
824
825
    /* allow all threads to exit */
826
0
    for (i = 0; i < pbi->allocated_decoding_thread_count; ++i) {
827
0
      vp8_sem_post(&pbi->h_event_start_decoding[i]);
828
0
      pthread_join(pbi->h_decoding_thread[i], NULL);
829
0
    }
830
831
0
    for (i = 0; i < pbi->allocated_decoding_thread_count; ++i) {
832
0
      vp8_sem_destroy(&pbi->h_event_start_decoding[i]);
833
0
    }
834
835
0
    if (pbi->allocated_decoding_thread_count) {
836
0
      vp8_sem_destroy(&pbi->h_event_end_decoding);
837
0
    }
838
839
0
    vpx_free(pbi->h_decoding_thread);
840
0
    pbi->h_decoding_thread = NULL;
841
842
0
    vpx_free(pbi->h_event_start_decoding);
843
0
    pbi->h_event_start_decoding = NULL;
844
845
0
    vpx_free(pbi->mb_row_di);
846
0
    pbi->mb_row_di = NULL;
847
848
0
    vpx_free(pbi->de_thread_data);
849
0
    pbi->de_thread_data = NULL;
850
851
0
    vp8mt_de_alloc_temp_buffers(pbi, pbi->common.mb_rows);
852
0
  }
853
7.14k
}
854
855
0
int vp8mt_decode_mb_rows(VP8D_COMP *pbi, MACROBLOCKD *xd) {
856
0
  VP8_COMMON *pc = &pbi->common;
857
0
  unsigned int i;
858
0
  int j;
859
860
0
  int filter_level = pc->filter_level;
861
0
  YV12_BUFFER_CONFIG *yv12_fb_new = pbi->dec_fb_ref[INTRA_FRAME];
862
863
0
  if (filter_level) {
864
    /* Set above_row buffer to 127 for decoding first MB row */
865
0
    memset(pbi->mt_yabove_row[0] + VP8BORDERINPIXELS - 1, 127,
866
0
           yv12_fb_new->y_width + 5);
867
0
    memset(pbi->mt_uabove_row[0] + (VP8BORDERINPIXELS >> 1) - 1, 127,
868
0
           (yv12_fb_new->y_width >> 1) + 5);
869
0
    memset(pbi->mt_vabove_row[0] + (VP8BORDERINPIXELS >> 1) - 1, 127,
870
0
           (yv12_fb_new->y_width >> 1) + 5);
871
872
0
    for (j = 1; j < pc->mb_rows; ++j) {
873
0
      memset(pbi->mt_yabove_row[j] + VP8BORDERINPIXELS - 1, (unsigned char)129,
874
0
             1);
875
0
      memset(pbi->mt_uabove_row[j] + (VP8BORDERINPIXELS >> 1) - 1,
876
0
             (unsigned char)129, 1);
877
0
      memset(pbi->mt_vabove_row[j] + (VP8BORDERINPIXELS >> 1) - 1,
878
0
             (unsigned char)129, 1);
879
0
    }
880
881
    /* Set left_col to 129 initially */
882
0
    for (j = 0; j < pc->mb_rows; ++j) {
883
0
      memset(pbi->mt_yleft_col[j], (unsigned char)129, 16);
884
0
      memset(pbi->mt_uleft_col[j], (unsigned char)129, 8);
885
0
      memset(pbi->mt_vleft_col[j], (unsigned char)129, 8);
886
0
    }
887
888
    /* Initialize the loop filter for this frame. */
889
0
    vp8_loop_filter_frame_init(pc, &pbi->mb, filter_level);
890
0
  } else {
891
0
    vp8_setup_intra_recon_top_line(yv12_fb_new);
892
0
  }
893
894
0
  setup_decoding_thread_data(pbi, xd, pbi->mb_row_di,
895
0
                             pbi->decoding_thread_count);
896
897
0
  for (i = 0; i < pbi->decoding_thread_count; ++i) {
898
0
    vp8_sem_post(&pbi->h_event_start_decoding[i]);
899
0
  }
900
901
0
  if (setjmp(xd->error_info.jmp)) {
902
0
    xd->error_info.setjmp = 0;
903
0
    xd->corrupted = 1;
904
    // Wait for other threads to finish. This prevents other threads decoding
905
    // the current frame while the main thread starts decoding the next frame,
906
    // which causes a data race.
907
0
    for (i = 0; i < pbi->decoding_thread_count; ++i)
908
0
      vp8_sem_wait(&pbi->h_event_end_decoding);
909
0
    return -1;
910
0
  }
911
912
0
  xd->error_info.setjmp = 1;
913
0
  mt_decode_mb_rows(pbi, xd, 0);
914
0
  xd->error_info.setjmp = 0;
915
916
0
  for (i = 0; i < pbi->decoding_thread_count + 1; ++i)
917
0
    vp8_sem_wait(&pbi->h_event_end_decoding); /* add back for each frame */
918
919
0
  for (i = 0; i < pbi->decoding_thread_count; ++i) {
920
0
    if (pbi->mb_row_di[i].mbd.error_info.error_code) {
921
0
      xd->error_info = pbi->mb_row_di[i].mbd.error_info;
922
0
      return -1;
923
0
    }
924
0
  }
925
926
0
  return 0;
927
0
}