1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Copyright (c) 2019 Guo Yejun
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * This file is part of FFmpeg.
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
10cabdff1aSopenharmony_ci *
11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14cabdff1aSopenharmony_ci * Lesser General Public License for more details.
15cabdff1aSopenharmony_ci *
16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19cabdff1aSopenharmony_ci */
20cabdff1aSopenharmony_ci
21cabdff1aSopenharmony_ci#include <stdio.h>
22cabdff1aSopenharmony_ci#include <string.h>
23cabdff1aSopenharmony_ci#include <math.h>
24cabdff1aSopenharmony_ci#include "libavfilter/dnn/dnn_backend_native_layer_pad.h"
25cabdff1aSopenharmony_ci
26cabdff1aSopenharmony_ci#define EPSON 0.00001
27cabdff1aSopenharmony_ci
28cabdff1aSopenharmony_cistatic int test_with_mode_symmetric(void)
29cabdff1aSopenharmony_ci{
30cabdff1aSopenharmony_ci    // the input data and expected data are generated with below python code.
31cabdff1aSopenharmony_ci    /*
32cabdff1aSopenharmony_ci    x = tf.placeholder(tf.float32, shape=[1, None, None, 3])
33cabdff1aSopenharmony_ci    y = tf.pad(x, [[0, 0], [2, 3], [3, 2], [0, 0]], 'SYMMETRIC')
34cabdff1aSopenharmony_ci    data = np.arange(48).reshape(1, 4, 4, 3);
35cabdff1aSopenharmony_ci
36cabdff1aSopenharmony_ci    sess=tf.Session()
37cabdff1aSopenharmony_ci    sess.run(tf.global_variables_initializer())
38cabdff1aSopenharmony_ci    output = sess.run(y, feed_dict={x: data})
39cabdff1aSopenharmony_ci
40cabdff1aSopenharmony_ci    print(list(data.flatten()))
41cabdff1aSopenharmony_ci    print(list(output.flatten()))
42cabdff1aSopenharmony_ci    print(data.shape)
43cabdff1aSopenharmony_ci    print(output.shape)
44cabdff1aSopenharmony_ci    */
45cabdff1aSopenharmony_ci
46cabdff1aSopenharmony_ci    LayerPadParams params;
47cabdff1aSopenharmony_ci    DnnOperand operands[2];
48cabdff1aSopenharmony_ci    int32_t input_indexes[1];
49cabdff1aSopenharmony_ci    float input[1*4*4*3] = {
50cabdff1aSopenharmony_ci        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47
51cabdff1aSopenharmony_ci    };
52cabdff1aSopenharmony_ci    float expected_output[1*9*9*3] = {
53cabdff1aSopenharmony_ci        18.0, 19.0, 20.0, 15.0, 16.0, 17.0, 12.0, 13.0, 14.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 21.0, 22.0, 23.0, 18.0, 19.0, 20.0, 6.0, 7.0, 8.0, 3.0,
54cabdff1aSopenharmony_ci        4.0, 5.0, 0.0, 1.0, 2.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 9.0, 10.0, 11.0, 6.0, 7.0, 8.0, 6.0, 7.0, 8.0, 3.0, 4.0, 5.0, 0.0, 1.0, 2.0, 0.0, 1.0, 2.0, 3.0,
55cabdff1aSopenharmony_ci        4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 9.0, 10.0, 11.0, 6.0, 7.0, 8.0, 18.0, 19.0, 20.0, 15.0, 16.0, 17.0, 12.0, 13.0, 14.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0,
56cabdff1aSopenharmony_ci        21.0, 22.0, 23.0, 21.0, 22.0, 23.0, 18.0, 19.0, 20.0, 30.0, 31.0, 32.0, 27.0, 28.0, 29.0, 24.0, 25.0, 26.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 33.0,
57cabdff1aSopenharmony_ci        34.0, 35.0, 30.0, 31.0, 32.0, 42.0, 43.0, 44.0, 39.0, 40.0, 41.0, 36.0, 37.0, 38.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 45.0, 46.0, 47.0, 42.0, 43.0,
58cabdff1aSopenharmony_ci        44.0, 42.0, 43.0, 44.0, 39.0, 40.0, 41.0, 36.0, 37.0, 38.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 45.0, 46.0, 47.0, 42.0, 43.0, 44.0, 30.0, 31.0, 32.0,
59cabdff1aSopenharmony_ci        27.0, 28.0, 29.0, 24.0, 25.0, 26.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 33.0, 34.0, 35.0, 30.0, 31.0, 32.0, 18.0, 19.0, 20.0, 15.0, 16.0, 17.0, 12.0,
60cabdff1aSopenharmony_ci        13.0, 14.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 21.0, 22.0, 23.0, 18.0, 19.0, 20.0
61cabdff1aSopenharmony_ci    };
62cabdff1aSopenharmony_ci    float *output;
63cabdff1aSopenharmony_ci
64cabdff1aSopenharmony_ci    params.mode = LPMP_SYMMETRIC;
65cabdff1aSopenharmony_ci    params.paddings[0][0] = 0;
66cabdff1aSopenharmony_ci    params.paddings[0][1] = 0;
67cabdff1aSopenharmony_ci    params.paddings[1][0] = 2;
68cabdff1aSopenharmony_ci    params.paddings[1][1] = 3;
69cabdff1aSopenharmony_ci    params.paddings[2][0] = 3;
70cabdff1aSopenharmony_ci    params.paddings[2][1] = 2;
71cabdff1aSopenharmony_ci    params.paddings[3][0] = 0;
72cabdff1aSopenharmony_ci    params.paddings[3][1] = 0;
73cabdff1aSopenharmony_ci
74cabdff1aSopenharmony_ci    operands[0].data = input;
75cabdff1aSopenharmony_ci    operands[0].dims[0] = 1;
76cabdff1aSopenharmony_ci    operands[0].dims[1] = 4;
77cabdff1aSopenharmony_ci    operands[0].dims[2] = 4;
78cabdff1aSopenharmony_ci    operands[0].dims[3] = 3;
79cabdff1aSopenharmony_ci    operands[1].data = NULL;
80cabdff1aSopenharmony_ci
81cabdff1aSopenharmony_ci    input_indexes[0] = 0;
82cabdff1aSopenharmony_ci    ff_dnn_execute_layer_pad(operands, input_indexes, 1, &params, NULL);
83cabdff1aSopenharmony_ci
84cabdff1aSopenharmony_ci    output = operands[1].data;
85cabdff1aSopenharmony_ci    for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) {
86cabdff1aSopenharmony_ci        if (fabs(output[i] - expected_output[i]) > EPSON) {
87cabdff1aSopenharmony_ci            printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]);
88cabdff1aSopenharmony_ci            av_freep(&output);
89cabdff1aSopenharmony_ci            return 1;
90cabdff1aSopenharmony_ci        }
91cabdff1aSopenharmony_ci    }
92cabdff1aSopenharmony_ci
93cabdff1aSopenharmony_ci    av_freep(&output);
94cabdff1aSopenharmony_ci    return 0;
95cabdff1aSopenharmony_ci
96cabdff1aSopenharmony_ci}
97cabdff1aSopenharmony_ci
98cabdff1aSopenharmony_cistatic int test_with_mode_reflect(void)
99cabdff1aSopenharmony_ci{
100cabdff1aSopenharmony_ci    // the input data and expected data are generated with below python code.
101cabdff1aSopenharmony_ci    /*
102cabdff1aSopenharmony_ci    x = tf.placeholder(tf.float32, shape=[3, None, None, 3])
103cabdff1aSopenharmony_ci    y = tf.pad(x, [[1, 2], [0, 0], [0, 0], [0, 0]], 'REFLECT')
104cabdff1aSopenharmony_ci    data = np.arange(36).reshape(3, 2, 2, 3);
105cabdff1aSopenharmony_ci
106cabdff1aSopenharmony_ci    sess=tf.Session()
107cabdff1aSopenharmony_ci    sess.run(tf.global_variables_initializer())
108cabdff1aSopenharmony_ci    output = sess.run(y, feed_dict={x: data})
109cabdff1aSopenharmony_ci
110cabdff1aSopenharmony_ci    print(list(data.flatten()))
111cabdff1aSopenharmony_ci    print(list(output.flatten()))
112cabdff1aSopenharmony_ci    print(data.shape)
113cabdff1aSopenharmony_ci    print(output.shape)
114cabdff1aSopenharmony_ci    */
115cabdff1aSopenharmony_ci
116cabdff1aSopenharmony_ci    LayerPadParams params;
117cabdff1aSopenharmony_ci    DnnOperand operands[2];
118cabdff1aSopenharmony_ci    int32_t input_indexes[1];
119cabdff1aSopenharmony_ci    float input[3*2*2*3] = {
120cabdff1aSopenharmony_ci        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35
121cabdff1aSopenharmony_ci    };
122cabdff1aSopenharmony_ci    float expected_output[6*2*2*3] = {
123cabdff1aSopenharmony_ci        12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0,
124cabdff1aSopenharmony_ci        12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0,
125cabdff1aSopenharmony_ci        35.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0
126cabdff1aSopenharmony_ci    };
127cabdff1aSopenharmony_ci    float *output;
128cabdff1aSopenharmony_ci
129cabdff1aSopenharmony_ci    params.mode = LPMP_REFLECT;
130cabdff1aSopenharmony_ci    params.paddings[0][0] = 1;
131cabdff1aSopenharmony_ci    params.paddings[0][1] = 2;
132cabdff1aSopenharmony_ci    params.paddings[1][0] = 0;
133cabdff1aSopenharmony_ci    params.paddings[1][1] = 0;
134cabdff1aSopenharmony_ci    params.paddings[2][0] = 0;
135cabdff1aSopenharmony_ci    params.paddings[2][1] = 0;
136cabdff1aSopenharmony_ci    params.paddings[3][0] = 0;
137cabdff1aSopenharmony_ci    params.paddings[3][1] = 0;
138cabdff1aSopenharmony_ci
139cabdff1aSopenharmony_ci    operands[0].data = input;
140cabdff1aSopenharmony_ci    operands[0].dims[0] = 3;
141cabdff1aSopenharmony_ci    operands[0].dims[1] = 2;
142cabdff1aSopenharmony_ci    operands[0].dims[2] = 2;
143cabdff1aSopenharmony_ci    operands[0].dims[3] = 3;
144cabdff1aSopenharmony_ci    operands[1].data = NULL;
145cabdff1aSopenharmony_ci
146cabdff1aSopenharmony_ci    input_indexes[0] = 0;
147cabdff1aSopenharmony_ci    ff_dnn_execute_layer_pad(operands, input_indexes, 1, &params, NULL);
148cabdff1aSopenharmony_ci
149cabdff1aSopenharmony_ci    output = operands[1].data;
150cabdff1aSopenharmony_ci    for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) {
151cabdff1aSopenharmony_ci        if (fabs(output[i] - expected_output[i]) > EPSON) {
152cabdff1aSopenharmony_ci            printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]);
153cabdff1aSopenharmony_ci            av_freep(&output);
154cabdff1aSopenharmony_ci            return 1;
155cabdff1aSopenharmony_ci        }
156cabdff1aSopenharmony_ci    }
157cabdff1aSopenharmony_ci
158cabdff1aSopenharmony_ci    av_freep(&output);
159cabdff1aSopenharmony_ci    return 0;
160cabdff1aSopenharmony_ci
161cabdff1aSopenharmony_ci}
162cabdff1aSopenharmony_ci
163cabdff1aSopenharmony_cistatic int test_with_mode_constant(void)
164cabdff1aSopenharmony_ci{
165cabdff1aSopenharmony_ci    // the input data and expected data are generated with below python code.
166cabdff1aSopenharmony_ci    /*
167cabdff1aSopenharmony_ci    x = tf.placeholder(tf.float32, shape=[1, None, None, 3])
168cabdff1aSopenharmony_ci    y = tf.pad(x, [[0, 0], [1, 0], [0, 0], [1, 2]], 'CONSTANT', constant_values=728)
169cabdff1aSopenharmony_ci    data = np.arange(12).reshape(1, 2, 2, 3);
170cabdff1aSopenharmony_ci
171cabdff1aSopenharmony_ci    sess=tf.Session()
172cabdff1aSopenharmony_ci    sess.run(tf.global_variables_initializer())
173cabdff1aSopenharmony_ci    output = sess.run(y, feed_dict={x: data})
174cabdff1aSopenharmony_ci
175cabdff1aSopenharmony_ci    print(list(data.flatten()))
176cabdff1aSopenharmony_ci    print(list(output.flatten()))
177cabdff1aSopenharmony_ci    print(data.shape)
178cabdff1aSopenharmony_ci    print(output.shape)
179cabdff1aSopenharmony_ci    */
180cabdff1aSopenharmony_ci
181cabdff1aSopenharmony_ci    LayerPadParams params;
182cabdff1aSopenharmony_ci    DnnOperand operands[2];
183cabdff1aSopenharmony_ci    int32_t input_indexes[1];
184cabdff1aSopenharmony_ci    float input[1*2*2*3] = {
185cabdff1aSopenharmony_ci        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
186cabdff1aSopenharmony_ci    };
187cabdff1aSopenharmony_ci    float expected_output[1*3*2*6] = {
188cabdff1aSopenharmony_ci        728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0,
189cabdff1aSopenharmony_ci        728.0, 728.0, 0.0, 1.0, 2.0, 728.0, 728.0, 728.0, 3.0, 4.0, 5.0, 728.0, 728.0,
190cabdff1aSopenharmony_ci        728.0, 6.0, 7.0, 8.0, 728.0, 728.0, 728.0, 9.0, 10.0, 11.0, 728.0, 728.0
191cabdff1aSopenharmony_ci    };
192cabdff1aSopenharmony_ci    float *output;
193cabdff1aSopenharmony_ci
194cabdff1aSopenharmony_ci    params.mode = LPMP_CONSTANT;
195cabdff1aSopenharmony_ci    params.constant_values = 728;
196cabdff1aSopenharmony_ci    params.paddings[0][0] = 0;
197cabdff1aSopenharmony_ci    params.paddings[0][1] = 0;
198cabdff1aSopenharmony_ci    params.paddings[1][0] = 1;
199cabdff1aSopenharmony_ci    params.paddings[1][1] = 0;
200cabdff1aSopenharmony_ci    params.paddings[2][0] = 0;
201cabdff1aSopenharmony_ci    params.paddings[2][1] = 0;
202cabdff1aSopenharmony_ci    params.paddings[3][0] = 1;
203cabdff1aSopenharmony_ci    params.paddings[3][1] = 2;
204cabdff1aSopenharmony_ci
205cabdff1aSopenharmony_ci    operands[0].data = input;
206cabdff1aSopenharmony_ci    operands[0].dims[0] = 1;
207cabdff1aSopenharmony_ci    operands[0].dims[1] = 2;
208cabdff1aSopenharmony_ci    operands[0].dims[2] = 2;
209cabdff1aSopenharmony_ci    operands[0].dims[3] = 3;
210cabdff1aSopenharmony_ci    operands[1].data = NULL;
211cabdff1aSopenharmony_ci
212cabdff1aSopenharmony_ci    input_indexes[0] = 0;
213cabdff1aSopenharmony_ci    ff_dnn_execute_layer_pad(operands, input_indexes, 1, &params, NULL);
214cabdff1aSopenharmony_ci
215cabdff1aSopenharmony_ci    output = operands[1].data;
216cabdff1aSopenharmony_ci    for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) {
217cabdff1aSopenharmony_ci        if (fabs(output[i] - expected_output[i]) > EPSON) {
218cabdff1aSopenharmony_ci            printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]);
219cabdff1aSopenharmony_ci            av_freep(&output);
220cabdff1aSopenharmony_ci            return 1;
221cabdff1aSopenharmony_ci        }
222cabdff1aSopenharmony_ci    }
223cabdff1aSopenharmony_ci
224cabdff1aSopenharmony_ci    av_freep(&output);
225cabdff1aSopenharmony_ci    return 0;
226cabdff1aSopenharmony_ci
227cabdff1aSopenharmony_ci}
228cabdff1aSopenharmony_ci
229cabdff1aSopenharmony_ciint main(int argc, char **argv)
230cabdff1aSopenharmony_ci{
231cabdff1aSopenharmony_ci    if (test_with_mode_symmetric())
232cabdff1aSopenharmony_ci        return 1;
233cabdff1aSopenharmony_ci
234cabdff1aSopenharmony_ci    if (test_with_mode_reflect())
235cabdff1aSopenharmony_ci        return 1;
236cabdff1aSopenharmony_ci
237cabdff1aSopenharmony_ci    if (test_with_mode_constant())
238cabdff1aSopenharmony_ci        return 1;
239cabdff1aSopenharmony_ci}
240