processing with jobs > threads without wasting too much memory. It also avoids needing a separate int array when the only additional data the jobs needs is a single int running from 0 to count-1. Originally committed as revision 20210 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.6
| @@ -30,7 +30,7 @@ | |||||
| #include "libavutil/avutil.h" | #include "libavutil/avutil.h" | ||||
| #define LIBAVCODEC_VERSION_MAJOR 52 | #define LIBAVCODEC_VERSION_MAJOR 52 | ||||
| #define LIBAVCODEC_VERSION_MINOR 36 | |||||
| #define LIBAVCODEC_VERSION_MINOR 37 | |||||
| #define LIBAVCODEC_VERSION_MICRO 0 | #define LIBAVCODEC_VERSION_MICRO 0 | ||||
| #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | ||||
| @@ -2526,6 +2526,26 @@ typedef struct AVCodecContext { | |||||
| * - decoding: Set by libavcodec | * - decoding: Set by libavcodec | ||||
| */ | */ | ||||
| enum AVChromaLocation chroma_sample_location; | enum AVChromaLocation chroma_sample_location; | ||||
| /** | |||||
| * The codec may call this to execute several independent things. | |||||
| * It will return only after finishing all tasks. | |||||
| * The user may replace this with some multithreaded implementation, | |||||
| * the default implementation will execute the parts serially. | |||||
| * Also see avcodec_thread_init and e.g. the --enable-pthread configure option. | |||||
| * @param c context passed also to func | |||||
| * @param count the number of things to execute | |||||
| * @param arg2 argument passed unchanged to func | |||||
| * @param ret return values of executed functions, must have space for "count" values. May be NULL. | |||||
| * @param func function that will be called count times, with jobnr from 0 to count-1. | |||||
| * threadnr will be in the range 0 to c->thread_count-1 < MAX_THREADS and so that no | |||||
| * two instances of func executing at the same time will have the same threadnr. | |||||
| * @return always 0 currently, but code should handle a future improvement where when any call to func | |||||
| * returns < 0 no further calls to func may be done and < 0 is returned. | |||||
| * - encoding: Set by libavcodec, user can override. | |||||
| * - decoding: Set by libavcodec, user can override. | |||||
| */ | |||||
| int (*execute2)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count); | |||||
| } AVCodecContext; | } AVCodecContext; | ||||
| /** | /** | ||||
| @@ -3154,6 +3174,7 @@ int avcodec_thread_init(AVCodecContext *s, int thread_count); | |||||
| void avcodec_thread_free(AVCodecContext *s); | void avcodec_thread_free(AVCodecContext *s); | ||||
| int avcodec_thread_execute(AVCodecContext *s, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size); | int avcodec_thread_execute(AVCodecContext *s, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size); | ||||
| int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size); | int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size); | ||||
| int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int, int),void *arg, int *ret, int count); | |||||
| //FIXME func typedef | //FIXME func typedef | ||||
| /** | /** | ||||
| @@ -433,6 +433,7 @@ void avcodec_get_context_defaults2(AVCodecContext *s, enum CodecType codec_type) | |||||
| s->release_buffer= avcodec_default_release_buffer; | s->release_buffer= avcodec_default_release_buffer; | ||||
| s->get_format= avcodec_default_get_format; | s->get_format= avcodec_default_get_format; | ||||
| s->execute= avcodec_default_execute; | s->execute= avcodec_default_execute; | ||||
| s->execute2= avcodec_default_execute2; | |||||
| s->sample_aspect_ratio= (AVRational){0,1}; | s->sample_aspect_ratio= (AVRational){0,1}; | ||||
| s->pix_fmt= PIX_FMT_NONE; | s->pix_fmt= PIX_FMT_NONE; | ||||
| s->sample_fmt= SAMPLE_FMT_S16; // FIXME: set to NONE | s->sample_fmt= SAMPLE_FMT_S16; // FIXME: set to NONE | ||||
| @@ -26,10 +26,12 @@ | |||||
| #include "avcodec.h" | #include "avcodec.h" | ||||
| typedef int (action_func)(AVCodecContext *c, void *arg); | typedef int (action_func)(AVCodecContext *c, void *arg); | ||||
| typedef int (action_func2)(AVCodecContext *c, void *arg, int jobnr, int threadnr); | |||||
| typedef struct ThreadContext { | typedef struct ThreadContext { | ||||
| pthread_t *workers; | pthread_t *workers; | ||||
| action_func *func; | action_func *func; | ||||
| action_func2 *func2; | |||||
| void *args; | void *args; | ||||
| int *rets; | int *rets; | ||||
| int rets_count; | int rets_count; | ||||
| @@ -68,7 +70,8 @@ static void* attribute_align_arg worker(void *v) | |||||
| } | } | ||||
| pthread_mutex_unlock(&c->current_job_lock); | pthread_mutex_unlock(&c->current_job_lock); | ||||
| c->rets[our_job%c->rets_count] = c->func(avctx, (char*)c->args + our_job*c->job_size); | |||||
| c->rets[our_job%c->rets_count] = c->func ? c->func(avctx, (char*)c->args + our_job*c->job_size): | |||||
| c->func2(avctx, c->args, our_job, self_id); | |||||
| pthread_mutex_lock(&c->current_job_lock); | pthread_mutex_lock(&c->current_job_lock); | ||||
| our_job = c->current_job++; | our_job = c->current_job++; | ||||
| @@ -130,6 +133,13 @@ int avcodec_thread_execute(AVCodecContext *avctx, action_func* func, void *arg, | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int avcodec_thread_execute2(AVCodecContext *avctx, action_func2* func2, void *arg, int *ret, int job_count) | |||||
| { | |||||
| ThreadContext *c= avctx->thread_opaque; | |||||
| c->func2 = func2; | |||||
| return avcodec_thread_execute(avctx, NULL, arg, ret, job_count, 0); | |||||
| } | |||||
| int avcodec_thread_init(AVCodecContext *avctx, int thread_count) | int avcodec_thread_init(AVCodecContext *avctx, int thread_count) | ||||
| { | { | ||||
| int i; | int i; | ||||
| @@ -167,5 +177,6 @@ int avcodec_thread_init(AVCodecContext *avctx, int thread_count) | |||||
| avcodec_thread_park_workers(c, thread_count); | avcodec_thread_park_workers(c, thread_count); | ||||
| avctx->execute = avcodec_thread_execute; | avctx->execute = avcodec_thread_execute; | ||||
| avctx->execute2 = avcodec_thread_execute2; | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -414,6 +414,16 @@ int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, v | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int jobnr, int threadnr),void *arg, int *ret, int count){ | |||||
| int i; | |||||
| for(i=0; i<count; i++){ | |||||
| int r= func(c, arg, i, 0); | |||||
| if(ret) ret[i]= r; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum PixelFormat *fmt){ | enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum PixelFormat *fmt){ | ||||
| while (*fmt != PIX_FMT_NONE && ff_is_hwaccel_pix_fmt(*fmt)) | while (*fmt != PIX_FMT_NONE && ff_is_hwaccel_pix_fmt(*fmt)) | ||||
| ++fmt; | ++fmt; | ||||