| @@ -28,6 +28,7 @@ · 27 unmodified lines |
| 28 | 28 | #include "dnn_backend_native_layer_conv2d.h" |
| 29 | 29 | #include "dnn_backend_native_layer_depth2space.h" |
| 30 | 30 | #include "libavformat/avio.h" |
| 31 | +#include "libavformat/internal.h" |
| 31 | 32 | #include "libavutil/avassert.h" |
| 32 | 33 | #include "../internal.h" |
| 33 | 34 | #include "dnn_backend_native_layer_pad.h" |
| @@ -206,53 +207,26 @@ static DNNReturnType load_tf_model(TFModel *tf_model, const char *model_filename · 172 unmodified lines |
| 206 | 207 | |
| 207 | 208 | // prepare the sess config data |
| 208 | 209 | if (tf_model->ctx.options.sess_config != NULL) { |
| 210 | + const char *config; |
| 209 | 211 | /* |
| 210 | 212 | tf_model->ctx.options.sess_config is hex to present the serialized proto |
| 211 | 213 | required by TF_SetConfig below, so we need to first generate the serialized |
| 212 | | − proto in a python script, the following is a script example to generate |
| 213 | | − serialized proto which specifies one GPU, we can change the script to add |
| 214 | | − more options. |
| 215 | | − |
| 216 | | − import tensorflow as tf |
| 217 | | − gpu_options = tf.GPUOptions(visible_device_list='0') |
| 218 | | − config = tf.ConfigProto(gpu_options=gpu_options) |
| 219 | | − s = config.SerializeToString() |
| 220 | | − b = ''.join("%02x" % int(ord(b)) for b in s[::-1]) |
| 221 | | − print('0x%s' % b) |
| 222 | | − |
| 223 | | − the script output looks like: 0xab...cd, and then pass 0xab...cd to sess_config. |
| 214 | + proto in a python script, tools/python/tf_sess_config.py is a script example |
| 215 | + to generate the configs of sess_config. |
| 224 | 216 | */ |
| 225 | | − char tmp[3]; |
| 226 | | − tmp[2] = '\0'; |
| 227 | | − |
| 228 | 217 | if (strncmp(tf_model->ctx.options.sess_config, "0x", 2) != 0) { |
| 229 | 218 | av_log(ctx, AV_LOG_ERROR, "sess_config should start with '0x'\n"); |
| 230 | 219 | return DNN_ERROR; |
| 231 | 220 | } |
| 221 | + config = tf_model->ctx.options.sess_config + 2; |
| 222 | + sess_config_length = ff_hex_to_data(NULL, config); |
| 232 | 223 | |
| 233 | | − sess_config_length = strlen(tf_model->ctx.options.sess_config); |
| 234 | | − if (sess_config_length % 2 != 0) { |
| 235 | | − av_log(ctx, AV_LOG_ERROR, "the length of sess_config is not even (%s), " |
| 236 | | − "please re-generate the config.\n", |
| 237 | | − tf_model->ctx.options.sess_config); |
| 238 | | − return DNN_ERROR; |
| 239 | | − } |
| 240 | | − |
| 241 | | − sess_config_length -= 2; //ignore the first '0x' |
| 242 | | − sess_config_length /= 2; //get the data length in byte |
| 243 | | − |
| 244 | | − sess_config = av_malloc(sess_config_length); |
| 224 | + sess_config = av_mallocz(sess_config_length + AV_INPUT_BUFFER_PADDING_SIZE); |
| 245 | 225 | if (!sess_config) { |
| 246 | 226 | av_log(ctx, AV_LOG_ERROR, "failed to allocate memory\n"); |
| 247 | 227 | return DNN_ERROR; |
| 248 | 228 | } |
| 249 | | − |
| 250 | | − for (int i = 0; i < sess_config_length; i++) { |
| 251 | | − int index = 2 + (sess_config_length - 1 - i) * 2; |
| 252 | | − tmp[0] = tf_model->ctx.options.sess_config[index]; |
| 253 | | − tmp[1] = tf_model->ctx.options.sess_config[index + 1]; |
| 254 | | − sess_config[i] = strtol(tmp, NULL, 16); |
| 255 | | − } |
| 229 | + ff_hex_to_data(sess_config, config); |
| 256 | 230 | } |
| 257 | 231 | |
| 258 | 232 | graph_def = read_graph(model_filename); |