• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/beosthread.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2004 François Revol <revol@free.fr>
00003  *
00004  * This file is part of FFmpeg.
00005  *
00006  * FFmpeg is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * FFmpeg is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with FFmpeg; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 //#define DEBUG
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 // it's odd Be never patented that :D
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 //printf("thread_func %X enter wait\n", (int)v); fflush(stdout);
00061         acquire_sem(c->work_sem);
00062 //printf("thread_func %X after wait (func=%X)\n", (int)v, (int)c->func); fflush(stdout);
00063         if(c->func)
00064             c->ret= c->func(c->avctx, c->arg);
00065         else
00066             return 0;
00067 //printf("thread_func %X signal complete\n", (int)v); fflush(stdout);
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 static 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     /* note, we can be certain that this is not called with the same AVCodecContext by different threads at the same time */
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     if (thread_count <= 1)
00127         return 0;
00128 
00129     assert(!s->thread_opaque);
00130     c= av_mallocz(sizeof(ThreadContext)*thread_count);
00131     s->thread_opaque= c;
00132 
00133     for(i=0; i<thread_count; i++){
00134 //printf("init semaphors %d\n", i); fflush(stdout);
00135         c[i].avctx= s;
00136 
00137         if((c[i].work_sem = create_sem(0, "ff work sem")) < B_OK)
00138             goto fail;
00139         if((c[i].done_sem = create_sem(0, "ff done sem")) < B_OK)
00140             goto fail;
00141 
00142 //printf("create thread %d\n", i); fflush(stdout);
00143         c[i].thread = spawn_thread(ff_thread_func, "libavcodec thread", B_LOW_PRIORITY, &c[i] );
00144         if( c[i].thread < B_OK ) goto fail;
00145         resume_thread(c[i].thread );
00146     }
00147 //printf("init done\n"); fflush(stdout);
00148 
00149     s->execute= avcodec_thread_execute;
00150 
00151     return 0;
00152 fail:
00153     avcodec_thread_free(s);
00154     return -1;
00155 }
00156 
00157 /* provide a mean to serialize calls to avcodec_*() for thread safety. */
00158 
00159 int avcodec_thread_lock_lib(void)
00160 {
00161         return lock_ben(&av_thread_lib_ben);
00162 }
00163 
00164 int avcodec_thread_unlock_lib(void)
00165 {
00166         return unlock_ben(&av_thread_lib_ben);
00167 }
00168 
00169 /* our versions of _init and _fini (which are called by those actually from crt.o) */
00170 
00171 void initialize_after(void)
00172 {
00173         av_thread_lib_ben.atom = 0;
00174         av_thread_lib_ben.sem = create_sem(0, "libavcodec benaphore");
00175 }
00176 
00177 void uninitialize_before(void)
00178 {
00179         delete_sem(av_thread_lib_ben.sem);
00180 }
00181 
00182 
00183 

Generated on Fri Sep 16 2011 17:17:34 for FFmpeg by  doxygen 1.7.1