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: 2017-12-14 01:15:32 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             : #if HAVE_W32THREADS
     136             :     w32thread_init();
     137             : #endif
     138             : 
     139             :     // We cannot do this in the encoder init as the threads are created before
     140          24 :     if (av_codec_is_encoder(avctx->codec) &&
     141          12 :         avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO &&
     142           0 :         avctx->height > 2800)
     143           0 :         thread_count = avctx->thread_count = 1;
     144             : 
     145          12 :     if (!thread_count) {
     146           0 :         int nb_cpus = av_cpu_count();
     147           0 :         if  (avctx->height)
     148           0 :             nb_cpus = FFMIN(nb_cpus, (avctx->height+15)/16);
     149             :         // use number of cores + 1 as thread count if there is more than one
     150           0 :         if (nb_cpus > 1)
     151           0 :             thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS);
     152             :         else
     153           0 :             thread_count = avctx->thread_count = 1;
     154             :     }
     155             : 
     156          12 :     if (thread_count <= 1) {
     157           0 :         avctx->active_thread_type = 0;
     158           0 :         return 0;
     159             :     }
     160             : 
     161          12 :     avctx->internal->thread_ctx = c = av_mallocz(sizeof(*c));
     162          12 :     mainfunc = avctx->codec->caps_internal & FF_CODEC_CAP_SLICE_THREAD_HAS_MF ? &main_function : NULL;
     163          12 :     if (!c || (thread_count = avpriv_slicethread_create(&c->thread, avctx, worker_func, mainfunc, thread_count)) <= 1) {
     164           0 :         if (c)
     165           0 :             avpriv_slicethread_free(&c->thread);
     166           0 :         av_freep(&avctx->internal->thread_ctx);
     167           0 :         avctx->thread_count = 1;
     168           0 :         avctx->active_thread_type = 0;
     169           0 :         return 0;
     170             :     }
     171          12 :     avctx->thread_count = thread_count;
     172             : 
     173          12 :     avctx->execute = thread_execute;
     174          12 :     avctx->execute2 = thread_execute2;
     175          12 :     return 0;
     176             : }
     177             : 
     178           0 : void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n)
     179             : {
     180           0 :     SliceThreadContext *p = avctx->internal->thread_ctx;
     181           0 :     int *entries = p->entries;
     182             : 
     183           0 :     pthread_mutex_lock(&p->progress_mutex[thread]);
     184           0 :     entries[field] +=n;
     185           0 :     pthread_cond_signal(&p->progress_cond[thread]);
     186           0 :     pthread_mutex_unlock(&p->progress_mutex[thread]);
     187           0 : }
     188             : 
     189           0 : void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int shift)
     190             : {
     191           0 :     SliceThreadContext *p  = avctx->internal->thread_ctx;
     192           0 :     int *entries      = p->entries;
     193             : 
     194           0 :     if (!entries || !field) return;
     195             : 
     196           0 :     thread = thread ? thread - 1 : p->thread_count - 1;
     197             : 
     198           0 :     pthread_mutex_lock(&p->progress_mutex[thread]);
     199           0 :     while ((entries[field - 1] - entries[field]) < shift){
     200           0 :         pthread_cond_wait(&p->progress_cond[thread], &p->progress_mutex[thread]);
     201             :     }
     202           0 :     pthread_mutex_unlock(&p->progress_mutex[thread]);
     203             : }
     204             : 
     205           0 : int ff_alloc_entries(AVCodecContext *avctx, int count)
     206             : {
     207             :     int i;
     208             : 
     209           0 :     if (avctx->active_thread_type & FF_THREAD_SLICE)  {
     210           0 :         SliceThreadContext *p = avctx->internal->thread_ctx;
     211             : 
     212           0 :         if (p->entries) {
     213           0 :             av_assert0(p->thread_count == avctx->thread_count);
     214           0 :             av_freep(&p->entries);
     215             :         }
     216             : 
     217           0 :         p->thread_count  = avctx->thread_count;
     218           0 :         p->entries       = av_mallocz_array(count, sizeof(int));
     219             : 
     220           0 :         if (!p->progress_mutex) {
     221           0 :             p->progress_mutex = av_malloc_array(p->thread_count, sizeof(pthread_mutex_t));
     222           0 :             p->progress_cond  = av_malloc_array(p->thread_count, sizeof(pthread_cond_t));
     223             :         }
     224             : 
     225           0 :         if (!p->entries || !p->progress_mutex || !p->progress_cond) {
     226           0 :             av_freep(&p->entries);
     227           0 :             av_freep(&p->progress_mutex);
     228           0 :             av_freep(&p->progress_cond);
     229           0 :             return AVERROR(ENOMEM);
     230             :         }
     231           0 :         p->entries_count  = count;
     232             : 
     233           0 :         for (i = 0; i < p->thread_count; i++) {
     234           0 :             pthread_mutex_init(&p->progress_mutex[i], NULL);
     235           0 :             pthread_cond_init(&p->progress_cond[i], NULL);
     236             :         }
     237             :     }
     238             : 
     239           0 :     return 0;
     240             : }
     241             : 
     242           0 : void ff_reset_entries(AVCodecContext *avctx)
     243             : {
     244           0 :     SliceThreadContext *p = avctx->internal->thread_ctx;
     245           0 :     memset(p->entries, 0, p->entries_count * sizeof(int));
     246           0 : }

Generated by: LCOV version 1.13