Coverage Report

Created: 2026-10-28 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libswscale/ops_chain.c
Line
Count
Source
1
/**
2
 * Copyright (C) 2025 Niklas Haas
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * FFmpeg is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with FFmpeg; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
#include "libavutil/avassert.h"
22
#include "libavutil/mem.h"
23
24
#include "ops_chain.h"
25
26
SwsOpChain *ff_sws_op_chain_alloc(void)
27
0
{
28
0
    return av_mallocz(sizeof(SwsOpChain));
29
0
}
30
31
void ff_sws_op_chain_free_cb(void *ptr)
32
0
{
33
0
    if (!ptr)
34
0
        return;
35
36
0
    SwsOpChain *chain = ptr;
37
0
    for (int i = 0; i < chain->num_impl + 1; i++) {
38
0
        if (chain->free[i])
39
0
            chain->free[i](&chain->impl[i].priv);
40
0
    }
41
42
0
    av_free(chain);
43
0
}
44
45
int ff_sws_op_chain_append(SwsOpChain *chain, SwsFuncPtr func,
46
                           void (*free)(SwsOpPriv *), const SwsOpPriv *priv)
47
0
{
48
0
    const int idx = chain->num_impl;
49
0
    if (idx == SWS_MAX_OPS)
50
0
        return AVERROR(EINVAL);
51
52
0
    av_assert1(func);
53
0
    chain->impl[idx].cont = func;
54
0
    chain->impl[idx + 1].priv = *priv;
55
0
    chain->free[idx + 1] = free;
56
0
    chain->num_impl++;
57
0
    return 0;
58
0
}
59
60
int ff_sws_uop_lookup(SwsContext *ctx, const SwsUOpTable *const tables[],
61
                      int num_tables, const SwsUOp *uop, const int block_size,
62
                      SwsOpChain *chain)
63
0
{
64
0
    const unsigned cpu_flags = av_get_cpu_flags();
65
0
    const SwsUOpEntry *match = NULL;
66
0
    int ret;
67
68
0
    SwsImplParams params = {
69
0
        .ctx = ctx,
70
0
        .uop = uop
71
0
    };
72
73
0
    for (int n = 0; !match && n < num_tables; n++) {
74
0
        const SwsUOpTable *table = params.table = tables[n];
75
0
        if (table->block_size && table->block_size != block_size ||
76
0
            table->cpu_flags & ~cpu_flags)
77
0
            continue;
78
79
0
        for (int i = 0; table->entries[i]; i++) {
80
0
            const SwsUOpEntry *entry = table->entries[i];
81
0
            const SwsUOp entry_uop = {
82
0
                .uop  = entry->uop,
83
0
                .type = entry->type,
84
0
                .mask = entry->mask,
85
0
                .par  = entry->par,
86
0
            };
87
88
0
            if (ff_sws_uop_cmp(uop, &entry_uop) != 0)
89
0
                continue;
90
0
            if (entry->check && !entry->check(&params))
91
0
                continue;
92
93
0
            match = entry;
94
0
            break;
95
0
        }
96
0
    }
97
98
0
    if (!match) {
99
0
        char name[64];
100
0
        ff_sws_uop_name(uop, name);
101
0
        av_log(ctx, AV_LOG_DEBUG, "No implementation found for: %s\n", name);
102
0
        return AVERROR(ENOTSUP);
103
0
    }
104
105
0
    SwsImplResult res = {0};
106
0
    if (match->setup) {
107
0
        ret = match->setup(&params, &res);
108
0
        if (ret < 0)
109
0
            return ret;
110
0
    }
111
112
0
    ret = ff_sws_op_chain_append(chain, res.func ? res.func : match->func,
113
0
                                 res.free, &res.priv);
114
0
    if (ret < 0) {
115
0
        if (res.free)
116
0
            res.free(&res.priv);
117
0
        return ret;
118
0
    }
119
120
0
    for (int i = 0; i < 4; i++) {
121
0
        chain->over_read[i]  = FFMAX(chain->over_read[i],  res.over_read[i]);
122
0
        chain->over_write[i] = FFMAX(chain->over_write[i], res.over_write[i]);
123
0
    }
124
125
0
    chain->cpu_flags |= params.table->cpu_flags;
126
0
    return 0;
127
0
}
128
129
int ff_sws_setup_scalar(const SwsImplParams *params, SwsImplResult *out)
130
0
{
131
0
    const SwsUOp *uop = params->uop;
132
0
    const SwsPixel scalar = uop->data.scalar;
133
0
    switch (uop->type) {
134
0
    case SWS_PIXEL_U8:  out->priv.u8[0]  = scalar.u8;  break;
135
0
    case SWS_PIXEL_U16: out->priv.u16[0] = scalar.u16; break;
136
0
    case SWS_PIXEL_U32: out->priv.u32[0] = scalar.u32; break;
137
0
    case SWS_PIXEL_F32: out->priv.f32[0] = scalar.f32; break;
138
0
    default: return AVERROR(EINVAL);
139
0
    }
140
141
0
    return 0;
142
0
}
143
144
int ff_sws_setup_vec4(const SwsImplParams *params, SwsImplResult *out)
145
0
{
146
0
    const SwsUOp *uop = params->uop;
147
0
    for (int i = 0; i < 4; i++) {
148
0
        const SwsPixel vi = uop->data.vec4[i];
149
0
        switch (uop->type) {
150
0
        case SWS_PIXEL_U8:  out->priv.u8[i]  = vi.u8;  break;
151
0
        case SWS_PIXEL_U16: out->priv.u16[i] = vi.u16; break;
152
0
        case SWS_PIXEL_U32: out->priv.u32[i] = vi.u32; break;
153
0
        case SWS_PIXEL_F32: out->priv.f32[i] = vi.f32; break;
154
0
        default: return AVERROR(EINVAL);
155
0
        }
156
0
    }
157
158
0
    return 0;
159
0
}