FFmpeg
dnn_backend_tf.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 Sergey Lavrushkin
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 tensorflow backend implementation.
24  */
25 
26 #include "dnn_backend_tf.h"
27 #include "dnn_backend_native.h"
28 #include "libavformat/avio.h"
29 #include "libavutil/avassert.h"
30 
31 #include <tensorflow/c/c_api.h>
32 
33 typedef struct TFModel{
34  TF_Graph *graph;
35  TF_Session *session;
36  TF_Status *status;
37  TF_Output input;
38  TF_Tensor *input_tensor;
39  TF_Output *outputs;
40  TF_Tensor **output_tensors;
41  uint32_t nb_output;
42 } TFModel;
43 
44 static void free_buffer(void *data, size_t length)
45 {
46  av_freep(&data);
47 }
48 
49 static TF_Buffer *read_graph(const char *model_filename)
50 {
51  TF_Buffer *graph_buf;
52  unsigned char *graph_data = NULL;
53  AVIOContext *model_file_context;
54  long size, bytes_read;
55 
56  if (avio_open(&model_file_context, model_filename, AVIO_FLAG_READ) < 0){
57  return NULL;
58  }
59 
60  size = avio_size(model_file_context);
61 
62  graph_data = av_malloc(size);
63  if (!graph_data){
64  avio_closep(&model_file_context);
65  return NULL;
66  }
67  bytes_read = avio_read(model_file_context, graph_data, size);
68  avio_closep(&model_file_context);
69  if (bytes_read != size){
70  av_freep(&graph_data);
71  return NULL;
72  }
73 
74  graph_buf = TF_NewBuffer();
75  graph_buf->data = (void *)graph_data;
76  graph_buf->length = size;
77  graph_buf->data_deallocator = free_buffer;
78 
79  return graph_buf;
80 }
81 
82 static TF_Tensor *allocate_input_tensor(const DNNInputData *input)
83 {
84  TF_DataType dt;
85  size_t size;
86  int64_t input_dims[] = {1, input->height, input->width, input->channels};
87  switch (input->dt) {
88  case DNN_FLOAT:
89  dt = TF_FLOAT;
90  size = sizeof(float);
91  break;
92  case DNN_UINT8:
93  dt = TF_UINT8;
94  size = sizeof(char);
95  break;
96  default:
97  av_assert0(!"should not reach here");
98  }
99 
100  return TF_AllocateTensor(dt, input_dims, 4,
101  input_dims[1] * input_dims[2] * input_dims[3] * size);
102 }
103 
104 static DNNReturnType set_input_output_tf(void *model, DNNInputData *input, const char *input_name, const char **output_names, uint32_t nb_output)
105 {
106  TFModel *tf_model = (TFModel *)model;
107  TF_SessionOptions *sess_opts;
108  const TF_Operation *init_op = TF_GraphOperationByName(tf_model->graph, "init");
109 
110  // Input operation
111  tf_model->input.oper = TF_GraphOperationByName(tf_model->graph, input_name);
112  if (!tf_model->input.oper){
113  return DNN_ERROR;
114  }
115  tf_model->input.index = 0;
116  if (tf_model->input_tensor){
117  TF_DeleteTensor(tf_model->input_tensor);
118  }
119  tf_model->input_tensor = allocate_input_tensor(input);
120  if (!tf_model->input_tensor){
121  return DNN_ERROR;
122  }
123  input->data = (float *)TF_TensorData(tf_model->input_tensor);
124 
125  // Output operation
126  if (nb_output == 0)
127  return DNN_ERROR;
128 
129  av_freep(&tf_model->outputs);
130  tf_model->outputs = av_malloc_array(nb_output, sizeof(*tf_model->outputs));
131  if (!tf_model->outputs)
132  return DNN_ERROR;
133  for (int i = 0; i < nb_output; ++i) {
134  tf_model->outputs[i].oper = TF_GraphOperationByName(tf_model->graph, output_names[i]);
135  if (!tf_model->outputs[i].oper){
136  av_freep(&tf_model->outputs);
137  return DNN_ERROR;
138  }
139  tf_model->outputs[i].index = 0;
140  }
141 
142  if (tf_model->output_tensors) {
143  for (uint32_t i = 0; i < tf_model->nb_output; ++i) {
144  if (tf_model->output_tensors[i]) {
145  TF_DeleteTensor(tf_model->output_tensors[i]);
146  tf_model->output_tensors[i] = NULL;
147  }
148  }
149  }
150  av_freep(&tf_model->output_tensors);
151  tf_model->output_tensors = av_mallocz_array(nb_output, sizeof(*tf_model->output_tensors));
152  if (!tf_model->output_tensors) {
153  av_freep(&tf_model->outputs);
154  return DNN_ERROR;
155  }
156 
157  tf_model->nb_output = nb_output;
158 
159  if (tf_model->session){
160  TF_CloseSession(tf_model->session, tf_model->status);
161  TF_DeleteSession(tf_model->session, tf_model->status);
162  }
163 
164  sess_opts = TF_NewSessionOptions();
165  tf_model->session = TF_NewSession(tf_model->graph, sess_opts, tf_model->status);
166  TF_DeleteSessionOptions(sess_opts);
167  if (TF_GetCode(tf_model->status) != TF_OK)
168  {
169  return DNN_ERROR;
170  }
171 
172  // Run initialization operation with name "init" if it is present in graph
173  if (init_op){
174  TF_SessionRun(tf_model->session, NULL,
175  NULL, NULL, 0,
176  NULL, NULL, 0,
177  &init_op, 1, NULL, tf_model->status);
178  if (TF_GetCode(tf_model->status) != TF_OK)
179  {
180  return DNN_ERROR;
181  }
182  }
183 
184  return DNN_SUCCESS;
185 }
186 
187 static DNNReturnType load_tf_model(TFModel *tf_model, const char *model_filename)
188 {
189  TF_Buffer *graph_def;
190  TF_ImportGraphDefOptions *graph_opts;
191 
192  graph_def = read_graph(model_filename);
193  if (!graph_def){
194  return DNN_ERROR;
195  }
196  tf_model->graph = TF_NewGraph();
197  tf_model->status = TF_NewStatus();
198  graph_opts = TF_NewImportGraphDefOptions();
199  TF_GraphImportGraphDef(tf_model->graph, graph_def, graph_opts, tf_model->status);
200  TF_DeleteImportGraphDefOptions(graph_opts);
201  TF_DeleteBuffer(graph_def);
202  if (TF_GetCode(tf_model->status) != TF_OK){
203  TF_DeleteGraph(tf_model->graph);
204  TF_DeleteStatus(tf_model->status);
205  return DNN_ERROR;
206  }
207 
208  return DNN_SUCCESS;
209 }
210 
211 #define NAME_BUFFER_SIZE 256
212 
213 static DNNReturnType add_conv_layer(TFModel *tf_model, TF_Operation *transpose_op, TF_Operation **cur_op,
214  ConvolutionalParams* params, const int layer)
215 {
216  TF_Operation *op;
217  TF_OperationDescription *op_desc;
218  TF_Output input;
219  int64_t strides[] = {1, 1, 1, 1};
220  TF_Tensor *tensor;
221  int64_t dims[4];
222  int dims_len;
223  char name_buffer[NAME_BUFFER_SIZE];
224  int32_t size;
225 
226  size = params->input_num * params->output_num * params->kernel_size * params->kernel_size;
227  input.index = 0;
228 
229  snprintf(name_buffer, NAME_BUFFER_SIZE, "conv_kernel%d", layer);
230  op_desc = TF_NewOperation(tf_model->graph, "Const", name_buffer);
231  TF_SetAttrType(op_desc, "dtype", TF_FLOAT);
232  dims[0] = params->output_num;
233  dims[1] = params->kernel_size;
234  dims[2] = params->kernel_size;
235  dims[3] = params->input_num;
236  dims_len = 4;
237  tensor = TF_AllocateTensor(TF_FLOAT, dims, dims_len, size * sizeof(float));
238  memcpy(TF_TensorData(tensor), params->kernel, size * sizeof(float));
239  TF_SetAttrTensor(op_desc, "value", tensor, tf_model->status);
240  if (TF_GetCode(tf_model->status) != TF_OK){
241  return DNN_ERROR;
242  }
243  op = TF_FinishOperation(op_desc, tf_model->status);
244  if (TF_GetCode(tf_model->status) != TF_OK){
245  return DNN_ERROR;
246  }
247 
248  snprintf(name_buffer, NAME_BUFFER_SIZE, "transpose%d", layer);
249  op_desc = TF_NewOperation(tf_model->graph, "Transpose", name_buffer);
250  input.oper = op;
251  TF_AddInput(op_desc, input);
252  input.oper = transpose_op;
253  TF_AddInput(op_desc, input);
254  TF_SetAttrType(op_desc, "T", TF_FLOAT);
255  TF_SetAttrType(op_desc, "Tperm", TF_INT32);
256  op = TF_FinishOperation(op_desc, tf_model->status);
257  if (TF_GetCode(tf_model->status) != TF_OK){
258  return DNN_ERROR;
259  }
260 
261  snprintf(name_buffer, NAME_BUFFER_SIZE, "conv2d%d", layer);
262  op_desc = TF_NewOperation(tf_model->graph, "Conv2D", name_buffer);
263  input.oper = *cur_op;
264  TF_AddInput(op_desc, input);
265  input.oper = op;
266  TF_AddInput(op_desc, input);
267  TF_SetAttrType(op_desc, "T", TF_FLOAT);
268  TF_SetAttrIntList(op_desc, "strides", strides, 4);
269  TF_SetAttrString(op_desc, "padding", "VALID", 5);
270  *cur_op = TF_FinishOperation(op_desc, tf_model->status);
271  if (TF_GetCode(tf_model->status) != TF_OK){
272  return DNN_ERROR;
273  }
274 
275  snprintf(name_buffer, NAME_BUFFER_SIZE, "conv_biases%d", layer);
276  op_desc = TF_NewOperation(tf_model->graph, "Const", name_buffer);
277  TF_SetAttrType(op_desc, "dtype", TF_FLOAT);
278  dims[0] = params->output_num;
279  dims_len = 1;
280  tensor = TF_AllocateTensor(TF_FLOAT, dims, dims_len, params->output_num * sizeof(float));
281  memcpy(TF_TensorData(tensor), params->biases, params->output_num * sizeof(float));
282  TF_SetAttrTensor(op_desc, "value", tensor, tf_model->status);
283  if (TF_GetCode(tf_model->status) != TF_OK){
284  return DNN_ERROR;
285  }
286  op = TF_FinishOperation(op_desc, tf_model->status);
287  if (TF_GetCode(tf_model->status) != TF_OK){
288  return DNN_ERROR;
289  }
290 
291  snprintf(name_buffer, NAME_BUFFER_SIZE, "bias_add%d", layer);
292  op_desc = TF_NewOperation(tf_model->graph, "BiasAdd", name_buffer);
293  input.oper = *cur_op;
294  TF_AddInput(op_desc, input);
295  input.oper = op;
296  TF_AddInput(op_desc, input);
297  TF_SetAttrType(op_desc, "T", TF_FLOAT);
298  *cur_op = TF_FinishOperation(op_desc, tf_model->status);
299  if (TF_GetCode(tf_model->status) != TF_OK){
300  return DNN_ERROR;
301  }
302 
303  snprintf(name_buffer, NAME_BUFFER_SIZE, "activation%d", layer);
304  switch (params->activation){
305  case RELU:
306  op_desc = TF_NewOperation(tf_model->graph, "Relu", name_buffer);
307  break;
308  case TANH:
309  op_desc = TF_NewOperation(tf_model->graph, "Tanh", name_buffer);
310  break;
311  case SIGMOID:
312  op_desc = TF_NewOperation(tf_model->graph, "Sigmoid", name_buffer);
313  break;
314  default:
315  return DNN_ERROR;
316  }
317  input.oper = *cur_op;
318  TF_AddInput(op_desc, input);
319  TF_SetAttrType(op_desc, "T", TF_FLOAT);
320  *cur_op = TF_FinishOperation(op_desc, tf_model->status);
321  if (TF_GetCode(tf_model->status) != TF_OK){
322  return DNN_ERROR;
323  }
324 
325  return DNN_SUCCESS;
326 }
327 
328 static DNNReturnType add_depth_to_space_layer(TFModel *tf_model, TF_Operation **cur_op,
329  DepthToSpaceParams *params, const int layer)
330 {
331  TF_OperationDescription *op_desc;
332  TF_Output input;
333  char name_buffer[NAME_BUFFER_SIZE];
334 
335  snprintf(name_buffer, NAME_BUFFER_SIZE, "depth_to_space%d", layer);
336  op_desc = TF_NewOperation(tf_model->graph, "DepthToSpace", name_buffer);
337  input.oper = *cur_op;
338  input.index = 0;
339  TF_AddInput(op_desc, input);
340  TF_SetAttrType(op_desc, "T", TF_FLOAT);
341  TF_SetAttrInt(op_desc, "block_size", params->block_size);
342  *cur_op = TF_FinishOperation(op_desc, tf_model->status);
343  if (TF_GetCode(tf_model->status) != TF_OK){
344  return DNN_ERROR;
345  }
346 
347  return DNN_SUCCESS;
348 }
349 
350 static int calculate_pad(const ConvolutionalNetwork *conv_network)
351 {
353  int32_t layer;
354  int pad = 0;
355 
356  for (layer = 0; layer < conv_network->layers_num; ++layer){
357  if (conv_network->layers[layer].type == CONV){
358  params = (ConvolutionalParams *)conv_network->layers[layer].params;
359  pad += params->kernel_size >> 1;
360  }
361  }
362 
363  return pad;
364 }
365 
366 static DNNReturnType add_pad_op(TFModel *tf_model, TF_Operation **cur_op, const int32_t pad)
367 {
368  TF_Operation *op;
369  TF_Tensor *tensor;
370  TF_OperationDescription *op_desc;
371  TF_Output input;
372  int32_t *pads;
373  int64_t pads_shape[] = {4, 2};
374 
375  input.index = 0;
376 
377  op_desc = TF_NewOperation(tf_model->graph, "Const", "pads");
378  TF_SetAttrType(op_desc, "dtype", TF_INT32);
379  tensor = TF_AllocateTensor(TF_INT32, pads_shape, 2, 4 * 2 * sizeof(int32_t));
380  pads = (int32_t *)TF_TensorData(tensor);
381  pads[0] = 0; pads[1] = 0;
382  pads[2] = pad; pads[3] = pad;
383  pads[4] = pad; pads[5] = pad;
384  pads[6] = 0; pads[7] = 0;
385  TF_SetAttrTensor(op_desc, "value", tensor, tf_model->status);
386  if (TF_GetCode(tf_model->status) != TF_OK){
387  return DNN_ERROR;
388  }
389  op = TF_FinishOperation(op_desc, tf_model->status);
390  if (TF_GetCode(tf_model->status) != TF_OK){
391  return DNN_ERROR;
392  }
393 
394  op_desc = TF_NewOperation(tf_model->graph, "MirrorPad", "mirror_pad");
395  input.oper = *cur_op;
396  TF_AddInput(op_desc, input);
397  input.oper = op;
398  TF_AddInput(op_desc, input);
399  TF_SetAttrType(op_desc, "T", TF_FLOAT);
400  TF_SetAttrType(op_desc, "Tpaddings", TF_INT32);
401  TF_SetAttrString(op_desc, "mode", "SYMMETRIC", 9);
402  *cur_op = TF_FinishOperation(op_desc, tf_model->status);
403  if (TF_GetCode(tf_model->status) != TF_OK){
404  return DNN_ERROR;
405  }
406 
407  return DNN_SUCCESS;
408 }
409 
410 static DNNReturnType load_native_model(TFModel *tf_model, const char *model_filename)
411 {
412  int32_t layer;
413  TF_OperationDescription *op_desc;
414  TF_Operation *op;
415  TF_Operation *transpose_op;
416  TF_Tensor *tensor;
417  TF_Output input;
419  int64_t transpose_perm_shape[] = {4};
420  int64_t input_shape[] = {1, -1, -1, -1};
421  int32_t pad;
422  DNNReturnType layer_add_res;
423  DNNModel *native_model = NULL;
424  ConvolutionalNetwork *conv_network;
425 
426  native_model = ff_dnn_load_model_native(model_filename);
427  if (!native_model){
428  return DNN_ERROR;
429  }
430 
431  conv_network = (ConvolutionalNetwork *)native_model->model;
432  pad = calculate_pad(conv_network);
433  tf_model->graph = TF_NewGraph();
434  tf_model->status = TF_NewStatus();
435 
436 #define CLEANUP_ON_ERROR(tf_model) \
437  { \
438  TF_DeleteGraph(tf_model->graph); \
439  TF_DeleteStatus(tf_model->status); \
440  return DNN_ERROR; \
441  }
442 
443  op_desc = TF_NewOperation(tf_model->graph, "Placeholder", "x");
444  TF_SetAttrType(op_desc, "dtype", TF_FLOAT);
445  TF_SetAttrShape(op_desc, "shape", input_shape, 4);
446  op = TF_FinishOperation(op_desc, tf_model->status);
447  if (TF_GetCode(tf_model->status) != TF_OK){
448  CLEANUP_ON_ERROR(tf_model);
449  }
450 
451  if (add_pad_op(tf_model, &op, pad) != DNN_SUCCESS){
452  CLEANUP_ON_ERROR(tf_model);
453  }
454 
455  op_desc = TF_NewOperation(tf_model->graph, "Const", "transpose_perm");
456  TF_SetAttrType(op_desc, "dtype", TF_INT32);
457  tensor = TF_AllocateTensor(TF_INT32, transpose_perm_shape, 1, 4 * sizeof(int32_t));
458  transpose_perm = (int32_t *)TF_TensorData(tensor);
459  transpose_perm[0] = 1;
460  transpose_perm[1] = 2;
461  transpose_perm[2] = 3;
462  transpose_perm[3] = 0;
463  TF_SetAttrTensor(op_desc, "value", tensor, tf_model->status);
464  if (TF_GetCode(tf_model->status) != TF_OK){
465  CLEANUP_ON_ERROR(tf_model);
466  }
467  transpose_op = TF_FinishOperation(op_desc, tf_model->status);
468 
469  for (layer = 0; layer < conv_network->layers_num; ++layer){
470  switch (conv_network->layers[layer].type){
471  case INPUT:
472  layer_add_res = DNN_SUCCESS;
473  break;
474  case CONV:
475  layer_add_res = add_conv_layer(tf_model, transpose_op, &op,
476  (ConvolutionalParams *)conv_network->layers[layer].params, layer);
477  break;
478  case DEPTH_TO_SPACE:
479  layer_add_res = add_depth_to_space_layer(tf_model, &op,
480  (DepthToSpaceParams *)conv_network->layers[layer].params, layer);
481  break;
482  default:
483  CLEANUP_ON_ERROR(tf_model);
484  }
485 
486  if (layer_add_res != DNN_SUCCESS){
487  CLEANUP_ON_ERROR(tf_model);
488  }
489  }
490 
491  op_desc = TF_NewOperation(tf_model->graph, "Identity", "y");
492  input.oper = op;
493  TF_AddInput(op_desc, input);
494  TF_FinishOperation(op_desc, tf_model->status);
495  if (TF_GetCode(tf_model->status) != TF_OK){
496  CLEANUP_ON_ERROR(tf_model);
497  }
498 
499  ff_dnn_free_model_native(&native_model);
500 
501  return DNN_SUCCESS;
502 }
503 
504 DNNModel *ff_dnn_load_model_tf(const char *model_filename)
505 {
506  DNNModel *model = NULL;
507  TFModel *tf_model = NULL;
508 
509  model = av_malloc(sizeof(DNNModel));
510  if (!model){
511  return NULL;
512  }
513 
514  tf_model = av_mallocz(sizeof(TFModel));
515  if (!tf_model){
516  av_freep(&model);
517  return NULL;
518  }
519 
520  if (load_tf_model(tf_model, model_filename) != DNN_SUCCESS){
521  if (load_native_model(tf_model, model_filename) != DNN_SUCCESS){
522  av_freep(&tf_model);
523  av_freep(&model);
524 
525  return NULL;
526  }
527  }
528 
529  model->model = (void *)tf_model;
531 
532  return model;
533 }
534 
535 
536 
538 {
539  TFModel *tf_model = (TFModel *)model->model;
540  uint32_t nb = FFMIN(nb_output, tf_model->nb_output);
541  if (nb == 0)
542  return DNN_ERROR;
543 
544  av_assert0(tf_model->output_tensors);
545  for (uint32_t i = 0; i < tf_model->nb_output; ++i) {
546  if (tf_model->output_tensors[i]) {
547  TF_DeleteTensor(tf_model->output_tensors[i]);
548  tf_model->output_tensors[i] = NULL;
549  }
550  }
551 
552  TF_SessionRun(tf_model->session, NULL,
553  &tf_model->input, &tf_model->input_tensor, 1,
554  tf_model->outputs, tf_model->output_tensors, nb,
555  NULL, 0, NULL, tf_model->status);
556 
557  if (TF_GetCode(tf_model->status) != TF_OK){
558  return DNN_ERROR;
559  }
560 
561  for (uint32_t i = 0; i < nb; ++i) {
562  outputs[i].height = TF_Dim(tf_model->output_tensors[i], 1);
563  outputs[i].width = TF_Dim(tf_model->output_tensors[i], 2);
564  outputs[i].channels = TF_Dim(tf_model->output_tensors[i], 3);
565  outputs[i].data = TF_TensorData(tf_model->output_tensors[i]);
566  }
567 
568  return DNN_SUCCESS;
569 }
570 
572 {
573  TFModel *tf_model;
574 
575  if (*model){
576  tf_model = (TFModel *)(*model)->model;
577  if (tf_model->graph){
578  TF_DeleteGraph(tf_model->graph);
579  }
580  if (tf_model->session){
581  TF_CloseSession(tf_model->session, tf_model->status);
582  TF_DeleteSession(tf_model->session, tf_model->status);
583  }
584  if (tf_model->status){
585  TF_DeleteStatus(tf_model->status);
586  }
587  if (tf_model->input_tensor){
588  TF_DeleteTensor(tf_model->input_tensor);
589  }
590  if (tf_model->output_tensors) {
591  for (uint32_t i = 0; i < tf_model->nb_output; ++i) {
592  if (tf_model->output_tensors[i]) {
593  TF_DeleteTensor(tf_model->output_tensors[i]);
594  tf_model->output_tensors[i] = NULL;
595  }
596  }
597  }
598  av_freep(&tf_model->outputs);
599  av_freep(&tf_model->output_tensors);
600  av_freep(&tf_model);
601  av_freep(model);
602  }
603 }
int avio_open(AVIOContext **s, const char *url, int flags)
Create and initialize a AVIOContext for accessing the resource indicated by url.
Definition: aviobuf.c:1153
void * model
Definition: dnn_interface.h:50
#define NULL
Definition: coverity.c:32
Bytestream IO Context.
Definition: avio.h:161
int64_t avio_size(AVIOContext *s)
Get the filesize.
Definition: aviobuf.c:336
Buffered I/O operations.
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
static TF_Buffer * read_graph(const char *model_filename)
int channels
Definition: dnn_interface.h:45
DNNActivationFunc activation
DNN inference functions interface for native backend.
#define AVIO_FLAG_READ
read-only
Definition: avio.h:654
DNNModel * ff_dnn_load_model_tf(const char *model_filename)
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
DNNDataType dt
Definition: dnn_interface.h:39
uint32_t nb_output
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
#define av_malloc(s)
TF_Status * status
DNN inference functions interface for TensorFlow backend.
ptrdiff_t size
Definition: opengl_enc.c:100
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:647
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
static TF_Tensor * allocate_input_tensor(const DNNInputData *input)
int height
Definition: dnn_interface.h:45
static DNNReturnType load_tf_model(TFModel *tf_model, const char *model_filename)
GLenum GLint * params
Definition: opengl_enc.c:113
simple assert() macros that are a bit more flexible than ISO C assert().
GLsizei GLsizei * length
Definition: opengl_enc.c:114
TF_Tensor * input_tensor
TF_Output input
static DNNReturnType load_native_model(TFModel *tf_model, const char *model_filename)
#define FFMIN(a, b)
Definition: common.h:96
#define NAME_BUFFER_SIZE
int32_t
static int calculate_pad(const ConvolutionalNetwork *conv_network)
DNNReturnType
Definition: dnn_interface.h:31
void ff_dnn_free_model_native(DNNModel **model)
if(ret)
static DNNReturnType add_conv_layer(TFModel *tf_model, TF_Operation *transpose_op, TF_Operation **cur_op, ConvolutionalParams *params, const int layer)
DNNReturnType ff_dnn_execute_model_tf(const DNNModel *model, DNNData *outputs, uint32_t nb_output)
static void free_buffer(void *data, size_t length)
static DNNReturnType add_depth_to_space_layer(TFModel *tf_model, TF_Operation **cur_op, DepthToSpaceParams *params, const int layer)
DNNReturnType(* set_input_output)(void *model, DNNInputData *input, const char *input_name, const char **output_names, uint32_t nb_output)
Definition: dnn_interface.h:53
TF_Tensor ** output_tensors
#define snprintf
Definition: snprintf.h:34
DNNLayerType type
TF_Session * session
static int op(uint8_t **dst, const uint8_t *dst_end, GetByteContext *gb, int pixel, int count, int *x, int width, int linesize)
Perform decode operation.
Definition: anm.c:78
TF_Output * outputs
static DNNReturnType add_pad_op(TFModel *tf_model, TF_Operation **cur_op, const int32_t pad)
static DNNReturnType set_input_output_tf(void *model, DNNInputData *input, const char *input_name, const char **output_names, uint32_t nb_output)
TF_Graph * graph
void ff_dnn_free_model_tf(DNNModel **model)
float * data
Definition: dnn_interface.h:44
void * params
static void transpose_perm(int16_t *out, int16_t *in, int num_vect, const uint8_t line_len[2], int length_div)
Interpret the input data as in the following table:
Definition: twinvq.c:630
DNNModel * ff_dnn_load_model_native(const char *model_filename)
#define av_freep(p)
#define av_malloc_array(a, b)
int avio_closep(AVIOContext **s)
Close the resource accessed by the AVIOContext *s, free it and set the pointer pointing to it to NULL...
Definition: aviobuf.c:1208
#define CLEANUP_ON_ERROR(tf_model)
void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.c:191