GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavfilter/pthread.c Lines: 37 45 82.2 %
Date: 2020-08-14 10:39:37 Branches: 9 14 64.3 %

Line Branch Exec Source
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
 * Libavfilter multithreading support
22
 */
23
24
#include "config.h"
25
26
#include "libavutil/common.h"
27
#include "libavutil/cpu.h"
28
#include "libavutil/mem.h"
29
#include "libavutil/thread.h"
30
#include "libavutil/slicethread.h"
31
32
#include "avfilter.h"
33
#include "internal.h"
34
#include "thread.h"
35
36
typedef struct ThreadContext {
37
    AVFilterGraph *graph;
38
    AVSliceThread *thread;
39
    avfilter_action_func *func;
40
41
    /* per-execute parameters */
42
    AVFilterContext *ctx;
43
    void *arg;
44
    int   *rets;
45
} ThreadContext;
46
47
26246
static void worker_func(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads)
48
{
49
26246
    ThreadContext *c = priv;
50
26246
    int ret = c->func(c->ctx, c->arg, jobnr, nb_jobs);
51
26246
    if (c->rets)
52
        c->rets[jobnr] = ret;
53
26246
}
54
55
2609
static void slice_thread_uninit(ThreadContext *c)
56
{
57
2609
    avpriv_slicethread_free(&c->thread);
58
2609
}
59
60
3076
static int thread_execute(AVFilterContext *ctx, avfilter_action_func *func,
61
                          void *arg, int *ret, int nb_jobs)
62
{
63
3076
    ThreadContext *c = ctx->graph->internal->thread;
64
65
3076
    if (nb_jobs <= 0)
66
        return 0;
67
3076
    c->ctx         = ctx;
68
3076
    c->arg         = arg;
69
3076
    c->func        = func;
70
3076
    c->rets        = ret;
71
72
3076
    avpriv_slicethread_execute(c->thread, nb_jobs, 0);
73
3076
    return 0;
74
}
75
76
2609
static int thread_init_internal(ThreadContext *c, int nb_threads)
77
{
78
2609
    nb_threads = avpriv_slicethread_create(&c->thread, c, worker_func, NULL, nb_threads);
79
2609
    if (nb_threads <= 1)
80
        avpriv_slicethread_free(&c->thread);
81
2609
    return FFMAX(nb_threads, 1);
82
}
83
84
5989
int ff_graph_thread_init(AVFilterGraph *graph)
85
{
86
    int ret;
87
88
5989
    if (graph->nb_threads == 1) {
89
3380
        graph->thread_type = 0;
90
3380
        return 0;
91
    }
92
93
2609
    graph->internal->thread = av_mallocz(sizeof(ThreadContext));
94
2609
    if (!graph->internal->thread)
95
        return AVERROR(ENOMEM);
96
97
2609
    ret = thread_init_internal(graph->internal->thread, graph->nb_threads);
98
2609
    if (ret <= 1) {
99
        av_freep(&graph->internal->thread);
100
        graph->thread_type = 0;
101
        graph->nb_threads  = 1;
102
        return (ret < 0) ? ret : 0;
103
    }
104
2609
    graph->nb_threads = ret;
105
106
2609
    graph->internal->thread_execute = thread_execute;
107
108
2609
    return 0;
109
}
110
111
5989
void ff_graph_thread_free(AVFilterGraph *graph)
112
{
113
5989
    if (graph->internal->thread)
114
2609
        slice_thread_uninit(graph->internal->thread);
115
5989
    av_freep(&graph->internal->thread);
116
5989
}