LCOV - code coverage report
Current view: top level - libavcodec - pthread_slice.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 39 116 33.6 %
Date: 2018-02-24 03:21:38 Functions: 4 11 36.4 %

          Line data    Source code
       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 "internal.h"
      29             : #include "pthread_internal.h"
      30             : #include "thread.h"
      31             : 
      32             : #include "libavutil/avassert.h"
      33             : #include "libavutil/common.h"
      34             : #include "libavutil/cpu.h"
      35             : #include "libavutil/mem.h"
      36             : #include "libavutil/thread.h"
      37             : #include "libavutil/slicethread.h"
      38             : 
      39             : typedef int (action_func)(AVCodecContext *c, void *arg);
      40             : typedef int (action_func2)(AVCodecContext *c, void *arg, int jobnr, int threadnr);
      41             : typedef int (main_func)(AVCodecContext *c);
      42             : 
      43             : typedef struct SliceThreadContext {
      44             :     AVSliceThread *thread;
      45             :     action_func *func;
      46             :     action_func2 *func2;
      47             :     main_func *mainfunc;
      48             :     void *args;
      49             :     int *rets;
      50             :     int job_size;
      51             : 
      52             :     int *entries;
      53             :     int entries_count;
      54             :     int thread_count;
      55             :     pthread_cond_t *progress_cond;
      56             :     pthread_mutex_t *progress_mutex;
      57             : } SliceThreadContext;
      58             : 
      59           0 : static void main_function(void *priv) {
      60           0 :     AVCodecContext *avctx = priv;
      61           0 :     SliceThreadContext *c = avctx->internal->thread_ctx;
      62           0 :     c->mainfunc(avctx);
      63           0 : }
      64             : 
      65        2324 : static void worker_func(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads)
      66             : {
      67        2324 :     AVCodecContext *avctx = priv;
      68        2324 :     SliceThreadContext *c = avctx->internal->thread_ctx;
      69             :     int ret;
      70             : 
      71        6972 :     ret = c->func ? c->func(avctx, (char *)c->args + c->job_size * jobnr)
      72        4648 :                   : c->func2(avctx, c->args, jobnr, threadnr);
      73        2324 :     if (c->rets)
      74           0 :         c->rets[jobnr] = ret;
      75        2324 : }
      76             : 
      77          12 : void ff_slice_thread_free(AVCodecContext *avctx)
      78             : {
      79          12 :     SliceThreadContext *c = avctx->internal->thread_ctx;
      80             :     int i;
      81             : 
      82          12 :     avpriv_slicethread_free(&c->thread);
      83             : 
      84          12 :     for (i = 0; i < c->thread_count; i++) {
      85           0 :         pthread_mutex_destroy(&c->progress_mutex[i]);
      86           0 :         pthread_cond_destroy(&c->progress_cond[i]);
      87             :     }
      88             : 
      89          12 :     av_freep(&c->entries);
      90          12 :     av_freep(&c->progress_mutex);
      91          12 :     av_freep(&c->progress_cond);
      92          12 :     av_freep(&avctx->internal->thread_ctx);
      93          12 : }
      94             : 
      95        1162 : static int thread_execute(AVCodecContext *avctx, action_func* func, void *arg, int *ret, int job_count, int job_size)
      96             : {
      97        1162 :     SliceThreadContext *c = avctx->internal->thread_ctx;
      98             : 
      99        1162 :     if (!(avctx->active_thread_type&FF_THREAD_SLICE) || avctx->thread_count <= 1)
     100           0 :         return avcodec_default_execute(avctx, func, arg, ret, job_count, job_size);
     101             : 
     102        1162 :     if (job_count <= 0)
     103           0 :         return 0;
     104             : 
     105        1162 :     c->job_size = job_size;
     106        1162 :     c->args = arg;
     107        1162 :     c->func = func;
     108        1162 :     c->rets = ret;
     109             : 
     110        1162 :     avpriv_slicethread_execute(c->thread, job_count, !!c->mainfunc  );
     111        1162 :     return 0;
     112             : }
     113             : 
     114           0 : static int thread_execute2(AVCodecContext *avctx, action_func2* func2, void *arg, int *ret, int job_count)
     115             : {
     116           0 :     SliceThreadContext *c = avctx->internal->thread_ctx;
     117           0 :     c->func2 = func2;
     118           0 :     return thread_execute(avctx, NULL, arg, ret, job_count, 0);
     119             : }
     120             : 
     121           0 : int ff_slice_thread_execute_with_mainfunc(AVCodecContext *avctx, action_func2* func2, main_func *mainfunc, void *arg, int *ret, int job_count)
     122             : {
     123           0 :     SliceThreadContext *c = avctx->internal->thread_ctx;
     124           0 :     c->func2 = func2;
     125           0 :     c->mainfunc = mainfunc;
     126           0 :     return thread_execute(avctx, NULL, arg, ret, job_count, 0);
     127             : }
     128             : 
     129          12 : int ff_slice_thread_init(AVCodecContext *avctx)
     130             : {
     131             :     SliceThreadContext *c;
     132          12 :     int thread_count = avctx->thread_count;
     133             :     static void (*mainfunc)(void *);
     134             : 
     135             :     // We cannot do this in the encoder init as the threads are created before
     136          24 :     if (av_codec_is_encoder(avctx->codec) &&
     137          12 :         avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO &&
     138           0 :         avctx->height > 2800)
     139           0 :         thread_count = avctx->thread_count = 1;
     140             : 
     141          12 :     if (!thread_count) {
     142           0 :         int nb_cpus = av_cpu_count();
     143           0 :         if  (avctx->height)
     144           0 :             nb_cpus = FFMIN(nb_cpus, (avctx->height+15)/16);
     145             :         // use number of cores + 1 as thread count if there is more than one
     146           0 :         if (nb_cpus > 1)
     147           0 :             thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS);
     148             :         else
     149           0 :             thread_count = avctx->thread_count = 1;
     150             :     }
     151             : 
     152          12 :     if (thread_count <= 1) {
     153           0 :         avctx->active_thread_type = 0;
     154           0 :         return 0;
     155             :     }
     156             : 
     157          12 :     avctx->internal->thread_ctx = c = av_mallocz(sizeof(*c));
     158          12 :     mainfunc = avctx->codec->caps_internal & FF_CODEC_CAP_SLICE_THREAD_HAS_MF ? &main_function : NULL;
     159          12 :     if (!c || (thread_count = avpriv_slicethread_create(&c->thread, avctx, worker_func, mainfunc, thread_count)) <= 1) {
     160           0 :         if (c)
     161           0 :             avpriv_slicethread_free(&c->thread);
     162           0 :         av_freep(&avctx->internal->thread_ctx);
     163           0 :         avctx->thread_count = 1;
     164           0 :         avctx->active_thread_type = 0;
     165           0 :         return 0;
     166             :     }
     167          12 :     avctx->thread_count = thread_count;
     168             : 
     169          12 :     avctx->execute = thread_execute;
     170          12 :     avctx->execute2 = thread_execute2;
     171          12 :     return 0;
     172             : }
     173             : 
     174           0 : void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n)
     175             : {
     176           0 :     SliceThreadContext *p = avctx->internal->thread_ctx;
     177           0 :     int *entries = p->entries;
     178             : 
     179           0 :     pthread_mutex_lock(&p->progress_mutex[thread]);
     180           0 :     entries[field] +=n;
     181           0 :     pthread_cond_signal(&p->progress_cond[thread]);
     182           0 :     pthread_mutex_unlock(&p->progress_mutex[thread]);
     183           0 : }
     184             : 
     185           0 : void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int shift)
     186             : {
     187           0 :     SliceThreadContext *p  = avctx->internal->thread_ctx;
     188           0 :     int *entries      = p->entries;
     189             : 
     190           0 :     if (!entries || !field) return;
     191             : 
     192           0 :     thread = thread ? thread - 1 : p->thread_count - 1;
     193             : 
     194           0 :     pthread_mutex_lock(&p->progress_mutex[thread]);
     195           0 :     while ((entries[field - 1] - entries[field]) < shift){
     196           0 :         pthread_cond_wait(&p->progress_cond[thread], &p->progress_mutex[thread]);
     197             :     }
     198           0 :     pthread_mutex_unlock(&p->progress_mutex[thread]);
     199             : }
     200             : 
     201           0 : int ff_alloc_entries(AVCodecContext *avctx, int count)
     202             : {
     203             :     int i;
     204             : 
     205           0 :     if (avctx->active_thread_type & FF_THREAD_SLICE)  {
     206           0 :         SliceThreadContext *p = avctx->internal->thread_ctx;
     207             : 
     208           0 :         if (p->entries) {
     209           0 :             av_assert0(p->thread_count == avctx->thread_count);
     210           0 :             av_freep(&p->entries);
     211             :         }
     212             : 
     213           0 :         p->thread_count  = avctx->thread_count;
     214           0 :         p->entries       = av_mallocz_array(count, sizeof(int));
     215             : 
     216           0 :         if (!p->progress_mutex) {
     217           0 :             p->progress_mutex = av_malloc_array(p->thread_count, sizeof(pthread_mutex_t));
     218           0 :             p->progress_cond  = av_malloc_array(p->thread_count, sizeof(pthread_cond_t));
     219             :         }
     220             : 
     221           0 :         if (!p->entries || !p->progress_mutex || !p->progress_cond) {
     222           0 :             av_freep(&p->entries);
     223           0 :             av_freep(&p->progress_mutex);
     224           0 :             av_freep(&p->progress_cond);
     225           0 :             return AVERROR(ENOMEM);
     226             :         }
     227           0 :         p->entries_count  = count;
     228             : 
     229           0 :         for (i = 0; i < p->thread_count; i++) {
     230           0 :             pthread_mutex_init(&p->progress_mutex[i], NULL);
     231           0 :             pthread_cond_init(&p->progress_cond[i], NULL);
     232             :         }
     233             :     }
     234             : 
     235           0 :     return 0;
     236             : }
     237             : 
     238           0 : void ff_reset_entries(AVCodecContext *avctx)
     239             : {
     240           0 :     SliceThreadContext *p = avctx->internal->thread_ctx;
     241           0 :     memset(p->entries, 0, p->entries_count * sizeof(int));
     242           0 : }

Generated by: LCOV version 1.13