This commit bring all up-to-date changes from master that are applicable to nextgenv2. Due to the remove VP10 code in master, we had to cherry pick the following commits to get those changes: Add default flags for arm64/armv8 builds Allows building simple targets with sane default flags. For example, using the Android arm64 toolchain from the NDK: https://developer.android.com/ndk/guides/standalone_toolchain.html ./build/tools/make-standalone-toolchain.sh --arch=arm64 \ --platform=android-24 --install-dir=/tmp/arm64 CROSS=/tmp/arm64/bin/aarch64-linux-android- \ ~/libvpx/configure --target=arm64-linux-gcc --disable-multithread BUG=webm:1143 vpx_lpf_horizontal_4_sse2: Remove dead load. Change-Id: I51026c52baa1f0881fcd5b68e1fdf08a2dc0916e Fail early when android target does not include --sdk-path Change-Id: I07e7e63476a2e32e3aae123abdee8b7bbbdc6a8c configure: clean up var style and set_all usage Use quotes whenever possible and {} always for variables. Replace multiple set_all calls with *able_feature(). Conflicts: build/make/configure.sh vp9-svc: Remove some unneeded code/comment. datarate_test,DatarateTestLarge: normalize bits type quiets a msvc warning: conversion from 'const int64_t' to 'size_t', possible loss of data mips added p6600 cpu support Removed -funroll-loops psnr.c: use int64_t for sum of differences Since the values can be negative. *.asm: normalize label format add a trailing ':', though it's optional with the tools we support, it's more common to use it to mark a label. this also quiets the orphan-labels warning with nasm/yasm. BUG=b/29583530 Prevent negative variance Due to rounding, hbd variance may become negative. This commit put in check and clamp of negative values to 0. configure: remove old visual studio support (<2010) BUG=b/29583530 Conflicts: configure configure: restore vs_version variable inadvertently lost in the final patchset of:078dff7configure: remove old visual studio support (<2010) this prevents an empty CONFIG_VS_VERSION and avoids make failure Require x86inc.asm Force enable x86inc.asm when building for x86. Previously there were compatibility issues so a flag was added to simplify disabling this code. The known issues have been resolved and x86inc.asm is the preferred abstraction layer (over x86_abi_support.asm). BUG=b:29583530 convolve_test: fix byte offsets in hbd build CONVERT_TO_BYTEPTR(x) was corrected in:003a9d2Port metric computation changes from nextgenv2 to use the more common (x) within the expansion. offsets should occur after converting the pointer to the desired type. + factorized some common expressions Conflicts: test/convolve_test.cc vpx_dsp: remove x86inc.asm distinction BUG=b:29583530 Conflicts: vpx_dsp/vpx_dsp.mk vpx_dsp/vpx_dsp_rtcd_defs.pl vpx_dsp/x86/highbd_variance_sse2.c vpx_dsp/x86/variance_sse2.c test: remove x86inc.asm distinction BUG=b:29583530 Conflicts: test/vp9_subtract_test.cc configure: remove x86inc.asm distinction BUG=b:29583530 Change-Id: I59a1192142e89a6a36b906f65a491a734e603617 Update vpx subpixel 1d filter ssse3 asm Speed test shows the new vertical filters have degradation on Celeron Chromebook. Added "X86_SUBPIX_VFILTER_PREFER_SLOW_CELERON" to control the vertical filters activated code. Now just simply active the code without degradation on Celeron. Later there should be 2 set of vertical filters ssse3 functions, and let jump table to choose based on CPU type. improve vpx_filter_block1d* based on replace paddsw+psrlw to pmulhrsw Make set_reference control API work in VP9 Moved the API patch from NextGenv2. An example was included. To try it, for example, run the following command: $ examples/vpx_cx_set_ref vp9 352 288 in.yuv out.ivf 4 30 Conflicts: examples.mk examples/vpx_cx_set_ref.c test/cx_set_ref.sh vp9/decoder/vp9_decoder.c deblock filter : moved from vp8 code branch The deblocking filters used in vp8 have been moved to vpx_dsp for use by both vp8 and vp9. vpx_thread.[hc]: update webp source reference + drop the blob hash, the updated reference will be updated in the commit message BUG=b/29583578 vpx_thread: use native windows cond var if available BUG=b/29583578 original webp change: commit 110ad5835ecd66995d0e7f66dca1b90dea595f5a Author: James Zern <jzern@google.com> Date: Mon Nov 23 19:49:58 2015 -0800 thread: use native windows cond var if available Vista / Server 2008 and up. no speed difference observed. 100644 blob 4fc372b7bc6980a9ed3618c8cce5b67ed7b0f412 src/utils/thread.c 100644 blob 840831185502d42a3246e4b7ff870121c8064791 src/utils/thread.h vpx_thread: use InitializeCriticalSectionEx if available BUG=b/29583578 original webp change: commit 63fadc9ffacc77d4617526a50c696d21d558a70b Author: James Zern <jzern@google.com> Date: Mon Nov 23 20:38:46 2015 -0800 thread: use InitializeCriticalSectionEx if available Windows Vista / Server 2008 and up 100644 blob f84207d89b3a6bb98bfe8f3fa55cad72dfd061ff src/utils/thread.c 100644 blob 840831185502d42a3246e4b7ff870121c8064791 src/utils/thread.h vpx_thread: use WaitForSingleObjectEx if available BUG=b/29583578 original webp change: commit 0fd0e12bfe83f16ce4f1c038b251ccbc13c62ac2 Author: James Zern <jzern@google.com> Date: Mon Nov 23 20:40:26 2015 -0800 thread: use WaitForSingleObjectEx if available Windows XP and up 100644 blob d58f74e5523dbc985fc531cf5f0833f1e9157cf0 src/utils/thread.c 100644 blob 840831185502d42a3246e4b7ff870121c8064791 src/utils/thread.h vpx_thread: use CreateThread for windows phone BUG=b/29583578 original webp change: commit d2afe974f9d751de144ef09d31255aea13b442c0 Author: James Zern <jzern@google.com> Date: Mon Nov 23 20:41:26 2015 -0800 thread: use CreateThread for windows phone _beginthreadex is unavailable for winrt/uwp Change-Id: Ie7412a568278ac67f0047f1764e2521193d74d4d 100644 blob 93f7622797f05f6acc1126e8296c481d276e4047 src/utils/thread.c 100644 blob 840831185502d42a3246e4b7ff870121c8064791 src/utils/thread.h vp9_postproc.c missing extern. BUG=webm:1256 deblock: missing const on extern const. postproc - move filling of noise buffer to vpx_dsp. Fix encoder crashes for odd size input clean-up vp9_intrapred_test remove tuple and overkill VP9IntraPredBase class. postproc: noise style fixes. gtest-all.cc: quiet an unused variable warning under windows / mingw builds vp9_intrapred_test: follow-up cleanup address few comments fromce050afaf3Change-Id: I3eece7efa9335f4210303993ef6c1857ad5c29c8
		
			
				
	
	
		
			418 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			418 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// Copyright 2013 Google Inc. All Rights Reserved.
 | 
						|
