// main entry point int VP8EncAnalyze(VP8Encoder* const enc) { int ok = 1; const int do_segments = enc->config_->emulate_jpeg_size || // We need the complexity evaluation. (enc->segment_hdr_.num_segments_ > 1) || (enc->method_ == 0); // for method 0, we need preds_[] to be filled. if (do_segments) { const int last_row = enc->mb_h_; // We give a little more than a half work to the main thread. const int split_row = (9 * last_row + 15) >> 4; const int total_mb = last_row * enc->mb_w_; #ifdef WEBP_USE_THREAD const int kMinSplitRow = 2; // minimal rows needed for mt to be worth it const int do_mt = (enc->thread_level_ > 0) && (split_row >= kMinSplitRow); #else const int do_mt = 0; #endif SegmentJob main_job; if (do_mt) { SegmentJob side_job; // Note the use of '&' instead of '&&' because we must call the functions // no matter what. InitSegmentJob(enc, &main_job, 0, split_row); InitSegmentJob(enc, &side_job, split_row, last_row); // we don't need to call Reset() on main_job.worker, since we're calling // WebPWorkerExecute() on it ok &= WebPWorkerReset(&side_job.worker); // launch the two jobs in parallel if (ok) { WebPWorkerLaunch(&side_job.worker); WebPWorkerExecute(&main_job.worker); ok &= WebPWorkerSync(&side_job.worker); ok &= WebPWorkerSync(&main_job.worker); } WebPWorkerEnd(&side_job.worker); if (ok) MergeJobs(&side_job, &main_job); // merge results together } else { // Even for single-thread case, we use the generic Worker tools. InitSegmentJob(enc, &main_job, 0, last_row); WebPWorkerExecute(&main_job.worker); ok &= WebPWorkerSync(&main_job.worker); } WebPWorkerEnd(&main_job.worker); if (ok) { enc->alpha_ = main_job.alpha / total_mb; enc->uv_alpha_ = main_job.uv_alpha / total_mb; AssignSegments(enc, main_job.alphas); } } else { // Use only one default segment.
void WebPWorkerLaunch(WebPWorker* const worker) { #ifdef WEBP_USE_THREAD ChangeState(worker, WORK); #else WebPWorkerExecute(worker); #endif }
static THREADFN ThreadLoop(void* ptr) { WebPWorker* const worker = (WebPWorker*)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) { WebPWorkerExecute(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 }