Merge commit '90f9a5830b5d332de7ebb1ab45589f1870cbd65d'
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 24 May 2013 10:32:18 +0000 (12:32 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 24 May 2013 11:01:41 +0000 (13:01 +0200)
* commit '90f9a5830b5d332de7ebb1ab45589f1870cbd65d':
  w32pthreads: move from lavc to compat/

Conflicts:
libavcodec/Makefile
libavcodec/pthread.c
libavcodec/vp8.h

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
Makefile
compat/w32pthreads.h
libavcodec/Makefile
libavcodec/frame_thread_encoder.c
libavcodec/pthread.c
libavcodec/vp8.h
libavformat/network.c

diff --cc Makefile
+++ b/Makefile
@@@ -40,10 -82,9 +40,10 @@@ FFLIBS-$(CONFIG_SWSCALE)  += swscal
  
  FFLIBS := avutil
  
 -DATA_FILES := $(wildcard $(SRC_PATH)/presets/*.avpreset)
 +DATA_FILES := $(wildcard $(SRC_PATH)/presets/*.ffpreset) $(SRC_PATH)/doc/ffprobe.xsd
 +EXAMPLES_FILES := $(wildcard $(SRC_PATH)/doc/examples/*.c) $(SRC_PATH)/doc/examples/Makefile $(SRC_PATH)/doc/examples/README
  
- SKIPHEADERS = cmdutils_common_opts.h
+ SKIPHEADERS = cmdutils_common_opts.h compat/w32pthreads.h
  
  include $(SRC_PATH)/common.mak
  
index 0000000,a5ff6ac..71c1da6
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,279 +1,280 @@@
 - * This file is part of Libav.
+ /*
+  * Copyright (C) 2010-2011 x264 project
+  *
+  * Authors: Steven Walters <kemuri9@gmail.com>
+  *          Pegasys Inc. <http://www.pegasys-inc.com>
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ /**
+  * @file
+  * w32threads to pthreads wrapper
+  */
+ #ifndef LIBAV_W32PTHREADS_H
+ #define LIBAV_W32PTHREADS_H
+ /* Build up a pthread-like API using underlying Windows API. Have only static
+  * methods so as to not conflict with a potentially linked in pthread-win32
+  * library.
+  * As most functions here are used without checking return values,
+  * only implement return values as necessary. */
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+ #include <process.h>
++#include "libavutil/common.h"
+ #include "libavutil/internal.h"
+ #include "libavutil/mem.h"
+ typedef struct pthread_t {
+     void *handle;
+     void *(*func)(void* arg);
+     void *arg;
+     void *ret;
+ } pthread_t;
+ /* the conditional variable api for windows 6.0+ uses critical sections and
+  * not mutexes */
+ typedef CRITICAL_SECTION pthread_mutex_t;
+ /* This is the CONDITIONAL_VARIABLE typedef for using Window's native
+  * conditional variables on kernels 6.0+.
+  * MinGW does not currently have this typedef. */
+ typedef struct pthread_cond_t {
+     void *ptr;
+ } pthread_cond_t;
+ /* function pointers to conditional variable API on windows 6.0+ kernels */
+ static void (WINAPI *cond_broadcast)(pthread_cond_t *cond);
+ static void (WINAPI *cond_init)(pthread_cond_t *cond);
+ static void (WINAPI *cond_signal)(pthread_cond_t *cond);
+ static BOOL (WINAPI *cond_wait)(pthread_cond_t *cond, pthread_mutex_t *mutex,
+                                 DWORD milliseconds);
+ static unsigned __stdcall attribute_align_arg win32thread_worker(void *arg)
+ {
+     pthread_t *h = arg;
+     h->ret = h->func(h->arg);
+     return 0;
+ }
+ static int pthread_create(pthread_t *thread, const void *unused_attr,
+                           void *(*start_routine)(void*), void *arg)
+ {
+     thread->func   = start_routine;
+     thread->arg    = arg;
+     thread->handle = (void*)_beginthreadex(NULL, 0, win32thread_worker, thread,
+                                            0, NULL);
+     return !thread->handle;
+ }
+ static void pthread_join(pthread_t thread, void **value_ptr)
+ {
+     DWORD ret = WaitForSingleObject(thread.handle, INFINITE);
+     if (ret != WAIT_OBJECT_0)
+         return;
+     if (value_ptr)
+         *value_ptr = thread.ret;
+     CloseHandle(thread.handle);
+ }
+ static inline int pthread_mutex_init(pthread_mutex_t *m, void* attr)
+ {
+     InitializeCriticalSection(m);
+     return 0;
+ }
+ static inline int pthread_mutex_destroy(pthread_mutex_t *m)
+ {
+     DeleteCriticalSection(m);
+     return 0;
+ }
+ static inline int pthread_mutex_lock(pthread_mutex_t *m)
+ {
+     EnterCriticalSection(m);
+     return 0;
+ }
+ static inline int pthread_mutex_unlock(pthread_mutex_t *m)
+ {
+     LeaveCriticalSection(m);
+     return 0;
+ }
+ /* for pre-Windows 6.0 platforms we need to define and use our own condition
+  * variable and api */
+ typedef struct  win32_cond_t {
+     pthread_mutex_t mtx_broadcast;
+     pthread_mutex_t mtx_waiter_count;
+     volatile int waiter_count;
+     HANDLE semaphore;
+     HANDLE waiters_done;
+     volatile int is_broadcast;
+ } win32_cond_t;
+ static void pthread_cond_init(pthread_cond_t *cond, const void *unused_attr)
+ {
+     win32_cond_t *win32_cond = NULL;
+     if (cond_init) {
+         cond_init(cond);
+         return;
+     }
+     /* non native condition variables */
+     win32_cond = av_mallocz(sizeof(win32_cond_t));
+     if (!win32_cond)
+         return;
+     cond->ptr = win32_cond;
+     win32_cond->semaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
+     if (!win32_cond->semaphore)
+         return;
+     win32_cond->waiters_done = CreateEvent(NULL, TRUE, FALSE, NULL);
+     if (!win32_cond->waiters_done)
+         return;
+     pthread_mutex_init(&win32_cond->mtx_waiter_count, NULL);
+     pthread_mutex_init(&win32_cond->mtx_broadcast, NULL);
+ }
+ static void pthread_cond_destroy(pthread_cond_t *cond)
+ {
+     win32_cond_t *win32_cond = cond->ptr;
+     /* native condition variables do not destroy */
+     if (cond_init)
+         return;
+     /* non native condition variables */
+     CloseHandle(win32_cond->semaphore);
+     CloseHandle(win32_cond->waiters_done);
+     pthread_mutex_destroy(&win32_cond->mtx_waiter_count);
+     pthread_mutex_destroy(&win32_cond->mtx_broadcast);
+     av_freep(&win32_cond);
+     cond->ptr = NULL;
+ }
+ static void pthread_cond_broadcast(pthread_cond_t *cond)
+ {
+     win32_cond_t *win32_cond = cond->ptr;
+     int have_waiter;
+     if (cond_broadcast) {
+         cond_broadcast(cond);
+         return;
+     }
+     /* non native condition variables */
+     pthread_mutex_lock(&win32_cond->mtx_broadcast);
+     pthread_mutex_lock(&win32_cond->mtx_waiter_count);
+     have_waiter = 0;
+     if (win32_cond->waiter_count) {
+         win32_cond->is_broadcast = 1;
+         have_waiter = 1;
+     }
+     if (have_waiter) {
+         ReleaseSemaphore(win32_cond->semaphore, win32_cond->waiter_count, NULL);
+         pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
+         WaitForSingleObject(win32_cond->waiters_done, INFINITE);
+         ResetEvent(win32_cond->waiters_done);
+         win32_cond->is_broadcast = 0;
+     } else
+         pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
+     pthread_mutex_unlock(&win32_cond->mtx_broadcast);
+ }
+ static int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
+ {
+     win32_cond_t *win32_cond = cond->ptr;
+     int last_waiter;
+     if (cond_wait) {
+         cond_wait(cond, mutex, INFINITE);
+         return 0;
+     }
+     /* non native condition variables */
+     pthread_mutex_lock(&win32_cond->mtx_broadcast);
+     pthread_mutex_lock(&win32_cond->mtx_waiter_count);
+     win32_cond->waiter_count++;
+     pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
+     pthread_mutex_unlock(&win32_cond->mtx_broadcast);
+     // unlock the external mutex
+     pthread_mutex_unlock(mutex);
+     WaitForSingleObject(win32_cond->semaphore, INFINITE);
+     pthread_mutex_lock(&win32_cond->mtx_waiter_count);
+     win32_cond->waiter_count--;
+     last_waiter = !win32_cond->waiter_count || !win32_cond->is_broadcast;
+     pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
+     if (last_waiter)
+         SetEvent(win32_cond->waiters_done);
+     // lock the external mutex
+     return pthread_mutex_lock(mutex);
+ }
+ static void pthread_cond_signal(pthread_cond_t *cond)
+ {
+     win32_cond_t *win32_cond = cond->ptr;
+     int have_waiter;
+     if (cond_signal) {
+         cond_signal(cond);
+         return;
+     }
+     pthread_mutex_lock(&win32_cond->mtx_broadcast);
+     /* non-native condition variables */
+     pthread_mutex_lock(&win32_cond->mtx_waiter_count);
+     have_waiter = win32_cond->waiter_count;
+     pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
+     if (have_waiter) {
+         ReleaseSemaphore(win32_cond->semaphore, 1, NULL);
+         WaitForSingleObject(win32_cond->waiters_done, INFINITE);
+         ResetEvent(win32_cond->waiters_done);
+     }
+     pthread_mutex_unlock(&win32_cond->mtx_broadcast);
+ }
+ static void w32thread_init(void)
+ {
+ #if _WIN32_WINNT < 0x0600
+     HANDLE kernel_dll = GetModuleHandle(TEXT("kernel32.dll"));
+     /* if one is available, then they should all be available */
+     cond_init      =
+         (void*)GetProcAddress(kernel_dll, "InitializeConditionVariable");
+     cond_broadcast =
+         (void*)GetProcAddress(kernel_dll, "WakeAllConditionVariable");
+     cond_signal    =
+         (void*)GetProcAddress(kernel_dll, "WakeConditionVariable");
+     cond_wait      =
+         (void*)GetProcAddress(kernel_dll, "SleepConditionVariableCS");
+ #else
+     cond_init      = InitializeConditionVariable;
+     cond_broadcast = WakeAllConditionVariable;
+     cond_signal    = WakeConditionVariable;
+     cond_wait      = SleepConditionVariableCS;
+ #endif
+ }
+ #endif /* LIBAV_W32PTHREADS_H */
@@@ -803,11 -679,10 +803,10 @@@ SKIPHEADERS-$(CONFIG_MPEG_XVMC_DECODER
  SKIPHEADERS-$(CONFIG_VAAPI)            += vaapi_internal.h
  SKIPHEADERS-$(CONFIG_VDA)              += vda.h
  SKIPHEADERS-$(CONFIG_VDPAU)            += vdpau.h
- SKIPHEADERS-$(HAVE_W32THREADS)         += w32pthreads.h
 +SKIPHEADERS-$(HAVE_OS2THREADS)         += os2threads.h
  
 -EXAMPLES = api
 -
 -TESTPROGS = dct                                                         \
 +TESTPROGS = cabac                                                       \
 +            dct                                                         \
              fft                                                         \
              fft-fixed                                                   \
              golomb                                                      \
index b11a54a,0000000..98c50ab
mode 100644,000000..100644
--- /dev/null
@@@ -1,270 -1,0 +1,270 @@@
- #include "w32pthreads.h"
 +/*
 + * Copyright (c) 2012 Michael Niedermayer <michaelni@gmx.at>
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "frame_thread_encoder.h"
 +
 +#include "libavutil/fifo.h"
 +#include "libavutil/avassert.h"
 +#include "libavutil/imgutils.h"
 +#include "avcodec.h"
 +#include "internal.h"
 +#include "thread.h"
 +
 +#if HAVE_PTHREADS
 +#include <pthread.h>
 +#elif HAVE_W32THREADS
++#include "compat/w32pthreads.h"
 +#elif HAVE_OS2THREADS
 +#include "os2threads.h"
 +#endif
 +
 +#define MAX_THREADS 64
 +#define BUFFER_SIZE (2*MAX_THREADS)
 +
 +typedef struct{
 +    void *indata;
 +    void *outdata;
 +    int64_t return_code;
 +    unsigned index;
 +} Task;
 +
 +typedef struct{
 +    AVCodecContext *parent_avctx;
 +    pthread_mutex_t buffer_mutex;
 +
 +    AVFifoBuffer *task_fifo;
 +    pthread_mutex_t task_fifo_mutex;
 +    pthread_cond_t task_fifo_cond;
 +
 +    Task finished_tasks[BUFFER_SIZE];
 +    pthread_mutex_t finished_task_mutex;
 +    pthread_cond_t finished_task_cond;
 +
 +    unsigned task_index;
 +    unsigned finished_task_index;
 +
 +    pthread_t worker[MAX_THREADS];
 +    int exit;
 +} ThreadContext;
 +
 +static void * attribute_align_arg worker(void *v){
 +    AVCodecContext *avctx = v;
 +    ThreadContext *c = avctx->internal->frame_thread_encoder;
 +    AVPacket *pkt = NULL;
 +
 +    while(!c->exit){
 +        int got_packet, ret;
 +        AVFrame *frame;
 +        Task task;
 +
 +        if(!pkt) pkt= av_mallocz(sizeof(*pkt));
 +        if(!pkt) continue;
 +        av_init_packet(pkt);
 +
 +        pthread_mutex_lock(&c->task_fifo_mutex);
 +        while (av_fifo_size(c->task_fifo) <= 0 || c->exit) {
 +            if(c->exit){
 +                pthread_mutex_unlock(&c->task_fifo_mutex);
 +                goto end;
 +            }
 +            pthread_cond_wait(&c->task_fifo_cond, &c->task_fifo_mutex);
 +        }
 +        av_fifo_generic_read(c->task_fifo, &task, sizeof(task), NULL);
 +        pthread_mutex_unlock(&c->task_fifo_mutex);
 +        frame = task.indata;
 +
 +        ret = avcodec_encode_video2(avctx, pkt, frame, &got_packet);
 +        pthread_mutex_lock(&c->buffer_mutex);
 +        av_frame_unref(frame);
 +        pthread_mutex_unlock(&c->buffer_mutex);
 +        av_frame_free(&frame);
 +        if(got_packet) {
 +            av_dup_packet(pkt);
 +        } else {
 +            pkt->data = NULL;
 +            pkt->size = 0;
 +        }
 +        pthread_mutex_lock(&c->finished_task_mutex);
 +        c->finished_tasks[task.index].outdata = pkt; pkt = NULL;
 +        c->finished_tasks[task.index].return_code = ret;
 +        pthread_cond_signal(&c->finished_task_cond);
 +        pthread_mutex_unlock(&c->finished_task_mutex);
 +    }
 +end:
 +    av_free(pkt);
 +    pthread_mutex_lock(&c->buffer_mutex);
 +    avcodec_close(avctx);
 +    pthread_mutex_unlock(&c->buffer_mutex);
 +    av_freep(&avctx);
 +    return NULL;
 +}
 +
 +int ff_frame_thread_encoder_init(AVCodecContext *avctx, AVDictionary *options){
 +    int i=0;
 +    ThreadContext *c;
 +
 +
 +    if(   !(avctx->thread_type & FF_THREAD_FRAME)
 +       || !(avctx->codec->capabilities & CODEC_CAP_INTRA_ONLY))
 +        return 0;
 +
 +    if(!avctx->thread_count) {
 +        avctx->thread_count = ff_get_logical_cpus(avctx);
 +        avctx->thread_count = FFMIN(avctx->thread_count, MAX_THREADS);
 +    }
 +
 +    if(avctx->thread_count <= 1)
 +        return 0;
 +
 +    if(avctx->thread_count > MAX_THREADS)
 +        return AVERROR(EINVAL);
 +
 +    av_assert0(!avctx->internal->frame_thread_encoder);
 +    c = avctx->internal->frame_thread_encoder = av_mallocz(sizeof(ThreadContext));
 +    if(!c)
 +        return AVERROR(ENOMEM);
 +
 +    c->parent_avctx = avctx;
 +
 +    c->task_fifo = av_fifo_alloc(sizeof(Task) * BUFFER_SIZE);
 +    if(!c->task_fifo)
 +        goto fail;
 +
 +    pthread_mutex_init(&c->task_fifo_mutex, NULL);
 +    pthread_mutex_init(&c->finished_task_mutex, NULL);
 +    pthread_mutex_init(&c->buffer_mutex, NULL);
 +    pthread_cond_init(&c->task_fifo_cond, NULL);
 +    pthread_cond_init(&c->finished_task_cond, NULL);
 +
 +    for(i=0; i<avctx->thread_count ; i++){
 +        AVDictionary *tmp = NULL;
 +        void *tmpv;
 +        AVCodecContext *thread_avctx = avcodec_alloc_context3(avctx->codec);
 +        if(!thread_avctx)
 +            goto fail;
 +        tmpv = thread_avctx->priv_data;
 +        *thread_avctx = *avctx;
 +        thread_avctx->priv_data = tmpv;
 +        thread_avctx->internal = NULL;
 +        memcpy(thread_avctx->priv_data, avctx->priv_data, avctx->codec->priv_data_size);
 +        thread_avctx->thread_count = 1;
 +        thread_avctx->active_thread_type &= ~FF_THREAD_FRAME;
 +
 +        av_dict_copy(&tmp, options, 0);
 +        av_dict_set(&tmp, "threads", "1", 0);
 +        if(avcodec_open2(thread_avctx, avctx->codec, &tmp) < 0) {
 +            av_dict_free(&tmp);
 +            goto fail;
 +        }
 +        av_dict_free(&tmp);
 +        av_assert0(!thread_avctx->internal->frame_thread_encoder);
 +        thread_avctx->internal->frame_thread_encoder = c;
 +        if(pthread_create(&c->worker[i], NULL, worker, thread_avctx)) {
 +            goto fail;
 +        }
 +    }
 +
 +    avctx->active_thread_type = FF_THREAD_FRAME;
 +
 +    return 0;
 +fail:
 +    avctx->thread_count = i;
 +    av_log(avctx, AV_LOG_ERROR, "ff_frame_thread_encoder_init failed\n");
 +    ff_frame_thread_encoder_free(avctx);
 +    return -1;
 +}
 +
 +void ff_frame_thread_encoder_free(AVCodecContext *avctx){
 +    int i;
 +    ThreadContext *c= avctx->internal->frame_thread_encoder;
 +
 +    pthread_mutex_lock(&c->task_fifo_mutex);
 +    c->exit = 1;
 +    pthread_cond_broadcast(&c->task_fifo_cond);
 +    pthread_mutex_unlock(&c->task_fifo_mutex);
 +
 +    for (i=0; i<avctx->thread_count; i++) {
 +         pthread_join(c->worker[i], NULL);
 +    }
 +
 +    pthread_mutex_destroy(&c->task_fifo_mutex);
 +    pthread_mutex_destroy(&c->finished_task_mutex);
 +    pthread_mutex_destroy(&c->buffer_mutex);
 +    pthread_cond_destroy(&c->task_fifo_cond);
 +    pthread_cond_destroy(&c->finished_task_cond);
 +    av_fifo_free(c->task_fifo); c->task_fifo = NULL;
 +    av_freep(&avctx->internal->frame_thread_encoder);
 +}
 +
 +int ff_thread_video_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet_ptr){
 +    ThreadContext *c = avctx->internal->frame_thread_encoder;
 +    Task task;
 +    int ret;
 +
 +    av_assert1(!*got_packet_ptr);
 +
 +    if(frame){
 +        if(!(avctx->flags & CODEC_FLAG_INPUT_PRESERVED)){
 +            AVFrame *new = av_frame_alloc();
 +            if(!new)
 +                return AVERROR(ENOMEM);
 +            pthread_mutex_lock(&c->buffer_mutex);
 +            ret = ff_get_buffer(c->parent_avctx, new, 0);
 +            pthread_mutex_unlock(&c->buffer_mutex);
 +            if(ret<0)
 +                return ret;
 +            new->pts = frame->pts;
 +            new->quality = frame->quality;
 +            new->pict_type = frame->pict_type;
 +            av_image_copy(new->data, new->linesize, (const uint8_t **)frame->data, frame->linesize,
 +                          avctx->pix_fmt, avctx->width, avctx->height);
 +            frame = new;
 +        }
 +
 +        task.index = c->task_index;
 +        task.indata = (void*)frame;
 +        pthread_mutex_lock(&c->task_fifo_mutex);
 +        av_fifo_generic_write(c->task_fifo, &task, sizeof(task), NULL);
 +        pthread_cond_signal(&c->task_fifo_cond);
 +        pthread_mutex_unlock(&c->task_fifo_mutex);
 +
 +        c->task_index = (c->task_index+1) % BUFFER_SIZE;
 +
 +        if(!c->finished_tasks[c->finished_task_index].outdata && (c->task_index - c->finished_task_index) % BUFFER_SIZE <= avctx->thread_count)
 +            return 0;
 +    }
 +
 +    if(c->task_index == c->finished_task_index)
 +        return 0;
 +
 +    pthread_mutex_lock(&c->finished_task_mutex);
 +    while (!c->finished_tasks[c->finished_task_index].outdata) {
 +        pthread_cond_wait(&c->finished_task_cond, &c->finished_task_mutex);
 +    }
 +    task = c->finished_tasks[c->finished_task_index];
 +    *pkt = *(AVPacket*)(task.outdata);
 +    if(pkt->data)
 +        *got_packet_ptr = 1;
 +    av_freep(&c->finished_tasks[c->finished_task_index].outdata);
 +    c->finished_task_index = (c->finished_task_index+1) % BUFFER_SIZE;
 +    pthread_mutex_unlock(&c->finished_task_mutex);
 +
 +    return task.return_code;
 +}
@@@ -61,9 -58,7 +61,9 @@@
  #if HAVE_PTHREADS
  #include <pthread.h>
  #elif HAVE_W32THREADS
- #include "w32pthreads.h"
+ #include "compat/w32pthreads.h"
 +#elif HAVE_OS2THREADS
 +#include "os2threads.h"
  #endif
  
  typedef int (action_func)(AVCodecContext *c, void *arg);
@@@ -36,9 -36,7 +36,9 @@@
  #if HAVE_PTHREADS
  #include <pthread.h>
  #elif HAVE_W32THREADS
- #include "w32pthreads.h"
+ #include "compat/w32pthreads.h"
 +#elif HAVE_OS2THREADS
 +#include "os2threads.h"
  #endif
  
  #define VP8_MAX_QUANT 127
  #if HAVE_THREADS
  #if HAVE_PTHREADS
  #include <pthread.h>
 +#elif HAVE_OS2THREADS
 +#include "libavcodec/os2threads.h"
  #else
- #include "libavcodec/w32pthreads.h"
+ #include "compat/w32pthreads.h"
  #endif
  #endif