FFmpeg
dnn_backend_native_layer_pad.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 Guo Yejun
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 <string.h>
22 #include "libavutil/avassert.h"
24 
25 static int before_get_buddy(int given, int paddings, LayerPadModeParam mode)
26 {
27  if (mode == LPMP_SYMMETRIC) {
28  return (2 * paddings - 1 - given);
29  } else if (mode == LPMP_REFLECT) {
30  return (2 * paddings - given);
31  } else {
32  av_assert0(!"should not reach here");
33  return 0;
34  }
35 }
36 
37 static int after_get_buddy(int given, int border, LayerPadModeParam mode)
38 {
39  if (mode == LPMP_SYMMETRIC) {
40  int offset = given - border;
41  return (border - 1 - offset);
42  } else if (mode == LPMP_REFLECT) {
43  int offset = given - border;
44  return (border - 2 - offset);
45  } else {
46  av_assert0(!"should not reach here");
47  return 0;
48  }
49 }
50 
51 int dnn_execute_layer_pad(DnnOperand *operands, const int32_t *input_operand_indexes, int32_t output_operand_index,
52  const LayerPadParams *params)
53 {
54  int32_t before_paddings;
55  int32_t after_paddings;
56  float* output;
57 
58  // suppose format is <N, H, W, C>
59  int32_t input_operand_index = input_operand_indexes[0];
60  int number = operands[input_operand_index].dims[0];
61  int height = operands[input_operand_index].dims[1];
62  int width = operands[input_operand_index].dims[2];
63  int channel = operands[input_operand_index].dims[3];
64  const float *input = operands[input_operand_index].data;
65 
66  int new_number = number + params->paddings[0][0] + params->paddings[0][1];
67  int new_height = height + params->paddings[1][0] + params->paddings[1][1];
68  int new_width = width + params->paddings[2][0] + params->paddings[2][1];
69  int new_channel = channel + params->paddings[3][0] + params->paddings[3][1];
70 
71  int c_stride = channel;
72  int wc_stride = c_stride * width;
73  int hwc_stride = wc_stride * height;
74 
75  int new_c_stride = new_channel;
76  int new_wc_stride = new_c_stride * new_width;
77  int new_hwc_stride = new_wc_stride * new_height;
78 
79  DnnOperand *output_operand = &operands[output_operand_index];
80  output_operand->dims[0] = new_number;
81  output_operand->dims[1] = new_height;
82  output_operand->dims[2] = new_width;
83  output_operand->dims[3] = new_channel;
84  output_operand->length = calculate_operand_data_length(output_operand);
85  output_operand->data = av_realloc(output_operand->data, output_operand->length);
86  if (!output_operand->data)
87  return -1;
88  output = output_operand->data;
89 
90  // copy the original data
91  for (int n = 0; n < number; n++) {
92  for (int h = 0; h < height; h++) {
93  for (int w = 0; w < width; w++) {
94  const float *src = input + n * hwc_stride + h * wc_stride + w * c_stride;
95  float *dst = output + (n + params->paddings[0][0]) * new_hwc_stride
96  + (h + params->paddings[1][0]) * new_wc_stride
97  + (w + params->paddings[2][0]) * new_c_stride
98  + params->paddings[3][0];
99  memcpy(dst, src, channel * sizeof(float));
100  }
101  }
102  }
103 
104  // handle the first dimension
105  before_paddings = params->paddings[0][0];
106  after_paddings = params->paddings[0][1];
107  for (int n = 0; n < before_paddings; n++) {
108  float *dst = output + n * new_hwc_stride;
109  if (params->mode == LPMP_CONSTANT) {
110  for (int i = 0; i < new_hwc_stride; i++) {
111  dst[i] = params->constant_values;
112  }
113  }
114  else {
115  int buddy = before_get_buddy(n, before_paddings, params->mode);
116  float *src = output + buddy * new_hwc_stride;
117  memcpy(dst, src, new_hwc_stride * sizeof(float));
118  }
119  }
120  for (int n = 0; n < after_paddings; n++) {
121  int given = number + before_paddings + n;
122  float *dst = output + given * new_hwc_stride;
123  if (params->mode == LPMP_CONSTANT) {
124  for (int i = 0; i < new_hwc_stride; i++) {
125  dst[i] = params->constant_values;
126  }
127  } else {
128  int buddy = after_get_buddy(given, number + before_paddings, params->mode);
129  float *src = output + buddy * new_hwc_stride;
130  memcpy(dst, src, new_hwc_stride * sizeof(float));
131  }
132  }
133 
134  // handle the second dimension
135  before_paddings = params->paddings[1][0];
136  after_paddings = params->paddings[1][1];
137  for (int n = 0; n < new_number; n++) {
138  float *start = output + n * new_hwc_stride;
139  for (int h = 0; h < before_paddings; h++) {
140  float *dst = start + h * new_wc_stride;
141  if (params->mode == LPMP_CONSTANT) {
142  for (int i = 0; i < new_wc_stride; i++) {
143  dst[i] = params->constant_values;
144  }
145  } else {
146  int buddy = before_get_buddy(h, before_paddings, params->mode);
147  float *src = start + buddy * new_wc_stride;
148  memcpy(dst, src, new_wc_stride * sizeof(float));
149  }
150  }
151  for (int h = 0; h < after_paddings; h++) {
152  int given = height + before_paddings + h;
153  float *dst = start + given * new_wc_stride;
154  if (params->mode == LPMP_CONSTANT) {
155  for (int i = 0; i < new_wc_stride; i++) {
156  dst[i] = params->constant_values;
157  }
158  } else {
159  int buddy = after_get_buddy(given, height + before_paddings, params->mode);
160  float *src = start + buddy * new_wc_stride;
161  memcpy(dst, src, new_wc_stride * sizeof(float));
162  }
163  }
164  }
165 
166  // handle the third dimension
167  before_paddings = params->paddings[2][0];
168  after_paddings = params->paddings[2][1];
169  for (int n = 0; n < new_number; n++) {
170  for (int h = 0; h < new_height; h++) {
171  float *start = output + n * new_hwc_stride + h * new_wc_stride;
172  for (int w = 0; w < before_paddings; w++) {
173  float *dst = start + w * new_c_stride;
174  if (params->mode == LPMP_CONSTANT) {
175  for (int i = 0; i < new_c_stride; i++) {
176  dst[i] = params->constant_values;
177  }
178  } else {
179  int buddy = before_get_buddy(w, before_paddings, params->mode);
180  float *src = start + buddy * new_c_stride;
181  memcpy(dst, src, new_c_stride * sizeof(float));
182  }
183  }
184  for (int w = 0; w < after_paddings; w++) {
185  int given = width + before_paddings + w;
186  float *dst = start + given * new_c_stride;
187  if (params->mode == LPMP_CONSTANT) {
188  for (int i = 0; i < new_c_stride; i++) {
189  dst[i] = params->constant_values;
190  }
191  } else {
192  int buddy = after_get_buddy(given, width + before_paddings, params->mode);
193  float *src = start + buddy * new_c_stride;
194  memcpy(dst, src, new_c_stride * sizeof(float));
195  }
196  }
197  }
198  }
199 
200  // handle the fourth dimension
201  before_paddings = params->paddings[3][0];
202  after_paddings = params->paddings[3][1];
203  for (int n = 0; n < new_number; n++) {
204  for (int h = 0; h < new_height; h++) {
205  for (int w = 0; w < new_width; w++) {
206  float *start = output + n * new_hwc_stride + h * new_wc_stride + w * new_c_stride;
207  for (int c = 0; c < before_paddings; c++) {
208  float *dst = start + c;
209  if (params->mode == LPMP_CONSTANT) {
210  *dst = params->constant_values;
211  } else {
212  int buddy = before_get_buddy(c, before_paddings, params->mode);
213  float *src = start + buddy;
214  *dst = *src;
215  }
216  }
217  for (int c = 0; c < after_paddings; c++) {
218  int given = channel + before_paddings + c;
219  float *dst = start + given;
220  if (params->mode == LPMP_CONSTANT) {
221  *dst = params->constant_values;
222  } else {
223  int buddy = after_get_buddy(given, channel + before_paddings, params->mode);
224  float *src = start + buddy;
225  *dst = *src;
226  }
227  }
228  }
229  }
230  }
231 
232  return 0;
233 }
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:135
AVS_VideoFrame int int int int new_height
Definition: avisynth_c.h:913
#define src
Definition: vp8dsp.c:254
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce output
#define height
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
void * data
data pointer with data length in bytes.
GLenum GLint * params
Definition: opengl_enc.c:113
simple assert() macros that are a bit more flexible than ISO C assert().
int32_t dims[4]
there are two memory layouts, NHWC or NCHW, so we use dims, dims[0] is Number.
#define width
uint8_t w
Definition: llviddspenc.c:38
static int after_get_buddy(int given, int border, LayerPadModeParam mode)
int32_t
int n
Definition: avisynth_c.h:760
static int before_get_buddy(int given, int paddings, LayerPadModeParam mode)
int dnn_execute_layer_pad(DnnOperand *operands, const int32_t *input_operand_indexes, int32_t output_operand_index, const LayerPadParams *params)
layer pad (equivalent to tf.pad) for native backend.
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some input
channel
Use these values when setting the channel map with ebur128_set_channel().
Definition: ebur128.h:39
int32_t calculate_operand_data_length(DnnOperand *operand)
void INT64 start
Definition: avisynth_c.h:766
mode
Use these values in ebur128_init (or&#39;ed).
Definition: ebur128.h:83