Browse code

Add an execute2 function that is more flexible and allows to use parallel 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/trunk

Reimar Döffinger authored on 2009/10/12 20:35:35
Showing 4 changed files
... ...
@@ -30,7 +30,7 @@
30 30
 #include "libavutil/avutil.h"
31 31
 
32 32
 #define LIBAVCODEC_VERSION_MAJOR 52
33
-#define LIBAVCODEC_VERSION_MINOR 36
33
+#define LIBAVCODEC_VERSION_MINOR 37
34 34
 #define LIBAVCODEC_VERSION_MICRO  0
35 35
 
36 36
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
... ...
@@ -2526,6 +2526,26 @@ typedef struct AVCodecContext {
2526 2526
      * - decoding: Set by libavcodec
2527 2527
      */
2528 2528
     enum AVChromaLocation chroma_sample_location;
2529
+
2530
+    /**
2531
+     * The codec may call this to execute several independent things.
2532
+     * It will return only after finishing all tasks.
2533
+     * The user may replace this with some multithreaded implementation,
2534
+     * the default implementation will execute the parts serially.
2535
+     * Also see avcodec_thread_init and e.g. the --enable-pthread configure option.
2536
+     * @param c context passed also to func
2537
+     * @param count the number of things to execute
2538
+     * @param arg2 argument passed unchanged to func
2539
+     * @param ret return values of executed functions, must have space for "count" values. May be NULL.
2540
+     * @param func function that will be called count times, with jobnr from 0 to count-1.
2541
+     *             threadnr will be in the range 0 to c->thread_count-1 < MAX_THREADS and so that no
2542
+     *             two instances of func executing at the same time will have the same threadnr.
2543
+     * @return always 0 currently, but code should handle a future improvement where when any call to func
2544
+     *         returns < 0 no further calls to func may be done and < 0 is returned.
2545
+     * - encoding: Set by libavcodec, user can override.
2546
+     * - decoding: Set by libavcodec, user can override.
2547
+     */
2548
+    int (*execute2)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count);
2529 2549
 } AVCodecContext;
2530 2550
 
2531 2551
 /**
... ...
@@ -3154,6 +3174,7 @@ int avcodec_thread_init(AVCodecContext *s, int thread_count);
3154 3154
 void avcodec_thread_free(AVCodecContext *s);
3155 3155
 int avcodec_thread_execute(AVCodecContext *s, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size);
3156 3156
 int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size);
3157
+int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int, int),void *arg, int *ret, int count);
3157 3158
 //FIXME func typedef
3158 3159
 
3159 3160
 /**
... ...
@@ -433,6 +433,7 @@ void avcodec_get_context_defaults2(AVCodecContext *s, enum CodecType codec_type)
433 433
     s->release_buffer= avcodec_default_release_buffer;
434 434
     s->get_format= avcodec_default_get_format;
435 435
     s->execute= avcodec_default_execute;
436
+    s->execute2= avcodec_default_execute2;
436 437
     s->sample_aspect_ratio= (AVRational){0,1};
437 438
     s->pix_fmt= PIX_FMT_NONE;
438 439
     s->sample_fmt= SAMPLE_FMT_S16; // FIXME: set to NONE
... ...
@@ -26,10 +26,12 @@
26 26
 #include "avcodec.h"
27 27
 
28 28
 typedef int (action_func)(AVCodecContext *c, void *arg);
29
+typedef int (action_func2)(AVCodecContext *c, void *arg, int jobnr, int threadnr);
29 30
 
30 31
 typedef struct ThreadContext {
31 32
     pthread_t *workers;
32 33
     action_func *func;
34
+    action_func2 *func2;
33 35
     void *args;
34 36
     int *rets;
35 37
     int rets_count;
... ...
@@ -68,7 +70,8 @@ static void* attribute_align_arg worker(void *v)
68 68
         }
69 69
         pthread_mutex_unlock(&c->current_job_lock);
70 70
 
71
-        c->rets[our_job%c->rets_count] = c->func(avctx, (char*)c->args + our_job*c->job_size);
71
+        c->rets[our_job%c->rets_count] = c->func ? c->func(avctx, (char*)c->args + our_job*c->job_size):
72
+                                                   c->func2(avctx, c->args, our_job, self_id);
72 73
 
73 74
         pthread_mutex_lock(&c->current_job_lock);
74 75
         our_job = c->current_job++;
... ...
@@ -130,6 +133,13 @@ int avcodec_thread_execute(AVCodecContext *avctx, action_func* func, void *arg,
130 130
     return 0;
131 131
 }
132 132
 
133
+int avcodec_thread_execute2(AVCodecContext *avctx, action_func2* func2, void *arg, int *ret, int job_count)
134
+{
135
+    ThreadContext *c= avctx->thread_opaque;
136
+    c->func2 = func2;
137
+    return avcodec_thread_execute(avctx, NULL, arg, ret, job_count, 0);
138
+}
139
+
133 140
 int avcodec_thread_init(AVCodecContext *avctx, int thread_count)
134 141
 {
135 142
     int i;
... ...
@@ -167,5 +177,6 @@ int avcodec_thread_init(AVCodecContext *avctx, int thread_count)
167 167
     avcodec_thread_park_workers(c, thread_count);
168 168
 
169 169
     avctx->execute = avcodec_thread_execute;
170
+    avctx->execute2 = avcodec_thread_execute2;
170 171
     return 0;
171 172
 }
... ...
@@ -414,6 +414,16 @@ int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, v
414 414
     return 0;
415 415
 }
416 416
 
417
+int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int jobnr, int threadnr),void *arg, int *ret, int count){
418
+    int i;
419
+
420
+    for(i=0; i<count; i++){
421
+        int r= func(c, arg, i, 0);
422
+        if(ret) ret[i]= r;
423
+    }
424
+    return 0;
425
+}
426
+
417 427
 enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum PixelFormat *fmt){
418 428
     while (*fmt != PIX_FMT_NONE && ff_is_hwaccel_pix_fmt(*fmt))
419 429
         ++fmt;