00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "avcodec.h"
00023
00024 #define WIN32_LEAN_AND_MEAN
00025 #include <windows.h>
00026 #include <process.h>
00027
00028 typedef struct ThreadContext{
00029 AVCodecContext *avctx;
00030 HANDLE thread;
00031 HANDLE work_sem;
00032 HANDLE job_sem;
00033 HANDLE done_sem;
00034 int (*func)(AVCodecContext *c, void *arg);
00035 int (*func2)(AVCodecContext *c, void *arg, int, int);
00036 void *arg;
00037 int argsize;
00038 int *jobnr;
00039 int *ret;
00040 int threadnr;
00041 }ThreadContext;
00042
00043
00044 static unsigned WINAPI attribute_align_arg thread_func(void *v){
00045 ThreadContext *c= v;
00046
00047 for(;;){
00048 int ret, jobnr;
00049
00050 WaitForSingleObject(c->work_sem, INFINITE);
00051
00052 if (!c->func && !c->func2)
00053 break;
00054 WaitForSingleObject(c->job_sem, INFINITE);
00055 jobnr = (*c->jobnr)++;
00056 ReleaseSemaphore(c->job_sem, 1, 0);
00057
00058 if(c->func)
00059 ret= c->func(c->avctx, (uint8_t *)c->arg + jobnr*c->argsize);
00060 else
00061 ret= c->func2(c->avctx, c->arg, jobnr, c->threadnr);
00062 if (c->ret)
00063 c->ret[jobnr] = ret;
00064
00065 ReleaseSemaphore(c->done_sem, 1, 0);
00066 }
00067
00068 return 0;
00069 }
00070
00075 void avcodec_thread_free(AVCodecContext *s){
00076 ThreadContext *c= s->thread_opaque;
00077 int i;
00078
00079 for(i=0; i<s->thread_count; i++){
00080
00081 c[i].func= NULL;
00082 c[i].func2= NULL;
00083 }
00084 ReleaseSemaphore(c[0].work_sem, s->thread_count, 0);
00085 for(i=0; i<s->thread_count; i++){
00086 WaitForSingleObject(c[i].thread, INFINITE);
00087 if(c[i].thread) CloseHandle(c[i].thread);
00088 }
00089 if(c[0].work_sem) CloseHandle(c[0].work_sem);
00090 if(c[0].job_sem) CloseHandle(c[0].job_sem);
00091 if(c[0].done_sem) CloseHandle(c[0].done_sem);
00092
00093 av_freep(&s->thread_opaque);
00094 }
00095
00096 static int avcodec_thread_execute(AVCodecContext *s, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size){
00097 ThreadContext *c= s->thread_opaque;
00098 int i;
00099 int jobnr = 0;
00100
00101 assert(s == c->avctx);
00102
00103
00104
00105 for(i=0; i<s->thread_count; i++){
00106 c[i].arg= arg;
00107 c[i].argsize= size;
00108 c[i].func= func;
00109 c[i].ret= ret;
00110 c[i].jobnr = &jobnr;
00111 }
00112 ReleaseSemaphore(c[0].work_sem, count, 0);
00113 for(i=0; i<count; i++)
00114 WaitForSingleObject(c[0].done_sem, INFINITE);
00115
00116 return 0;
00117 }
00118
00119 static int avcodec_thread_execute2(AVCodecContext *s, int (*func)(AVCodecContext *c2, void *arg2, int, int),void *arg, int *ret, int count){
00120 ThreadContext *c= s->thread_opaque;
00121 int i;
00122 for(i=0; i<s->thread_count; i++)
00123 c[i].func2 = func;
00124 avcodec_thread_execute(s, NULL, arg, ret, count, 0);
00125 }
00126
00127 int avcodec_thread_init(AVCodecContext *s, int thread_count){
00128 int i;
00129 ThreadContext *c;
00130 uint32_t threadid;
00131
00132 s->thread_count= thread_count;
00133
00134 if (thread_count <= 1)
00135 return 0;
00136
00137 assert(!s->thread_opaque);
00138 c= av_mallocz(sizeof(ThreadContext)*thread_count);
00139 s->thread_opaque= c;
00140 if(!(c[0].work_sem = CreateSemaphore(NULL, 0, INT_MAX, NULL)))
00141 goto fail;
00142 if(!(c[0].job_sem = CreateSemaphore(NULL, 1, 1, NULL)))
00143 goto fail;
00144 if(!(c[0].done_sem = CreateSemaphore(NULL, 0, INT_MAX, NULL)))
00145 goto fail;
00146
00147 for(i=0; i<thread_count; i++){
00148
00149 c[i].avctx= s;
00150 c[i].work_sem = c[0].work_sem;
00151 c[i].job_sem = c[0].job_sem;
00152 c[i].done_sem = c[0].done_sem;
00153 c[i].threadnr = i;
00154
00155
00156 c[i].thread = (HANDLE)_beginthreadex(NULL, 0, thread_func, &c[i], 0, &threadid );
00157 if( !c[i].thread ) goto fail;
00158 }
00159
00160
00161 s->execute= avcodec_thread_execute;
00162 s->execute2= avcodec_thread_execute2;
00163
00164 return 0;
00165 fail:
00166 avcodec_thread_free(s);
00167 return -1;
00168 }