Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1-only */
2 : /**
3 : * GStreamer / NNStreamer tensor_decoder subplugin, "Flatbuffer"
4 : * Copyright (C) 2020 Gichan Jang <gichan2.jang@samsung.com>
5 : */
6 : /**
7 : * @file tensordec-flatbuf.cc
8 : * @date 26 Feb 2020
9 : * @brief NNStreamer tensor-decoder subplugin, "flatbuffer",
10 : * which converts tensor or tensors to flatbuffer byte stream.
11 : *
12 : * @see https://github.com/nnstreamer/nnstreamer
13 : * @author Gichan Jang <gichan2.jang@samsung.com>
14 : * @bug No known bugs except for NYI items
15 : *
16 : */
17 :
18 : #include <glib.h>
19 : #include <gst/gstinfo.h>
20 : #include <iostream>
21 : #include <nnstreamer_generated.h> /* Generated by `flatc`. */
22 : #include <nnstreamer_log.h>
23 : #include <nnstreamer_plugin_api.h>
24 : #include <nnstreamer_plugin_api_decoder.h>
25 : #include <nnstreamer_util.h>
26 : #include <typeinfo>
27 : #include "../extra/nnstreamer_flatbuf.h"
28 : #include "tensordecutil.h"
29 :
30 : namespace nnstreamer
31 : {
32 : namespace flatbuf
33 : {
34 :
35 : #ifdef __cplusplus
36 : extern "C" {
37 : #endif /* __cplusplus */
38 : void init_fbd (void) __attribute__ ((constructor));
39 : void fini_fbd (void) __attribute__ ((destructor));
40 : #ifdef __cplusplus
41 : }
42 : #endif /* __cplusplus */
43 :
44 : /** @brief tensordec-plugin's GstTensorDecoderDef callback */
45 : static int
46 21 : fbd_init (void **pdata)
47 : {
48 21 : *pdata = NULL;
49 21 : return TRUE;
50 : }
51 :
52 : /** @brief tensordec-plugin's GstTensorDecoderDef callback */
53 : static void
54 21 : fbd_exit (void **pdata)
55 : {
56 : UNUSED (pdata);
57 21 : return;
58 : }
59 :
60 : /** @brief tensordec-plugin's GstTensorDecoderDef callback */
61 : static int
62 0 : fbd_setOption (void **pdata, int opNum, const char *param)
63 : {
64 : UNUSED (pdata);
65 : UNUSED (opNum);
66 : UNUSED (param);
67 0 : return TRUE;
68 : }
69 :
70 : /** @brief tensordec-plugin's GstTensorDecoderDef callback */
71 : static GstCaps *
72 148 : fbd_getOutCaps (void **pdata, const GstTensorsConfig *config)
73 : {
74 : GstCaps *caps;
75 : UNUSED (pdata);
76 :
77 148 : caps = gst_caps_from_string (GST_FLATBUF_TENSOR_CAP_DEFAULT);
78 148 : setFramerateFromConfig (caps, config);
79 148 : return caps;
80 : }
81 :
82 : /** @brief tensordec-plugin's GstTensorDecoderDef callback */
83 : static GstFlowReturn
84 84 : fbd_decode (void **pdata, const GstTensorsConfig *config,
85 : const GstTensorMemory *input, GstBuffer *outbuf)
86 : {
87 : Tensor_type type;
88 : Tensor_format format;
89 : GstMapInfo out_info;
90 : GstMemory *out_mem;
91 : guint i, num_tensors;
92 : flatbuffers::uoffset_t fb_size;
93 84 : flatbuffers::FlatBufferBuilder builder;
94 84 : std::vector<flatbuffers::Offset<Tensor>> tensor_vector;
95 84 : flatbuffers::Offset<flatbuffers::Vector<uint32_t>> dim;
96 84 : flatbuffers::Offset<flatbuffers::String> tensor_name;
97 84 : flatbuffers::Offset<flatbuffers::Vector<unsigned char>> input_vector;
98 84 : flatbuffers::Offset<Tensor> tensor;
99 84 : flatbuffers::Offset<Tensors> tensors;
100 84 : frame_rate fr;
101 : gboolean is_flexible;
102 : GstTensorMetaInfo meta;
103 : GstTensorInfo *_info;
104 :
105 : UNUSED (pdata);
106 :
107 84 : if (!config || !input || !outbuf) {
108 3 : ml_loge ("NULL parameter is passed to tensor_decoder::flatbuf");
109 3 : return GST_FLOW_ERROR;
110 : }
111 :
112 81 : is_flexible = gst_tensors_config_is_flexible (config);
113 :
114 81 : num_tensors = config->info.num_tensors;
115 81 : fr = frame_rate (config->rate_n, config->rate_d);
116 81 : format = (Tensor_format) config->info.format;
117 : /* Fill the info in tensor and puth to tensor vector */
118 187 : for (i = 0; i < num_tensors; i++) {
119 : unsigned char *tmp_buf;
120 :
121 106 : _info = gst_tensors_info_get_nth_info ((GstTensorsInfo *) &config->info, i);
122 :
123 106 : if (is_flexible) {
124 9 : gst_tensor_meta_info_parse_header (&meta, input[i].data);
125 9 : gst_tensor_meta_info_convert (&meta, _info);
126 : }
127 :
128 106 : dim = builder.CreateVector (_info->dimension, NNS_TENSOR_RANK_LIMIT);
129 :
130 106 : if (_info->name == NULL)
131 105 : tensor_name = builder.CreateString ("");
132 : else
133 1 : tensor_name = builder.CreateString (_info->name);
134 :
135 106 : type = (Tensor_type) _info->type;
136 :
137 : /* Create the vector first, and fill in data later */
138 : /** @todo Consider to remove memcpy */
139 106 : input_vector = builder.CreateUninitializedVector<unsigned char> (input[i].size, &tmp_buf);
140 106 : memcpy (tmp_buf, input[i].data, input[i].size);
141 :
142 106 : tensor = CreateTensor (builder, tensor_name, type, dim, input_vector);
143 106 : tensor_vector.push_back (tensor);
144 : }
145 :
146 81 : tensors = CreateTensors (
147 : builder, num_tensors, &fr, builder.CreateVector (tensor_vector), format);
148 :
149 : /* Serialize the data.*/
150 81 : builder.Finish (tensors);
151 81 : fb_size = builder.GetSize ();
152 :
153 81 : if (gst_buffer_get_size (outbuf) == 0) {
154 81 : out_mem = gst_allocator_alloc (NULL, fb_size, NULL);
155 : } else {
156 0 : if (gst_buffer_get_size (outbuf) < fb_size) {
157 0 : gst_buffer_set_size (outbuf, fb_size);
158 : }
159 0 : out_mem = gst_buffer_get_all_memory (outbuf);
160 : }
161 :
162 81 : if (!gst_memory_map (out_mem, &out_info, GST_MAP_WRITE)) {
163 0 : gst_memory_unref (out_mem);
164 0 : nns_loge ("Cannot map gst memory (tensor decoder flatbuf)\n");
165 0 : return GST_FLOW_ERROR;
166 : }
167 :
168 81 : memcpy (out_info.data, builder.GetBufferPointer (), fb_size);
169 :
170 81 : gst_memory_unmap (out_mem, &out_info);
171 :
172 81 : if (gst_buffer_get_size (outbuf) == 0)
173 81 : gst_buffer_append_memory (outbuf, out_mem);
174 : else
175 0 : gst_buffer_replace_all_memory (outbuf, out_mem);
176 :
177 81 : return GST_FLOW_OK;
178 84 : }
179 :
180 : static gchar decoder_subplugin_flatbuf[] = "flatbuf";
181 :
182 : /** @brief flatbuffer tensordec-plugin GstTensorDecoderDef instance */
183 : static GstTensorDecoderDef flatBuf = { .modename = decoder_subplugin_flatbuf,
184 : .init = fbd_init,
185 : .exit = fbd_exit,
186 : .setOption = fbd_setOption,
187 : .getOutCaps = fbd_getOutCaps,
188 : .decode = fbd_decode,
189 : .getTransformSize = NULL };
190 :
191 : #ifdef __cplusplus
192 : extern "C" {
193 : #endif /* __cplusplus */
194 :
195 : /** @brief Initialize this object for tensordec-plugin */
196 : void
197 14 : init_fbd (void)
198 : {
199 14 : nnstreamer_decoder_probe (&flatBuf);
200 14 : }
201 :
202 : /** @brief Destruct this object for tensordec-plugin */
203 : void
204 14 : fini_fbd (void)
205 : {
206 14 : nnstreamer_decoder_exit (flatBuf.modename);
207 14 : }
208 : #ifdef __cplusplus
209 : }
210 : #endif /* __cplusplus */
211 :
212 : }; /* Namespace flatbuf */
213 : }; /* Namespace nnstreamer */
|