ethread.c 7.04 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
4
5
6
7
8
9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Jingning Han's avatar
Jingning Han committed
10
11
 */

12
13
14
#include "av1/encoder/encodeframe.h"
#include "av1/encoder/encoder.h"
#include "av1/encoder/ethread.h"
Yaowu Xu's avatar
Yaowu Xu committed
15
#include "aom_dsp/aom_dsp_common.h"
Jingning Han's avatar
Jingning Han committed
16
17
18
19
20
21
22

static void accumulate_rd_opt(ThreadData *td, ThreadData *td_t) {
  int i, j, k, l, m, n;

  for (i = 0; i < REFERENCE_MODES; i++)
    td->rd_counts.comp_pred_diff[i] += td_t->rd_counts.comp_pred_diff[i];

23
24
25
26
27
28
#if CONFIG_GLOBAL_MOTION
  for (i = 0; i < TOTAL_REFS_PER_FRAME; i++)
    td->rd_counts.global_motion_used[i] +=
        td_t->rd_counts.global_motion_used[i];
#endif  // CONFIG_GLOBAL_MOTION

Jingning Han's avatar
Jingning Han committed
29
30
31
32
33
34
35
36
37
38
39
  for (i = 0; i < TX_SIZES; i++)
    for (j = 0; j < PLANE_TYPES; j++)
      for (k = 0; k < REF_TYPES; k++)
        for (l = 0; l < COEF_BANDS; l++)
          for (m = 0; m < COEFF_CONTEXTS; m++)
            for (n = 0; n < ENTROPY_TOKENS; n++)
              td->rd_counts.coef_counts[i][j][k][l][m][n] +=
                  td_t->rd_counts.coef_counts[i][j][k][l][m][n];
}

static int enc_worker_hook(EncWorkerData *const thread_data, void *unused) {
Yaowu Xu's avatar
Yaowu Xu committed
40
41
  AV1_COMP *const cpi = thread_data->cpi;
  const AV1_COMMON *const cm = &cpi->common;
42
43
  const int tile_cols = cm->tile_cols;
  const int tile_rows = cm->tile_rows;
Jingning Han's avatar
Jingning Han committed
44
45
  int t;

46
  (void)unused;
Jingning Han's avatar
Jingning Han committed
47
48

  for (t = thread_data->start; t < tile_rows * tile_cols;
49
       t += cpi->num_workers) {
Jingning Han's avatar
Jingning Han committed
50
51
52
    int tile_row = t / tile_cols;
    int tile_col = t % tile_cols;

Yaowu Xu's avatar
Yaowu Xu committed
53
    av1_encode_tile(cpi, thread_data->td, tile_row, tile_col);
Jingning Han's avatar
Jingning Han committed
54
55
56
57
58
  }

  return 0;
}

