2
0

vp9_ethread.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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. #include "vpx_dsp/vpx_dsp_common.h"
  14. static void accumulate_rd_opt(ThreadData *td, ThreadData *td_t) {
  15. int i, j, k, l, m, n;
  16. for (i = 0; i < REFERENCE_MODES; i++)
  17. td->rd_counts.comp_pred_diff[i] += td_t->rd_counts.comp_pred_diff[i];
  18. for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++)
  19. td->rd_counts.filter_diff[i] += td_t->rd_counts.filter_diff[i];
  20. for (i = 0; i < TX_SIZES; i++)
  21. for (j = 0; j < PLANE_TYPES; j++)
  22. for (k = 0; k < REF_TYPES; k++)
  23. for (l = 0; l < COEF_BANDS; l++)
  24. for (m = 0; m < COEFF_CONTEXTS; m++)
  25. for (n = 0; n < ENTROPY_TOKENS; n++)
  26. td->rd_counts.coef_counts[i][j][k][l][m][n] +=
  27. td_t->rd_counts.coef_counts[i][j][k][l][m][n];
  28. // Counts of all motion searches and exhuastive mesh searches.
  29. td->rd_counts.m_search_count += td_t->rd_counts.m_search_count;
  30. td->rd_counts.ex_search_count += td_t->rd_counts.ex_search_count;
  31. }
  32. static int enc_worker_hook(EncWorkerData *const thread_data, void *unused) {
  33. VP9_COMP *const cpi = thread_data->cpi;
  34. const VP9_COMMON *const cm = &cpi->common;
  35. const int tile_cols = 1 << cm->log2_tile_cols;
  36. const int tile_rows = 1 << cm->log2_tile_rows;
  37. int t;
  38. (void)unused;
  39. for (t = thread_data->start; t < tile_rows * tile_cols;
  40. t += cpi->num_workers) {
  41. int tile_row = t / tile_cols;
  42. int tile_col = t % tile_cols;
  43. vp9_encode_tile(cpi, thread_data->td, tile_row, tile_col);
  44. }
  45. return 0;
  46. }
  47. static int get_max_tile_cols(VP9_COMP *cpi) {
  48. const int aligned_width = ALIGN_POWER_OF_TWO(cpi->oxcf.width, MI_SIZE_LOG2);
  49. int mi_cols = aligned_width >> MI_SIZE_LOG2;
  50. int min_log2_tile_cols, max_log2_tile_cols;
  51. int log2_tile_cols;
  52. vp9_get_tile_n_bits(mi_cols, &min_log2_tile_cols, &max_log2_tile_cols);
  53. log2_tile_cols =
  54. clamp(cpi->oxcf.tile_columns, min_log2_tile_cols, max_log2_tile_cols);
  55. return (1 << log2_tile_cols);
  56. }
  57. void vp9_encode_tiles_mt(VP9_COMP *cpi) {
  58. VP9_COMMON *const cm = &cpi->common;
  59. const int tile_cols = 1 << cm->log2_tile_cols;
  60. const VPxWorkerInterface *const winterface = vpx_get_worker_interface();
  61. const int num_workers = VPXMIN(cpi->oxcf.max_threads, tile_cols);
  62. int i;
  63. vp9_init_tile_data(cpi);
  64. // Only run once to create threads and allocate thread data.
  65. if (cpi->num_workers == 0) {
  66. int allocated_workers = num_workers;
  67. // While using SVC, we need to allocate threads according to the highest
  68. // resolution.
  69. if (cpi->use_svc) {
  70. int max_tile_cols = get_max_tile_cols(cpi);
  71. allocated_workers = VPXMIN(cpi->oxcf.max_threads, max_tile_cols);
  72. }
  73. CHECK_MEM_ERROR(cm, cpi->workers,
  74. vpx_malloc(allocated_workers * sizeof(*cpi->workers)));
  75. CHECK_MEM_ERROR(cm, cpi->tile_thr_data,
  76. vpx_calloc(allocated_workers, sizeof(*cpi->tile_thr_data)));
  77. for (i = 0; i < allocated_workers; i++) {
  78. VPxWorker *const worker = &cpi->workers[i];
  79. EncWorkerData *thread_data = &cpi->tile_thr_data[i];
  80. ++cpi->num_workers;
  81. winterface->init(worker);
  82. if (i < allocated_workers - 1) {
  83. thread_data->cpi = cpi;
  84. // Allocate thread data.
  85. CHECK_MEM_ERROR(cm, thread_data->td,
  86. vpx_memalign(32, sizeof(*thread_data->td)));
  87. vp9_zero(*thread_data->td);
  88. // Set up pc_tree.
  89. thread_data->td->leaf_tree = NULL;
  90. thread_data->td->pc_tree = NULL;
  91. vp9_setup_pc_tree(cm, thread_data->td);
  92. // Allocate frame counters in thread data.
  93. CHECK_MEM_ERROR(cm, thread_data->td->counts,
  94. vpx_calloc(1, sizeof(*thread_data->td->counts)));
  95. // Create threads
  96. if (!winterface->reset(worker))
  97. vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
  98. "Tile encoder thread creation failed");
  99. } else {
  100. // Main thread acts as a worker and uses the thread data in cpi.
  101. thread_data->cpi = cpi;
  102. thread_data->td = &cpi->td;
  103. }
  104. winterface->sync(worker);
  105. }
  106. }
  107. for (i = 0; i < num_workers; i++) {
  108. VPxWorker *const worker = &cpi->workers[i];
  109. EncWorkerData *thread_data;
  110. worker->hook = (VPxWorkerHook)enc_worker_hook;
  111. worker->data1 = &cpi->tile_thr_data[i];
  112. worker->data2 = NULL;
  113. thread_data = (EncWorkerData *)worker->data1;
  114. // Before encoding a frame, copy the thread data from cpi.
  115. if (thread_data->td != &cpi->td) {
  116. thread_data->td->mb = cpi->td.mb;
  117. thread_data->td->rd_counts = cpi->td.rd_counts;
  118. }
  119. if (thread_data->td->counts != &cpi->common.counts) {
  120. memcpy(thread_data->td->counts, &cpi->common.counts,
  121. sizeof(cpi->common.counts));
  122. }
  123. // Handle use_nonrd_pick_mode case.
  124. if (cpi->sf.use_nonrd_pick_mode) {
  125. MACROBLOCK *const x = &thread_data->td->mb;
  126. MACROBLOCKD *const xd = &x->e_mbd;
  127. struct macroblock_plane *const p = x->plane;
  128. struct macroblockd_plane *const pd = xd->plane;
  129. PICK_MODE_CONTEXT *ctx = &thread_data->td->pc_root->none;
  130. int j;
  131. for (j = 0; j < MAX_MB_PLANE; ++j) {
  132. p[j].coeff = ctx->coeff_pbuf[j][0];
  133. p[j].qcoeff = ctx->qcoeff_pbuf[j][0];
  134. pd[j].dqcoeff = ctx->dqcoeff_pbuf[j][0];
  135. p[j].eobs = ctx->eobs_pbuf[j][0];
  136. }
  137. }
  138. }
  139. // Encode a frame
  140. for (i = 0; i < num_workers; i++) {
  141. VPxWorker *const worker = &cpi->workers[i];
  142. EncWorkerData *const thread_data = (EncWorkerData *)worker->data1;
  143. // Set the starting tile for each thread.
  144. thread_data->start = i;
  145. if (i == cpi->num_workers - 1)
  146. winterface->execute(worker);
  147. else
  148. winterface->launch(worker);
  149. }
  150. // Encoding ends.
  151. for (i = 0; i < num_workers; i++) {
  152. VPxWorker *const worker = &cpi->workers[i];
  153. winterface->sync(worker);
  154. }
  155. for (i = 0; i < num_workers; i++) {
  156. VPxWorker *const worker = &cpi->workers[i];
  157. EncWorkerData *const thread_data = (EncWorkerData *)worker->data1;
  158. // Accumulate counters.
  159. if (i < cpi->num_workers - 1) {
  160. vp9_accumulate_frame_counts(&cm->counts, thread_data->td->counts, 0);
  161. accumulate_rd_opt(&cpi->td, thread_data->td);
  162. }
  163. }
  164. }