GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavfilter/dnn/dnn_backend_native_layer_mathbinary.c Lines: 66 102 64.7 %
Date: 2020-08-11 16:46:18 Branches: 57 72 79.2 %

Line Branch Exec Source
1
/*
2
 * Copyright (c) 2020
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
/**
22
 * @file
23
 * DNN native backend implementation.
24
 */
25
26
#include "dnn_backend_native.h"
27
#include "libavutil/avassert.h"
28
#include "dnn_backend_native_layer_mathbinary.h"
29
30
int dnn_load_layer_math_binary(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num)
31
{
32
    DnnLayerMathBinaryParams *params;
33
    int dnn_size = 0;
34
    int input_index = 0;
35
    params = av_malloc(sizeof(*params));
36
    if (!params)
37
        return 0;
38
39
    params->bin_op = (int32_t)avio_rl32(model_file_context);
40
    dnn_size += 4;
41
42
    params->input0_broadcast = (int32_t)avio_rl32(model_file_context);
43
    dnn_size += 4;
44
    if (params->input0_broadcast) {
45
        params->v = av_int2float(avio_rl32(model_file_context));
46
    } else {
47
        layer->input_operand_indexes[input_index] = (int32_t)avio_rl32(model_file_context);
48
        if (layer->input_operand_indexes[input_index] >= operands_num) {
49
            return 0;
50
        }
51
        input_index++;
52
    }
53
    dnn_size += 4;
54
55
    params->input1_broadcast = (int32_t)avio_rl32(model_file_context);
56
    dnn_size += 4;
57
    if (params->input1_broadcast) {
58
        params->v = av_int2float(avio_rl32(model_file_context));
59
    } else {
60
        layer->input_operand_indexes[input_index] = (int32_t)avio_rl32(model_file_context);
61
        if (layer->input_operand_indexes[input_index] >= operands_num) {
62
            return 0;
63
        }
64
        input_index++;
65
    }
66
    dnn_size += 4;
67
68
    layer->output_operand_index = (int32_t)avio_rl32(model_file_context);
69
    dnn_size += 4;
70
    layer->params = params;
71
72
    if (layer->output_operand_index >= operands_num) {
73
        return 0;
74
    }
75
76
    return dnn_size;
77
}
78
79
15
int dnn_execute_layer_math_binary(DnnOperand *operands, const int32_t *input_operand_indexes,
80
                                 int32_t output_operand_index, const void *parameters)
81
{
82
15
    const DnnOperand *input = &operands[input_operand_indexes[0]];
83
15
    DnnOperand *output = &operands[output_operand_index];
84
15
    const DnnLayerMathBinaryParams *params = (const DnnLayerMathBinaryParams *)parameters;
85
    int dims_count;
86
    const float *src;
87
    float *dst;
88
89
75
    for (int i = 0; i < 4; ++i)
90
60
        output->dims[i] = input->dims[i];
91
92
15
    output->data_type = input->data_type;
93
15
    output->length = calculate_operand_data_length(output);
94
15
    if (output->length <= 0)
95
        return DNN_ERROR;
96
15
    output->data = av_realloc(output->data, output->length);
97
15
    if (!output->data)
98
        return DNN_ERROR;
99
100
15
    dims_count = calculate_operand_dims_count(output);
101
15
    src = input->data;
102
15
    dst = output->data;
103
104

15
    switch (params->bin_op) {
105
3
    case DMBO_SUB:
106
3
        if (params->input0_broadcast) {
107
7
            for (int i = 0; i < dims_count; ++i) {
108
6
                dst[i] = params->v - src[i];
109
            }
110
2
        } else if (params->input1_broadcast) {
111
7
            for (int i = 0; i < dims_count; ++i) {
112
6
                dst[i] = src[i] - params->v;
113
            }
114
        } else {
115
1
            const DnnOperand *input1 = &operands[input_operand_indexes[1]];
116
1
            const float *src1 = input1->data;
117
7
            for (int i = 0; i < dims_count; ++i) {
118
6
                dst[i] = src[i] - src1[i];
119
            }
120
        }
121
3
        return 0;
122
3
    case DMBO_ADD:
123

3
        if (params->input0_broadcast || params->input1_broadcast) {
124
14
            for (int i = 0; i < dims_count; ++i) {
125
12
                dst[i] = params->v + src[i];
126
            }
127
        } else {
128
1
            const DnnOperand *input1 = &operands[input_operand_indexes[1]];
129
1
            const float *src1 = input1->data;
130
7
            for (int i = 0; i < dims_count; ++i) {
131
6
                dst[i] = src[i] + src1[i];
132
            }
133
        }
134
3
        return 0;
135
3
    case DMBO_MUL:
136

3
        if (params->input0_broadcast || params->input1_broadcast) {
137
14
            for (int i = 0; i < dims_count; ++i) {
138
12
                dst[i] = params->v * src[i];
139
            }
140
        } else {
141
1
            const DnnOperand *input1 = &operands[input_operand_indexes[1]];
142
1
            const float *src1 = input1->data;
143
7
            for (int i = 0; i < dims_count; ++i) {
144
6
                dst[i] = src[i] * src1[i];
145
            }
146
        }
147
3
        return 0;
148
3
    case DMBO_REALDIV:
149
3
        if (params->input0_broadcast) {
150
7
            for (int i = 0; i < dims_count; ++i) {
151
6
                dst[i] = params->v / src[i];
152
            }
153
2
        } else if (params->input1_broadcast) {
154
7
            for (int i = 0; i < dims_count; ++i) {
155
6
                dst[i] = src[i] / params->v;
156
            }
157
        } else {
158
1
            const DnnOperand *input1 = &operands[input_operand_indexes[1]];
159
1
            const float *src1 = input1->data;
160
7
            for (int i = 0; i < dims_count; ++i) {
161
6
                dst[i] = src[i] / src1[i];
162
            }
163
        }
164
3
        return 0;
165
3
    case DMBO_MINIMUM:
166

3
        if (params->input0_broadcast || params->input1_broadcast) {
167
14
            for (int i = 0; i < dims_count; ++i) {
168
12
                dst[i] = FFMIN(params->v, src[i]);
169
            }
170
        } else {
171
1
            const DnnOperand *input1 = &operands[input_operand_indexes[1]];
172
1
            const float *src1 = input1->data;
173
7
            for (int i = 0; i < dims_count; ++i) {
174
6
                dst[i] = FFMIN(src[i], src1[i]);
175
            }
176
        }
177
3
        return 0;
178
    default:
179
        return -1;
180
    }
181
}