Пример #1
0
void vp9_worker_launch(VP9Worker* const worker) {
#if CONFIG_MULTITHREAD
  change_state(worker, WORK);
#else
  vp9_worker_execute(worker);
#endif
}
Пример #2
0
static THREADFN thread_loop(void *ptr) {    
  VP9Worker* const worker = (VP9Worker*)ptr;
  int done = 0;
  while (!done) {
    pthread_mutex_lock(&worker->mutex_);
    while (worker->status_ == OK) {   
      pthread_cond_wait(&worker->condition_, &worker->mutex_);
    }
    if (worker->status_ == WORK) {
      vp9_worker_execute(worker);
      worker->status_ = OK;
    } else if (worker->status_ == NOT_OK) {   
      done = 1;
    }
    
    pthread_cond_signal(&worker->condition_);
    pthread_mutex_unlock(&worker->mutex_);
  }
  return THREAD_RETURN(NULL);    
}
Пример #3
0
static THREADFN thread_loop(void *ptr) {    // thread loop
  VP9Worker* const worker = (VP9Worker*)ptr;
  int done = 0;
  while (!done) {
    pthread_mutex_lock(&worker->mutex_);
    while (worker->status_ == OK) {   // wait in idling mode
      pthread_cond_wait(&worker->condition_, &worker->mutex_);
    }
    if (worker->status_ == WORK) {
      vp9_worker_execute(worker);
      worker->status_ = OK;
    } else if (worker->status_ == NOT_OK) {   // finish the worker
      done = 1;
    }
    // signal to the main thread that we're done (for Sync())
    pthread_cond_signal(&worker->condition_);
    pthread_mutex_unlock(&worker->mutex_);
  }
  return THREAD_RETURN(NULL);    // Thread is finished
}
Пример #4
0
// VP9 decoder: Implement multi-threaded loopfilter that uses the tile
// threads.
void vp9_loop_filter_frame_mt(VP9Decoder *pbi,
                              VP9_COMMON *cm,
                              int frame_filter_level,
                              int y_only, int partial_frame) {
  VP9LfSync *const lf_sync = &pbi->lf_row_sync;
  // Number of superblock rows and cols
  const int sb_rows = mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2;
  const int tile_cols = 1 << cm->log2_tile_cols;
  const int num_workers = MIN(pbi->oxcf.max_threads & ~1, tile_cols);
  int i;

  // Allocate memory used in thread synchronization.
  // This always needs to be done even if frame_filter_level is 0.
  if (!cm->current_video_frame || cm->last_height != cm->height) {
    if (cm->last_height != cm->height) {
      const int aligned_last_height =
          ALIGN_POWER_OF_TWO(cm->last_height, MI_SIZE_LOG2);
      const int last_sb_rows =
          mi_cols_aligned_to_sb(aligned_last_height >> MI_SIZE_LOG2) >>
          MI_BLOCK_SIZE_LOG2;

      vp9_loop_filter_dealloc(lf_sync, last_sb_rows);
    }

    vp9_loop_filter_alloc(cm, lf_sync, sb_rows, cm->width);
  }

  if (!frame_filter_level) return;

  vp9_loop_filter_frame_init(cm, frame_filter_level);

  // Initialize cur_sb_col to -1 for all SB rows.
  vpx_memset(lf_sync->cur_sb_col, -1, sizeof(*lf_sync->cur_sb_col) * sb_rows);

  // Set up loopfilter thread data.
  // The decoder is using num_workers instead of pbi->num_tile_workers
  // because it has been observed that using more threads on the
  // loopfilter, than there are tile columns in the frame will hurt
  // performance on Android. This is because the system will only
  // schedule the tile decode workers on cores equal to the number
  // of tile columns. Then if the decoder tries to use more threads for the
  // loopfilter, it will hurt performance because of contention. If the
  // multithreading code changes in the future then the number of workers
  // used by the loopfilter should be revisited.
  for (i = 0; i < num_workers; ++i) {
    VP9Worker *const worker = &pbi->tile_workers[i];
    TileWorkerData *const tile_data = (TileWorkerData*)worker->data1;
    LFWorkerData *const lf_data = &tile_data->lfdata;

    worker->hook = (VP9WorkerHook)loop_filter_row_worker;

    // Loopfilter data
    lf_data->frame_buffer = get_frame_new_buffer(cm);
    lf_data->cm = cm;
    lf_data->xd = pbi->mb;
    lf_data->start = i;
    lf_data->stop = sb_rows;
    lf_data->y_only = y_only;   // always do all planes in decoder

    lf_data->lf_sync = lf_sync;
    lf_data->num_lf_workers = num_workers;

    // Start loopfiltering
    if (i == num_workers - 1) {
      vp9_worker_execute(worker);
    } else {
      vp9_worker_launch(worker);
    }
  }

  // Wait till all rows are finished
  for (i = 0; i < num_workers; ++i) {
    vp9_worker_sync(&pbi->tile_workers[i]);
  }
}