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 #include <OS.h>
00025
00026 typedef struct ThreadContext{
00027 AVCodecContext *avctx;
00028 thread_id thread;
00029 sem_id work_sem;
00030 sem_id done_sem;
00031 int (*func)(AVCodecContext *c, void *arg);
00032 void *arg;
00033 int ret;
00034 }ThreadContext;
00035
00036
00037 struct benaphore {
00038 vint32 atom;
00039 sem_id sem;
00040 };
00041 static inline int lock_ben(struct benaphore *ben)
00042 {
00043 if (atomic_add(&ben->atom, 1) > 0)
00044 return acquire_sem(ben->sem);
00045 return B_OK;
00046 }
00047 static inline int unlock_ben(struct benaphore *ben)
00048 {
00049 if (atomic_add(&ben->atom, -1) > 1)
00050 return release_sem(ben->sem);
00051 return B_OK;
00052 }
00053
00054 static struct benaphore av_thread_lib_ben;
00055
00056 static int32 ff_thread_func(void *v){
00057 ThreadContext *c= v;
00058
00059 for(;;){
00060
00061 acquire_sem(c->work_sem);
00062
00063 if(c->func)
00064 c->ret= c->func(c->avctx, c->arg);
00065 else
00066 return 0;
00067
00068 release_sem(c->done_sem);
00069 }
00070
00071 return B_OK;
00072 }
00073
00078 void avcodec_thread_free(AVCodecContext *s){
00079 ThreadContext *c= s->thread_opaque;
00080 int i;
00081 int32 ret;
00082
00083 for(i=0; i<s->thread_count; i++){
00084
00085 c[i].func= NULL;
00086 release_sem(c[i].work_sem);
00087 wait_for_thread(c[i].thread, &ret);
00088 if(c[i].work_sem > B_OK) delete_sem(c[i].work_sem);
00089 if(c[i].done_sem > B_OK) delete_sem(c[i].done_sem);
00090 }
00091
00092 av_freep(&s->thread_opaque);
00093 }
00094
00095 int avcodec_thread_execute(AVCodecContext *s, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size){
00096 ThreadContext *c= s->thread_opaque;
00097 int i;
00098
00099 assert(s == c->avctx);
00100 assert(count <= s->thread_count);
00101
00102
00103
00104 for(i=0; i<count; i++){
00105 c[i].arg= (char*)arg + i*size;
00106 c[i].func= func;
00107 c[i].ret= 12345;
00108
00109 release_sem(c[i].work_sem);
00110 }
00111 for(i=0; i<count; i++){
00112 acquire_sem(c[i].done_sem);
00113
00114 c[i].func= NULL;
00115 if(ret) ret[i]= c[i].ret;
00116 }
00117 return 0;
00118 }
00119
00120 int avcodec_thread_init(AVCodecContext *s, int thread_count){
00121 int i;
00122 ThreadContext *c;
00123
00124 s->thread_count= thread_count;
00125
00126 assert(!s->thread_opaque);
00127 c= av_mallocz(sizeof(ThreadContext)*thread_count);
00128 s->thread_opaque= c;
00129
00130 for(i=0; i<thread_count; i++){
00131
00132 c[i].avctx= s;
00133
00134 if((c[i].work_sem = create_sem(0, "ff work sem")) < B_OK)
00135 goto fail;
00136 if((c[i].done_sem = create_sem(0, "ff done sem")) < B_OK)
00137 goto fail;
00138
00139
00140 c[i].thread = spawn_thread(ff_thread_func, "libavcodec thread", B_LOW_PRIORITY, &c[i] );
00141 if( c[i].thread < B_OK ) goto fail;
00142 resume_thread(c[i].thread );
00143 }
00144
00145
00146 s->execute= avcodec_thread_execute;
00147
00148 return 0;
00149 fail:
00150 avcodec_thread_free(s);
00151 return -1;
00152 }
00153
00154
00155
00156 int avcodec_thread_lock_lib(void)
00157 {
00158 return lock_ben(&av_thread_lib_ben);
00159 }
00160
00161 int avcodec_thread_unlock_lib(void)
00162 {
00163 return unlock_ben(&av_thread_lib_ben);
00164 }
00165
00166
00167
00168 void initialize_after(void)
00169 {
00170 av_thread_lib_ben.atom = 0;
00171 av_thread_lib_ben.sem = create_sem(0, "libavcodec benaphore");
00172 }
00173
00174 void uninitialize_before(void)
00175 {
00176 delete_sem(av_thread_lib_ben.sem);
00177 }
00178
00179
00180