tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pthread_slice.c (5000B)


      1 /*
      2 * This file is part of FFmpeg.
      3 *
      4 * FFmpeg is free software; you can redistribute it and/or
      5 * modify it under the terms of the GNU Lesser General Public
      6 * License as published by the Free Software Foundation; either
      7 * version 2.1 of the License, or (at your option) any later version.
      8 *
      9 * FFmpeg is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12 * Lesser General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU Lesser General Public
     15 * License along with FFmpeg; if not, write to the Free Software
     16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     17 */
     18 
     19 /**
     20 * @file
     21 * Slice multithreading support functions
     22 * @see doc/multithreading.txt
     23 */
     24 
     25 #include "config.h"
     26 
     27 #include "avcodec.h"
     28 #include "codec_internal.h"
     29 #include "internal.h"
     30 #include "pthread_internal.h"
     31 #include "thread.h"
     32 
     33 #include "libavutil/avassert.h"
     34 #include "libavutil/common.h"
     35 #include "libavutil/cpu.h"
     36 #include "libavutil/mem.h"
     37 #include "libavutil/thread.h"
     38 #include "libavutil/slicethread.h"
     39 
     40 typedef int (action_func)(AVCodecContext *c, void *arg);
     41 typedef int (action_func2)(AVCodecContext *c, void *arg, int jobnr, int threadnr);
     42 typedef int (main_func)(AVCodecContext *c);
     43 
     44 typedef struct SliceThreadContext {
     45    AVSliceThread *thread;
     46    action_func *func;
     47    action_func2 *func2;
     48    main_func *mainfunc;
     49    void *args;
     50    int *rets;
     51    int job_size;
     52 } SliceThreadContext;
     53 
     54 static void main_function(void *priv) {
     55    AVCodecContext *avctx = priv;
     56    SliceThreadContext *c = avctx->internal->thread_ctx;
     57    c->mainfunc(avctx);
     58 }
     59 
     60 static void worker_func(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads)
     61 {
     62    AVCodecContext *avctx = priv;
     63    SliceThreadContext *c = avctx->internal->thread_ctx;
     64    int ret;
     65 
     66    ret = c->func ? c->func(avctx, (char *)c->args + c->job_size * jobnr)
     67                  : c->func2(avctx, c->args, jobnr, threadnr);
     68    if (c->rets)
     69        c->rets[jobnr] = ret;
     70 }
     71 
     72 void ff_slice_thread_free(AVCodecContext *avctx)
     73 {
     74    SliceThreadContext *c = avctx->internal->thread_ctx;
     75 
     76    avpriv_slicethread_free(&c->thread);
     77 
     78    av_freep(&avctx->internal->thread_ctx);
     79 }
     80 
     81 static int thread_execute(AVCodecContext *avctx, action_func* func, void *arg, int *ret, int job_count, int job_size)
     82 {
     83    SliceThreadContext *c = avctx->internal->thread_ctx;
     84 
     85    if (!(avctx->active_thread_type&FF_THREAD_SLICE) || avctx->thread_count <= 1)
     86        return avcodec_default_execute(avctx, func, arg, ret, job_count, job_size);
     87 
     88    if (job_count <= 0)
     89        return 0;
     90 
     91    c->job_size = job_size;
     92    c->args = arg;
     93    c->func = func;
     94    c->rets = ret;
     95 
     96    avpriv_slicethread_execute(c->thread, job_count, !!c->mainfunc  );
     97    return 0;
     98 }
     99 
    100 static int thread_execute2(AVCodecContext *avctx, action_func2* func2, void *arg, int *ret, int job_count)
    101 {
    102    SliceThreadContext *c = avctx->internal->thread_ctx;
    103    c->func2 = func2;
    104    return thread_execute(avctx, NULL, arg, ret, job_count, 0);
    105 }
    106 
    107 int ff_slice_thread_execute_with_mainfunc(AVCodecContext *avctx, action_func2* func2, main_func *mainfunc, void *arg, int *ret, int job_count)
    108 {
    109    SliceThreadContext *c = avctx->internal->thread_ctx;
    110    c->func2 = func2;
    111    c->mainfunc = mainfunc;
    112    return thread_execute(avctx, NULL, arg, ret, job_count, 0);
    113 }
    114 
    115 int ff_slice_thread_init(AVCodecContext *avctx)
    116 {
    117    SliceThreadContext *c;
    118    int thread_count = avctx->thread_count;
    119    void (*mainfunc)(void *);
    120 
    121    // We cannot do this in the encoder init as the threads are created before
    122    if (av_codec_is_encoder(avctx->codec) &&
    123        avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO &&
    124        avctx->height > 2800)
    125        thread_count = avctx->thread_count = 1;
    126 
    127    if (!thread_count) {
    128        int nb_cpus = av_cpu_count();
    129        if  (avctx->height)
    130            nb_cpus = FFMIN(nb_cpus, (avctx->height+15)/16);
    131        // use number of cores + 1 as thread count if there is more than one
    132        if (nb_cpus > 1)
    133            thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS);
    134        else
    135            thread_count = avctx->thread_count = 1;
    136    }
    137 
    138    if (thread_count <= 1) {
    139        avctx->active_thread_type = 0;
    140        return 0;
    141    }
    142 
    143    avctx->internal->thread_ctx = c = av_mallocz(sizeof(*c));
    144    mainfunc = ffcodec(avctx->codec)->caps_internal & FF_CODEC_CAP_SLICE_THREAD_HAS_MF ? &main_function : NULL;
    145    if (!c || (thread_count = avpriv_slicethread_create(&c->thread, avctx, worker_func, mainfunc, thread_count)) <= 1) {
    146        if (c)
    147            avpriv_slicethread_free(&c->thread);
    148        av_freep(&avctx->internal->thread_ctx);
    149        avctx->thread_count = 1;
    150        avctx->active_thread_type = 0;
    151        return 0;
    152    }
    153    avctx->thread_count = thread_count;
    154 
    155    avctx->execute = thread_execute;
    156    avctx->execute2 = thread_execute2;
    157    return 0;
    158 }