• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <stdio.h>
22 #include <string.h>
23 #include <math.h>
24 #include "libavfilter/dnn/dnn_backend_native_layer_mathbinary.h"
25 #include "libavutil/avassert.h"
26 
27 #define EPSON 0.00005
28 
get_expected(float f1,float f2,DNNMathBinaryOperation op)29 static float get_expected(float f1, float f2, DNNMathBinaryOperation op)
30 {
31     switch (op)
32     {
33     case DMBO_SUB:
34         return f1 - f2;
35     case DMBO_ADD:
36         return f1 + f2;
37     case DMBO_MUL:
38         return f1 * f2;
39     case DMBO_REALDIV:
40         return f1 / f2;
41     case DMBO_MINIMUM:
42         return (f1 < f2) ? f1 : f2;
43     default:
44         av_assert0(!"not supported yet");
45         return 0.f;
46     }
47 }
48 
test_broadcast_input0(DNNMathBinaryOperation op)49 static int test_broadcast_input0(DNNMathBinaryOperation op)
50 {
51     DnnLayerMathBinaryParams params;
52     DnnOperand operands[2];
53     int32_t input_indexes[1];
54     float input[1*1*2*3] = {
55         -3, 2.5, 2, -2.1, 7.8, 100
56     };
57     float *output;
58 
59     params.bin_op = op;
60     params.input0_broadcast = 1;
61     params.input1_broadcast = 0;
62     params.v = 7.28;
63 
64     operands[0].data = input;
65     operands[0].dims[0] = 1;
66     operands[0].dims[1] = 1;
67     operands[0].dims[2] = 2;
68     operands[0].dims[3] = 3;
69     operands[1].data = NULL;
70 
71     input_indexes[0] = 0;
72     dnn_execute_layer_math_binary(operands, input_indexes, 1, &params);
73 
74     output = operands[1].data;
75     for (int i = 0; i < sizeof(input) / sizeof(float); i++) {
76         float expected_output = get_expected(params.v, input[i], op);
77         if (fabs(output[i] - expected_output) > EPSON) {
78             printf("op %d, at index %d, output: %f, expected_output: %f (%s:%d)\n",
79                     op, i, output[i], expected_output, __FILE__, __LINE__);
80             av_freep(&output);
81             return 1;
82         }
83     }
84 
85     av_freep(&output);
86     return 0;
87 }
88 
test_broadcast_input1(DNNMathBinaryOperation op)89 static int test_broadcast_input1(DNNMathBinaryOperation op)
90 {
91     DnnLayerMathBinaryParams params;
92     DnnOperand operands[2];
93     int32_t input_indexes[1];
94     float input[1*1*2*3] = {
95         -3, 2.5, 2, -2.1, 7.8, 100
96     };
97     float *output;
98 
99     params.bin_op = op;
100     params.input0_broadcast = 0;
101     params.input1_broadcast = 1;
102     params.v = 7.28;
103 
104     operands[0].data = input;
105     operands[0].dims[0] = 1;
106     operands[0].dims[1] = 1;
107     operands[0].dims[2] = 2;
108     operands[0].dims[3] = 3;
109     operands[1].data = NULL;
110 
111     input_indexes[0] = 0;
112     dnn_execute_layer_math_binary(operands, input_indexes, 1, &params);
113 
114     output = operands[1].data;
115     for (int i = 0; i < sizeof(input) / sizeof(float); i++) {
116         float expected_output = get_expected(input[i], params.v, op);
117         if (fabs(output[i] - expected_output) > EPSON) {
118             printf("op %d, at index %d, output: %f, expected_output: %f (%s:%d)\n",
119                     op, i, output[i], expected_output, __FILE__, __LINE__);
120             av_freep(&output);
121             return 1;
122         }
123     }
124 
125     av_freep(&output);
126     return 0;
127 }
128 
test_no_broadcast(DNNMathBinaryOperation op)129 static int test_no_broadcast(DNNMathBinaryOperation op)
130 {
131     DnnLayerMathBinaryParams params;
132     DnnOperand operands[3];
133     int32_t input_indexes[2];
134     float input0[1*1*2*3] = {
135         -3, 2.5, 2, -2.1, 7.8, 100
136     };
137     float input1[1*1*2*3] = {
138         -1, 2, 3, -21, 8, 10.0
139     };
140     float *output;
141 
142     params.bin_op = op;
143     params.input0_broadcast = 0;
144     params.input1_broadcast = 0;
145 
146     operands[0].data = input0;
147     operands[0].dims[0] = 1;
148     operands[0].dims[1] = 1;
149     operands[0].dims[2] = 2;
150     operands[0].dims[3] = 3;
151     operands[1].data = input1;
152     operands[1].dims[0] = 1;
153     operands[1].dims[1] = 1;
154     operands[1].dims[2] = 2;
155     operands[1].dims[3] = 3;
156     operands[2].data = NULL;
157 
158     input_indexes[0] = 0;
159     input_indexes[1] = 1;
160     dnn_execute_layer_math_binary(operands, input_indexes, 2, &params);
161 
162     output = operands[2].data;
163     for (int i = 0; i < sizeof(input0) / sizeof(float); i++) {
164         float expected_output = get_expected(input0[i], input1[i], op);
165         if (fabs(output[i] - expected_output) > EPSON) {
166             printf("op %d, at index %d, output: %f, expected_output: %f (%s:%d)\n",
167                     op, i, output[i], expected_output, __FILE__, __LINE__);
168             av_freep(&output);
169             return 1;
170         }
171     }
172 
173     av_freep(&output);
174     return 0;
175 }
176 
test(DNNMathBinaryOperation op)177 static int test(DNNMathBinaryOperation op)
178 {
179     if (test_broadcast_input0(op))
180         return 1;
181 
182     if (test_broadcast_input1(op))
183         return 1;
184 
185     if (test_no_broadcast(op))
186         return 1;
187 
188     return 0;
189 }
190 
main(int argc,char ** argv)191 int main(int argc, char **argv)
192 {
193     if (test(DMBO_SUB))
194         return 1;
195 
196     if (test(DMBO_ADD))
197         return 1;
198 
199     if (test(DMBO_MUL))
200         return 1;
201 
202     if (test(DMBO_REALDIV))
203         return 1;
204 
205     if (test(DMBO_MINIMUM))
206         return 1;
207 
208     return 0;
209 }
210