Yaowu Xu's avatar
Yaowu Xu committed
59
60
void av1_encode_tiles_mt(AV1_COMP *cpi) {
  AV1_COMMON *const cm = &cpi->common;
61
  const int tile_cols = cm->tile_cols;
Yaowu Xu's avatar
Yaowu Xu committed
62
63
  const AVxWorkerInterface *const winterface = aom_get_worker_interface();
  const int num_workers = AOMMIN(cpi->oxcf.max_threads, tile_cols);
Jingning Han's avatar
Jingning Han committed
64
65
  int i;

Yaowu Xu's avatar
Yaowu Xu committed
66
  av1_init_tile_data(cpi);
Jingning Han's avatar
Jingning Han committed
67
68
69
70

  // Only run once to create threads and allocate thread data.
  if (cpi->num_workers == 0) {
    CHECK_MEM_ERROR(cm, cpi->workers,
Yaowu Xu's avatar
Yaowu Xu committed
71
                    aom_malloc(num_workers * sizeof(*cpi->workers)));
Jingning Han's avatar
Jingning Han committed
72
73

    CHECK_MEM_ERROR(cm, cpi->tile_thr_data,
Yaowu Xu's avatar
Yaowu Xu committed
74
                    aom_calloc(num_workers, sizeof(*cpi->tile_thr_data)));
Jingning Han's avatar
Jingning Han committed
75

76
    for (i = 0; i < num_workers; i++) {
Yaowu Xu's avatar
Yaowu Xu committed
77
      AVxWorker *const worker = &cpi->workers[i];
78
      EncWorkerData *const thread_data = &cpi->tile_thr_data[i];
Jingning Han's avatar
Jingning Han committed
79
80
81
82

      ++cpi->num_workers;
      winterface->init(worker);

83
84
85
      thread_data->cpi = cpi;

      if (i < num_workers - 1) {
Jingning Han's avatar
Jingning Han committed
86
87
        // Allocate thread data.
        CHECK_MEM_ERROR(cm, thread_data->td,
Yaowu Xu's avatar
Yaowu Xu committed
88
89
                        aom_memalign(32, sizeof(*thread_data->td)));
        av1_zero(*thread_data->td);
Jingning Han's avatar
Jingning Han committed
90
91
92
93

        // Set up pc_tree.
        thread_data->td->leaf_tree = NULL;
        thread_data->td->pc_tree = NULL;
Yaowu Xu's avatar
Yaowu Xu committed
94
        av1_setup_pc_tree(cm, thread_data->td);
Jingning Han's avatar
Jingning Han committed
95

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#if CONFIG_MOTION_VAR
#if CONFIG_HIGHBITDEPTH
        int buf_scaler = 2;
#else
        int buf_scaler = 1;
#endif
        CHECK_MEM_ERROR(cm, thread_data->td->above_pred_buf,
                        (uint8_t *)aom_memalign(
                            16, buf_scaler * MAX_MB_PLANE * MAX_SB_SQUARE *
                                    sizeof(*thread_data->td->above_pred_buf)));
        CHECK_MEM_ERROR(cm, thread_data->td->left_pred_buf,
                        (uint8_t *)aom_memalign(
                            16, buf_scaler * MAX_MB_PLANE * MAX_SB_SQUARE *
                                    sizeof(*thread_data->td->left_pred_buf)));
        CHECK_MEM_ERROR(
            cm, thread_data->td->wsrc_buf,
            (int32_t *)aom_memalign(
                16, MAX_SB_SQUARE * sizeof(*thread_data->td->wsrc_buf)));
        CHECK_MEM_ERROR(
            cm, thread_data->td->mask_buf,
            (int32_t *)aom_memalign(
                16, MAX_SB_SQUARE * sizeof(*thread_data->td->mask_buf)));
#endif
Jingning Han's avatar
Jingning Han committed
119
120
        // Allocate frame counters in thread data.
        CHECK_MEM_ERROR(cm, thread_data->td->counts,
Yaowu Xu's avatar
Yaowu Xu committed
121
                        aom_calloc(1, sizeof(*thread_data->td->counts)));
Jingning Han's avatar
Jingning Han committed
122

123
124
125
126
127
128
129
130
131
#if CONFIG_PALETTE
        // Allocate buffers used by palette coding mode.
        if (cpi->common.allow_screen_content_tools) {
          CHECK_MEM_ERROR(
              cm, thread_data->td->palette_buffer,
              aom_memalign(16, sizeof(*thread_data->td->palette_buffer)));
        }
#endif  // CONFIG_PALETTE

Jingning Han's avatar
Jingning Han committed
132
133
        // Create threads
        if (!winterface->reset(worker))
Yaowu Xu's avatar
Yaowu Xu committed
134
          aom_internal_error(&cm->error, AOM_CODEC_ERROR,
Jingning Han's avatar
Jingning Han committed
135
136
137
138
139
140
141
142
143
144
145
                             "Tile encoder thread creation failed");
      } else {
        // Main thread acts as a worker and uses the thread data in cpi.
        thread_data->td = &cpi->td;
      }

      winterface->sync(worker);
    }
  }

  for (i = 0; i < num_workers; i++) {
Yaowu Xu's avatar
Yaowu Xu committed
146
    AVxWorker *const worker = &cpi->workers[i];
Jingning Han's avatar
Jingning Han committed
147
148
    EncWorkerData *thread_data;

Yaowu Xu's avatar
Yaowu Xu committed
149
    worker->hook = (AVxWorkerHook)enc_worker_hook;
Jingning Han's avatar
Jingning Han committed
150
151
    worker->data1 = &cpi->tile_thr_data[i];
    worker->data2 = NULL;
152
    thread_data = (EncWorkerData *)worker->data1;
Jingning Han's avatar
Jingning Han committed
153
154
155
156
157

    // Before encoding a frame, copy the thread data from cpi.
    if (thread_data->td != &cpi->td) {
      thread_data->td->mb = cpi->td.mb;
      thread_data->td->rd_counts = cpi->td.rd_counts;
158
159
160
161
162
163
#if CONFIG_MOTION_VAR
      thread_data->td->mb.above_pred_buf = thread_data->td->above_pred_buf;
      thread_data->td->mb.left_pred_buf = thread_data->td->left_pred_buf;
      thread_data->td->mb.wsrc_buf = thread_data->td->wsrc_buf;
      thread_data->td->mb.mask_buf = thread_data->td->mask_buf;
#endif
Jingning Han's avatar
Jingning Han committed
164
165
166
167
168
    }
    if (thread_data->td->counts != &cpi->common.counts) {
      memcpy(thread_data->td->counts, &cpi->common.counts,
             sizeof(cpi->common.counts));
    }
hui su's avatar
hui su committed
169

170
#if CONFIG_PALETTE
171
172
    if (cpi->common.allow_screen_content_tools && i < num_workers - 1)
      thread_data->td->mb.palette_buffer = thread_data->td->palette_buffer;
173
#endif  // CONFIG_PALETTE
Jingning Han's avatar
Jingning Han committed
174
175
176
177
  }

  // Encode a frame
  for (i = 0; i < num_workers; i++) {
Yaowu Xu's avatar
Yaowu Xu committed
178
    AVxWorker *const worker = &cpi->workers[i];
179
    EncWorkerData *const thread_data = (EncWorkerData *)worker->data1;
Jingning Han's avatar
Jingning Han committed
180
181
182
183
184
185
186
187
188
189
190
191

    // Set the starting tile for each thread.
    thread_data->start = i;

    if (i == cpi->num_workers - 1)
      winterface->execute(worker);
    else
      winterface->launch(worker);
  }

  // Encoding ends.
  for (i = 0; i < num_workers; i++) {
Yaowu Xu's avatar
Yaowu Xu committed
192
    AVxWorker *const worker = &cpi->workers[i];
Jingning Han's avatar
Jingning Han committed
193
194
195
196
    winterface->sync(worker);
  }

  for (i = 0; i < num_workers; i++) {
Yaowu Xu's avatar
Yaowu Xu committed
197
    AVxWorker *const worker = &cpi->workers[i];
198
    EncWorkerData *const thread_data = (EncWorkerData *)worker->data1;
Jingning Han's avatar
Jingning Han committed
199
200
201

    // Accumulate counters.
    if (i < cpi->num_workers - 1) {
202
      av1_accumulate_frame_counts(&cm->counts, thread_data->td->counts);
Jingning Han's avatar
Jingning Han committed
203
      accumulate_rd_opt(&cpi->td, thread_data->td);
204
205
206
#if CONFIG_VAR_TX
      cpi->td.mb.txb_split_count += thread_data->td->mb.txb_split_count;
#endif
Jingning Han's avatar
Jingning Han committed
207
208
209
    }
  }
}