vp9_ethread.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * Copyright (c) 2014 The WebM project authors. All Rights Reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #include "vp9/encoder/vp9_encodeframe.h"
  11. #include "vp9/encoder/vp9_encoder.h"
  12. #include "vp9/encoder/vp9_ethread.h"
  13. static void accumulate_rd_opt(ThreadData *td, ThreadData *td_t) {
  14. int i, j, k, l, m, n;
  15. for (i = 0; i < REFERENCE_MODES; i++)
  16. td->rd_counts.comp_pred_diff[i] += td_t->rd_counts.comp_pred_diff[i];
  17. for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++)
  18. td->rd_counts.filter_diff[i] += td_t->rd_counts.filter_diff[i];
  19. for (i = 0; i < TX_MODES; i++)
  20. td->rd_counts.tx_select_diff[i] += td_t->rd_counts.tx_select_diff[i];
  21. for (i = 0; i < TX_SIZES; i++)
  22. for (j = 0; j < PLANE_TYPES; j++)
  23. for (k = 0; k < REF_TYPES; k++)
  24. for (l = 0; l < COEF_BANDS; l++)
  25. for (m = 0; m < COEFF_CONTEXTS; m++)
  26. for (n = 0; n < ENTROPY_TOKENS; n++)
  27. td->rd_counts.coef_counts[i][j][k][l][m][n] +=
  28. td_t->rd_counts.coef_counts[i][j][k][l][m][n];
  29. }
  30. static int enc_worker_hook(EncWorkerData *const thread_data, void *unused) {
  31. VP9_COMP *const cpi = thread_data->cpi;
  32. const VP9_COMMON *const cm = &cpi->common;
  33. const int tile_cols = 1 << cm->log2_tile_cols;
  34. const int tile_rows = 1 << cm->log2_tile_rows;
  35. int t;
  36. (void) unused;
  37. for (t = thread_data->start; t < tile_rows * tile_cols;
  38. t += cpi->num_workers) {
  39. int tile_row = t / tile_cols;
  40. int tile_col = t % tile_cols;
  41. vp9_encode_tile(cpi, thread_data->td, tile_row, tile_col);
  42. }
  43. return 0;
  44. }
  45. void vp9_encode_tiles_mt(VP9_COMP *cpi) {
  46. VP9_COMMON *const cm = &cpi->common;
  47. const int tile_cols = 1 << cm->log2_tile_cols;
  48. const VP9WorkerInterface *const winterface = vp9_get_worker_interface();
  49. const int num_workers = MIN(cpi->oxcf.max_threads, tile_cols);
  50. int i;
  51. vp9_init_tile_data(cpi);
  52. // Only run once to create threads and allocate thread data.
  53. if (cpi->num_workers == 0) {
  54. CHECK_MEM_ERROR(cm, cpi->workers,
  55. vpx_malloc(num_workers * sizeof(*cpi->workers)));
  56. CHECK_MEM_ERROR(cm, cpi->tile_thr_data,
  57. vpx_calloc(num_workers, sizeof(*cpi->tile_thr_data)));
  58. for (i = 0; i < num_workers; i++) {
  59. VP9Worker *const worker = &cpi->workers[i];
  60. EncWorkerData *thread_data = &cpi->tile_thr_data[i];
  61. ++cpi->num_workers;
  62. winterface->init(worker);
  63. if (i < num_workers - 1) {
  64. thread_data->cpi = cpi;
  65. // Allocate thread data.
  66. CHECK_MEM_ERROR(cm, thread_data->td,
  67. vpx_memalign(32, sizeof(*thread_data->td)));
  68. vp9_zero(*thread_data->td);
  69. // Set up pc_tree.
  70. thread_data->td->leaf_tree = NULL;
  71. thread_data->td->pc_tree = NULL;
  72. vp9_setup_pc_tree(cm, thread_data->td);
  73. // Allocate frame counters in thread data.
  74. CHECK_MEM_ERROR(cm, thread_data->td->counts,
  75. vpx_calloc(1, sizeof(*thread_data->td->counts)));
  76. // Create threads
  77. if (!winterface->reset(worker))
  78. vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
  79. "Tile encoder thread creation failed");
  80. } else {
  81. // Main thread acts as a worker and uses the thread data in cpi.
  82. thread_data->cpi = cpi;
  83. thread_data->td = &cpi->td;
  84. }
  85. winterface->sync(worker);
  86. }
  87. }
  88. for (i = 0; i < num_workers; i++) {
  89. VP9Worker *const worker = &cpi->workers[i];
  90. EncWorkerData *thread_data;
  91. worker->hook = (VP9WorkerHook)enc_worker_hook;
  92. worker->data1 = &cpi->tile_thr_data[i];
  93. worker->data2 = NULL;
  94. thread_data = (EncWorkerData*)worker->data1;
  95. // Before encoding a frame, copy the thread data from cpi.
  96. if (thread_data->td != &cpi->td) {
  97. thread_data->td->mb = cpi->td.mb;
  98. thread_data->td->rd_counts = cpi->td.rd_counts;
  99. }
  100. if (thread_data->td->counts != &cpi->common.counts) {
  101. memcpy(thread_data->td->counts, &cpi->common.counts,
  102. sizeof(cpi->common.counts));
  103. }
  104. // Handle use_nonrd_pick_mode case.
  105. if (cpi->sf.use_nonrd_pick_mode) {
  106. MACROBLOCK *const x = &thread_data->td->mb;
  107. MACROBLOCKD *const xd = &x->e_mbd;
  108. struct macroblock_plane *const p = x->plane;
  109. struct macroblockd_plane *const pd = xd->plane;
  110. PICK_MODE_CONTEXT *ctx = &thread_data->td->pc_root->none;
  111. int j;
  112. for (j = 0; j < MAX_MB_PLANE; ++j) {
  113. p[j].coeff = ctx->coeff_pbuf[j][0];
  114. p[j].qcoeff = ctx->qcoeff_pbuf[j][0];
  115. pd[j].dqcoeff = ctx->dqcoeff_pbuf[j][0];
  116. p[j].eobs = ctx->eobs_pbuf[j][0];
  117. }
  118. }
  119. }
  120. // Encode a frame
  121. for (i = 0; i < num_workers; i++) {
  122. VP9Worker *const worker = &cpi->workers[i];
  123. EncWorkerData *const thread_data = (EncWorkerData*)worker->data1;
  124. // Set the starting tile for each thread.
  125. thread_data->start = i;
  126. if (i == num_workers - 1)
  127. winterface->execute(worker);
  128. else
  129. winterface->launch(worker);
  130. }
  131. // Encoding ends.
  132. for (i = 0; i < num_workers; i++) {
  133. VP9Worker *const worker = &cpi->workers[i];
  134. winterface->sync(worker);
  135. }
  136. for (i = 0; i < num_workers; i++) {
  137. VP9Worker *const worker = &cpi->workers[i];
  138. EncWorkerData *const thread_data = (EncWorkerData*)worker->data1;
  139. // Accumulate counters.
  140. if (i < num_workers - 1) {
  141. vp9_accumulate_frame_counts(cm, thread_data->td->counts, 0);
  142. accumulate_rd_opt(&cpi->td, thread_data->td);
  143. }
  144. }
  145. }