FFmpeg
dnn_interface.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  * Implements DNN module initialization with specified backend.
24  */
25 
26 #include "../dnn_interface.h"
27 #include "libavutil/avassert.h"
28 #include "libavutil/mem.h"
29 #include "libavutil/opt.h"
30 
31 #include "libavfilter/filters.h"
32 
34 extern const DNNModule ff_dnn_backend_tf;
35 extern const DNNModule ff_dnn_backend_torch;
36 
37 #define OFFSET(x) offsetof(DnnContext, x)
38 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM
39 static const AVOption dnn_base_options[] = {
40  {"model", "path to model file",
41  OFFSET(model_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS},
42  {"input", "input name of the model",
43  OFFSET(model_inputname), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS},
44  {"output", "output name of the model",
45  OFFSET(model_outputnames_string), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS},
46  {"backend_configs", "backend configs (deprecated)",
47  OFFSET(backend_options), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS | AV_OPT_FLAG_DEPRECATED},
48  {"options", "backend configs (deprecated)",
49  OFFSET(backend_options), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS | AV_OPT_FLAG_DEPRECATED},
50  {"nireq", "number of request",
51  OFFSET(nireq), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS},
52  {"async", "use DNN async inference",
53  OFFSET(async), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS},
54  {"device", "device to run model",
55  OFFSET(device), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS},
56  {NULL}
57 };
58 
59 AVFILTER_DEFINE_CLASS(dnn_base);
60 
61 typedef struct DnnBackendInfo {
62  const size_t offset;
63  union {
64  const AVClass *class;
65  const DNNModule *module;
66  };
68 
70  {0, .class = &dnn_base_class},
71  // Must keep the same order as in DNNOptions, so offset value in incremental order
72 #if CONFIG_LIBTENSORFLOW
73  {offsetof(DnnContext, tf_option), .module = &ff_dnn_backend_tf},
74 #endif
75 #if CONFIG_LIBOPENVINO
76  {offsetof(DnnContext, ov_option), .module = &ff_dnn_backend_openvino},
77 #endif
78 #if CONFIG_LIBTORCH
79  {offsetof(DnnContext, torch_option), .module = &ff_dnn_backend_torch},
80 #endif
81 };
82 
83 const DNNModule *ff_get_dnn_module(DNNBackendType backend_type, void *log_ctx)
84 {
85  for (int i = 1; i < FF_ARRAY_ELEMS(dnn_backend_info_list); i++) {
86  if (dnn_backend_info_list[i].module->type == backend_type)
88  }
89 
90  av_log(log_ctx, AV_LOG_ERROR,
91  "Module backend_type %d is not supported or enabled.\n",
92  backend_type);
93  return NULL;
94 }
95 
97 {
98  for (int i = 0; i < FF_ARRAY_ELEMS(dnn_backend_info_list); i++) {
99  const AVClass **ptr = (const AVClass **) ((char *) ctx + dnn_backend_info_list[i].offset);
100  *ptr = dnn_backend_info_list[i].class;
101  }
102 }
103 
104 void *ff_dnn_child_next(DnnContext *obj, void *prev) {
105  size_t pre_offset;
106 
107  if (!prev) {
108  av_assert0(obj->clazz);
109  return obj;
110  }
111 
112  pre_offset = (char *)prev - (char *)obj;
113  for (int i = 0; i < FF_ARRAY_ELEMS(dnn_backend_info_list) - 1; i++) {
114  if (dnn_backend_info_list[i].offset == pre_offset) {
115  const AVClass **ptr = (const AVClass **) ((char *) obj + dnn_backend_info_list[i + 1].offset);
116  av_assert0(*ptr);
117  return ptr;
118  }
119  }
120 
121  return NULL;
122 }
123 
124 const AVClass *ff_dnn_child_class_iterate_with_mask(void **iter, uint32_t backend_mask)
125 {
126  for (uintptr_t i = (uintptr_t)*iter; i < FF_ARRAY_ELEMS(dnn_backend_info_list); i++) {
127  if (i > 0) {
128  const DNNModule *module = dnn_backend_info_list[i].module;
129 
130  if (!(module->type & backend_mask))
131  continue;
132  }
133 
134  *iter = (void *)(i + 1);
135  return dnn_backend_info_list[i].class;
136  }
137 
138  return NULL;
139 }
140 
ff_dnn_backend_openvino
const DNNModule ff_dnn_backend_openvino
DNNModule::type
DNNBackendType type
Definition: dnn_interface.h:177
opt.h
AVOption
AVOption.
Definition: opt.h:429
DnnContext::clazz
const AVClass * clazz
Definition: dnn_interface.h:144
dnn_base_options
static const AVOption dnn_base_options[]
Definition: dnn_interface.c:39
DnnContext
Definition: dnn_interface.h:143
dnn_backend_info_list
static const DnnBackendInfo dnn_backend_info_list[]
Definition: dnn_interface.c:69
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
filters.h
ff_dnn_init_child_class
void ff_dnn_init_child_class(DnnContext *ctx)
Definition: dnn_interface.c:96
ctx
AVFormatContext * ctx
Definition: movenc.c:49
DnnBackendInfo::offset
const size_t offset
Definition: dnn_interface.c:62
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(dnn_base)
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
DnnBackendInfo::module
const DNNModule * module
Definition: dnn_interface.c:65
NULL
#define NULL
Definition: coverity.c:32
FLAGS
#define FLAGS
Definition: dnn_interface.c:38
DNNBackendType
DNNBackendType
Definition: dnn_interface.h:35
DnnBackendInfo
Definition: dnn_interface.c:61
offset
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
Definition: writing_filters.txt:86
ff_get_dnn_module
const DNNModule * ff_get_dnn_module(DNNBackendType backend_type, void *log_ctx)
Definition: dnn_interface.c:83
ff_dnn_backend_tf
const DNNModule ff_dnn_backend_tf
Definition: dnn_backend_tf.c:886
ff_dnn_child_next
void * ff_dnn_child_next(DnnContext *obj, void *prev)
Definition: dnn_interface.c:104
AV_OPT_FLAG_DEPRECATED
#define AV_OPT_FLAG_DEPRECATED
Set if option is deprecated, users should refer to AVOption.help text for more information.
Definition: opt.h:386
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
ff_dnn_child_class_iterate_with_mask
const AVClass * ff_dnn_child_class_iterate_with_mask(void **iter, uint32_t backend_mask)
Definition: dnn_interface.c:124
ff_dnn_backend_torch
const DNNModule ff_dnn_backend_torch
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
mem.h
DnnBackendInfo::class
const AVClass * class
Definition: dnn_interface.c:64
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition: opt.h:327
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
OFFSET
#define OFFSET(x)
Definition: dnn_interface.c:37
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:276
DNNModule
Definition: dnn_interface.h:175