//
 | 
						|
// Use of this source code is governed by a BSD-style license
 | 
						|
// that can be found in the COPYING file in the root of the source
 | 
						|
// tree. An additional intellectual property rights grant can be found
 | 
						|
// in the file PATENTS. All contributing project authors may
 | 
						|
// be found in the AUTHORS file in the root of the source tree.
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
//
 | 
						|
// Multi-threaded worker
 | 
						|
//
 | 
						|
// Original source:
 | 
						|
//  https://chromium.googlesource.com/webm/libwebp
 | 
						|
 | 
						|
#ifndef VPX_THREAD_H_
 | 
						|
#define VPX_THREAD_H_
 | 
						|
 | 
						|
#include "./vpx_config.h"
 | 
						|
 | 
						|
#ifdef __cplusplus
 | 
						|
extern "C" {
 | 
						|
#endif
 | 
						|
 | 
						|
// Set maximum decode threads to be 8 due to the limit of frame buffers
 | 
						|
// and not enough semaphores in the emulation layer on windows.
 | 
						|
#define MAX_DECODE_THREADS 8
 | 
						|
 | 
						|
#if CONFIG_MULTITHREAD
 | 
						|
 | 
						|
#if defined(_WIN32) && !HAVE_PTHREAD_H
 | 
						|
#include <errno.h>  // NOLINT
 | 
						|
#include <process.h>  // NOLINT
 | 
						|
#include <windows.h>  // NOLINT
 | 
						|
typedef HANDLE pthread_t;
 | 
						|
typedef CRITICAL_SECTION pthread_mutex_t;
 | 
						|
 | 
						|
#if _WIN32_WINNT >= 0x0600  // Windows Vista / Server 2008 or greater
 | 
						|
#define USE_WINDOWS_CONDITION_VARIABLE
 | 
						|
typedef CONDITION_VARIABLE pthread_cond_t;
 | 
						|
#else
 | 
						|
typedef struct {
 | 
						|
  HANDLE waiting_sem_;
 | 
						|
  HANDLE received_sem_;
 | 
						|
  HANDLE signal_event_;
 | 
						|
} pthread_cond_t;
 | 
						|
#endif  // _WIN32_WINNT >= 0x600
 | 
						|
 | 
						|
#ifndef WINAPI_FAMILY_PARTITION
 | 
						|
#define WINAPI_PARTITION_DESKTOP 1
 | 
						|
#define WINAPI_FAMILY_PARTITION(x) x
 | 
						|
#endif
 | 
						|
 | 
						|
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
 | 
						|
#define USE_CREATE_THREAD
 | 
						|
#endif
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
// simplistic pthread emulation layer
 | 
						|
 | 
						|
// _beginthreadex requires __stdcall
 | 
						|
#define THREADFN unsigned int __stdcall
 | 
						|
#define THREAD_RETURN(val) (unsigned int)((DWORD_PTR)val)
 | 
						|
 | 
						|
#if _WIN32_WINNT >= 0x0501  // Windows XP or greater
 | 
						|
#define WaitForSingleObject(obj, timeout) \
 | 
						|
  WaitForSingleObjectEx(obj, timeout, FALSE /*bAlertable*/)
 | 
						|
#endif
 | 
						|
 | 
						|
static INLINE int pthread_create(pthread_t* const thread, const void* attr,
 | 
						|
                                 unsigned int (__stdcall *start)(void*),
 | 
						|
                                 void* arg) {
 | 
						|
  (void)attr;
 | 
						|
#ifdef USE_CREATE_THREAD
 | 
						|
  *thread = CreateThread(NULL,   /* lpThreadAttributes */
 | 
						|
                         0,      /* dwStackSize */
 | 
						|
                         start,
 | 
						|
                         arg,
 | 
						|
                         0,      /* dwStackSize */
 | 
						|
                         NULL);  /* lpThreadId */
 | 
						|
#else
 | 
						|
  *thread = (pthread_t)_beginthreadex(NULL,   /* void *security */
 | 
						|
                                      0,      /* unsigned stack_size */
 | 
						|
                                      start,
 | 
						|
                                      arg,
 | 
						|
                                      0,      /* unsigned initflag */
 | 
						|
                                      NULL);  /* unsigned *thrdaddr */
 | 
						|
#endif
 | 
						|
  if (*thread == NULL) return 1;
 | 
						|
  SetThreadPriority(*thread, THREAD_PRIORITY_ABOVE_NORMAL);
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_join(pthread_t thread, void** value_ptr) {
 | 
						|
  (void)value_ptr;
 | 
						|
  return (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0 ||
 | 
						|
          CloseHandle(thread) == 0);
 | 
						|
}
 | 
						|
 | 
						|
// Mutex
 | 
						|
static INLINE int pthread_mutex_init(pthread_mutex_t *const mutex,
 | 
						|
                                     void* mutexattr) {
 | 
						|
  (void)mutexattr;
 | 
						|
#if _WIN32_WINNT >= 0x0600  // Windows Vista / Server 2008 or greater
 | 
						|
  InitializeCriticalSectionEx(mutex, 0 /*dwSpinCount*/, 0 /*Flags*/);
 | 
						|
#else
 | 
						|
  InitializeCriticalSection(mutex);
 | 
						|
#endif
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_mutex_trylock(pthread_mutex_t *const mutex) {
 | 
						|
  return TryEnterCriticalSection(mutex) ? 0 : EBUSY;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_mutex_lock(pthread_mutex_t *const mutex) {
 | 
						|
  EnterCriticalSection(mutex);
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_mutex_unlock(pthread_mutex_t *const mutex) {
 | 
						|
  LeaveCriticalSection(mutex);
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_mutex_destroy(pthread_mutex_t *const mutex) {
 | 
						|
  DeleteCriticalSection(mutex);
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
// Condition
 | 
						|
static INLINE int pthread_cond_destroy(pthread_cond_t *const condition) {
 | 
						|
  int ok = 1;
 | 
						|
#ifdef USE_WINDOWS_CONDITION_VARIABLE
 | 
						|
  (void)condition;
 | 
						|
#else
 | 
						|
  ok &= (CloseHandle(condition->waiting_sem_) != 0);
 | 
						|
  ok &= (CloseHandle(condition->received_sem_) != 0);
 | 
						|
  ok &= (CloseHandle(condition->signal_event_) != 0);
 | 
						|
#endif
 | 
						|
  return !ok;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_cond_init(pthread_cond_t *const condition,
 | 
						|
                                    void* cond_attr) {
 | 
						|
  (void)cond_attr;
 | 
						|
#ifdef USE_WINDOWS_CONDITION_VARIABLE
 | 
						|
  InitializeConditionVariable(condition);
 | 
						|
#else
 | 
						|
  condition->waiting_sem_ = CreateSemaphore(NULL, 0, MAX_DECODE_THREADS, NULL);
 | 
						|
  condition->received_sem_ = CreateSemaphore(NULL, 0, MAX_DECODE_THREADS, NULL);
 | 
						|
  condition->signal_event_ = CreateEvent(NULL, FALSE, FALSE, NULL);
 | 
						|
  if (condition->waiting_sem_ == NULL ||
 | 
						|
      condition->received_sem_ == NULL ||
 | 
						|
      condition->signal_event_ == NULL) {
 | 
						|
    pthread_cond_destroy(condition);
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
#endif
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_cond_signal(pthread_cond_t *const condition) {
 | 
						|
  int ok = 1;
 | 
						|
#ifdef USE_WINDOWS_CONDITION_VARIABLE
 | 
						|
  WakeConditionVariable(condition);
 | 
						|
#else
 | 
						|
  if (WaitForSingleObject(condition->waiting_sem_, 0) == WAIT_OBJECT_0) {
 | 
						|
    // a thread is waiting in pthread_cond_wait: allow it to be notified
 | 
						|
    ok = SetEvent(condition->signal_event_);
 | 
						|
    // wait until the event is consumed so the signaler cannot consume
 | 
						|
    // the event via its own pthread_cond_wait.
 | 
						|
    ok &= (WaitForSingleObject(condition->received_sem_, INFINITE) !=
 | 
						|
           WAIT_OBJECT_0);
 | 
						|
  }
 | 
						|
#endif
 | 
						|
  return !ok;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_cond_wait(pthread_cond_t *const condition,
 | 
						|
                                    pthread_mutex_t *const mutex) {
 | 
						|
  int ok;
 | 
						|
#ifdef USE_WINDOWS_CONDITION_VARIABLE
 | 
						|
  ok = SleepConditionVariableCS(condition, mutex, INFINITE);
 | 
						|
#else
 | 
						|
  // note that there is a consumer available so the signal isn't dropped in
 | 
						|
  // pthread_cond_signal
 | 
						|
  if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL))
 | 
						|
    return 1;
 | 
						|
  // now unlock the mutex so pthread_cond_signal may be issued
 | 
						|
  pthread_mutex_unlock(mutex);
 | 
						|
  ok = (WaitForSingleObject(condition->signal_event_, INFINITE) ==
 | 
						|
        WAIT_OBJECT_0);
 | 
						|
  ok &= ReleaseSemaphore(condition->received_sem_, 1, NULL);
 | 
						|
  pthread_mutex_lock(mutex);
 | 
						|
#endif
 | 
						|
  return !ok;
 | 
						|
}
 | 
						|
#elif defined(__OS2__)
 | 
						|
#define INCL_DOS
 | 
						|
#include <os2.h>    // NOLINT
 | 
						|
 | 
						|
#include <errno.h>  // NOLINT
 | 
						|
#include <stdlib.h> // NOLINT
 | 
						|
#include <sys/builtin.h> // NOLINT
 | 
						|
 | 
						|
#define pthread_t TID
 | 
						|
#define pthread_mutex_t HMTX
 | 
						|
 | 
						|
typedef struct {
 | 
						|
  HEV event_sem_;
 | 
						|
  HEV ack_sem_;
 | 
						|
  volatile unsigned wait_count_;
 | 
						|
} pthread_cond_t;
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
// simplistic pthread emulation layer
 | 
						|
 | 
						|
#define THREADFN void *
 | 
						|
#define THREAD_RETURN(val) (val)
 | 
						|
 | 
						|
typedef struct {
 | 
						|
  void* (*start_)(void*);
 | 
						|
  void* arg_;
 | 
						|
} thread_arg;
 | 
						|
 | 
						|
static void thread_start(void* arg) {
 | 
						|
  thread_arg targ = *(thread_arg *)arg;
 | 
						|
  free(arg);
 | 
						|
 | 
						|
  targ.start_(targ.arg_);
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_create(pthread_t* const thread, const void* attr,
 | 
						|
                                 void* (*start)(void*),
 | 
						|
                                 void* arg) {
 | 
						|
  int tid;
 | 
						|
  thread_arg *targ = (thread_arg *)malloc(sizeof(*targ));
 | 
						|
  if (targ == NULL) return 1;
 | 
						|
 | 
						|
  (void)attr;
 | 
						|
 | 
						|
  targ->start_ = start;
 | 
						|
  targ->arg_ = arg;
 | 
						|
  tid = (pthread_t)_beginthread(thread_start, NULL, 1024 * 1024, targ);
 | 
						|
  if (tid == -1) {
 | 
						|
    free(targ);
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
 | 
						|
  *thread = tid;
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_join(pthread_t thread, void** value_ptr) {
 | 
						|
  (void)value_ptr;
 | 
						|
  return DosWaitThread(&thread, DCWW_WAIT) != 0;
 | 
						|
}
 | 
						|
 | 
						|
// Mutex
 | 
						|
static INLINE int pthread_mutex_init(pthread_mutex_t *const mutex,
 | 
						|
                                     void* mutexattr) {
 | 
						|
  (void)mutexattr;
 | 
						|
  return DosCreateMutexSem(NULL, mutex, 0, FALSE) != 0;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_mutex_trylock(pthread_mutex_t *const mutex) {
 | 
						|
  return DosRequestMutexSem(*mutex, SEM_IMMEDIATE_RETURN) == 0 ? 0 : EBUSY;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_mutex_lock(pthread_mutex_t *const mutex) {
 | 
						|
  return DosRequestMutexSem(*mutex, SEM_INDEFINITE_WAIT) != 0;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_mutex_unlock(pthread_mutex_t *const mutex) {
 | 
						|
  return DosReleaseMutexSem(*mutex) != 0;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_mutex_destroy(pthread_mutex_t *const mutex) {
 | 
						|
  return DosCloseMutexSem(*mutex) != 0;
 | 
						|
}
 | 
						|
 | 
						|
// Condition
 | 
						|
static INLINE int pthread_cond_destroy(pthread_cond_t *const condition) {
 | 
						|
  int ok = 1;
 | 
						|
  ok &= DosCloseEventSem(condition->event_sem_) == 0;
 | 
						|
  ok &= DosCloseEventSem(condition->ack_sem_) == 0;
 | 
						|
  return !ok;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_cond_init(pthread_cond_t *const condition,
 | 
						|
                                    void* cond_attr) {
 | 
						|
  int ok = 1;
 | 
						|
  (void)cond_attr;
 | 
						|
 | 
						|
  ok &= DosCreateEventSem(NULL, &condition->event_sem_, DCE_POSTONE, FALSE)
 | 
						|
          == 0;
 | 
						|
  ok &= DosCreateEventSem(NULL, &condition->ack_sem_, DCE_POSTONE, FALSE) == 0;
 | 
						|
  if (!ok) {
 | 
						|
    pthread_cond_destroy(condition);
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
  condition->wait_count_ = 0;
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_cond_signal(pthread_cond_t *const condition) {
 | 
						|
  int ok = 1;
 | 
						|
 | 
						|
  if (!__atomic_cmpxchg32(&condition->wait_count_, 0, 0)) {
 | 
						|
    ok &= DosPostEventSem(condition->event_sem_) == 0;
 | 
						|
    ok &= DosWaitEventSem(condition->ack_sem_, SEM_INDEFINITE_WAIT) == 0;
 | 
						|
  }
 | 
						|
 | 
						|
  return !ok;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_cond_broadcast(pthread_cond_t *const condition) {
 | 
						|
  int ok = 1;
 | 
						|
 | 
						|
  while (!__atomic_cmpxchg32(&condition->wait_count_, 0, 0))
 | 
						|
      ok &= pthread_cond_signal(condition) == 0;
 | 
						|
 | 
						|
  return !ok;
 | 
						|
}
 | 
						|
 | 
						|
static INLINE int pthread_cond_wait(pthread_cond_t *const condition,
 | 
						|
                                    pthread_mutex_t *const mutex) {
 | 
						|
  int ok = 1;
 | 
						|
 | 
						|
  __atomic_increment(&condition->wait_count_);
 | 
						|
 | 
						|
  ok &= pthread_mutex_unlock(mutex) == 0;
 | 
						|
 | 
						|
  ok &= DosWaitEventSem(condition->event_sem_, SEM_INDEFINITE_WAIT) == 0;
 | 
						|
 | 
						|
  __atomic_decrement(&condition->wait_count_);
 | 
						|
 | 
						|
  ok &= DosPostEventSem(condition->ack_sem_) == 0;
 | 
						|
 | 
						|
  pthread_mutex_lock(mutex);
 | 
						|
 | 
						|
  return !ok;
 | 
						|
}
 | 
						|
#else  // _WIN32
 | 
						|
#include <pthread.h> // NOLINT
 | 
						|
# define THREADFN void*
 | 
						|
# define THREAD_RETURN(val) val
 | 
						|
#endif
 | 
						|
 | 
						|
#endif  // CONFIG_MULTITHREAD
 | 
						|
 | 
						|
// State of the worker thread object
 | 
						|
typedef enum {
 | 
						|
  NOT_OK = 0,   // object is unusable
 | 
						|
  OK,           // ready to work
 | 
						|
  WORK          // busy finishing the current task
 | 
						|
} VPxWorkerStatus;
 | 
						|
 | 
						|
// Function to be called by the worker thread. Takes two opaque pointers as
 | 
						|
// arguments (data1 and data2), and should return false in case of error.
 | 
						|
typedef int (*VPxWorkerHook)(void*, void*);
 | 
						|
 | 
						|
// Platform-dependent implementation details for the worker.
 | 
						|
typedef struct VPxWorkerImpl VPxWorkerImpl;
 | 
						|
 | 
						|
// Synchronization object used to launch job in the worker thread
 | 
						|
typedef struct {
 | 
						|
  VPxWorkerImpl *impl_;
 | 
						|
  VPxWorkerStatus status_;
 | 
						|
  VPxWorkerHook hook;     // hook to call
 | 
						|
  void *data1;            // first argument passed to 'hook'
 | 
						|
  void *data2;            // second argument passed to 'hook'
 | 
						|
  int had_error;          // return value of the last call to 'hook'
 | 
						|
} VPxWorker;
 | 
						|
 | 
						|
// The interface for all thread-worker related functions. All these functions
 | 
						|
// must be implemented.
 | 
						|
typedef struct {
 | 
						|
  // Must be called first, before any other method.
 | 
						|
  void (*init)(VPxWorker *const worker);
 | 
						|
  // Must be called to initialize the object and spawn the thread. Re-entrant.
 | 
						|
  // Will potentially launch the thread. Returns false in case of error.
 | 
						|
  int (*reset)(VPxWorker *const worker);
 | 
						|
  // Makes sure the previous work is finished. Returns true if worker->had_error
 | 
						|
  // was not set and no error condition was triggered by the working thread.
 | 
						|
  int (*sync)(VPxWorker *const worker);
 | 
						|
  // Triggers the thread to call hook() with data1 and data2 arguments. These
 | 
						|
  // hook/data1/data2 values can be changed at any time before calling this
 | 
						|
  // function, but not be changed afterward until the next call to Sync().
 | 
						|
  void (*launch)(VPxWorker *const worker);
 | 
						|
  // This function is similar to launch() except that it calls the
 | 
						|
  // hook directly instead of using a thread. Convenient to bypass the thread
 | 
						|
  // mechanism while still using the VPxWorker structs. sync() must
 | 
						|
  // still be called afterward (for error reporting).
 | 
						|
  void (*execute)(VPxWorker *const worker);
 | 
						|
  // Kill the thread and terminate the object. To use the object again, one
 | 
						|
  // must call reset() again.
 | 
						|
  void (*end)(VPxWorker *const worker);
 | 
						|
} VPxWorkerInterface;
 | 
						|
 | 
						|
// Install a new set of threading functions, overriding the defaults. This
 | 
						|
// should be done before any workers are started, i.e., before any encoding or
 | 
						|
// decoding takes place. The contents of the interface struct are copied, it
 | 
						|
// is safe to free the corresponding memory after this call. This function is
 | 
						|
// not thread-safe. Return false in case of invalid pointer or methods.
 | 
						|
int vpx_set_worker_interface(const VPxWorkerInterface *const winterface);
 | 
						|
 | 
						|
// Retrieve the currently set thread worker interface.
 | 
						|
const VPxWorkerInterface *vpx_get_worker_interface(void);
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
 | 
						|
#ifdef __cplusplus
 | 
						|
}    // extern "C"
 | 
						|
#endif
 | 
						|
 | 
						|
#endif  // VPX_THREAD_H_
 |