| 368 | }; |
| 369 | |
| 370 | void* Init(TfLiteContext* context, const char* buffer, size_t length) { |
| 371 | auto* op_data = new OpData; |
| 372 | |
| 373 | const TfLiteDelegateParams* params = |
| 374 | reinterpret_cast<const TfLiteDelegateParams*>(buffer); |
| 375 | CHECK(params); |
| 376 | CHECK(params->delegate); |
| 377 | CHECK(params->delegate->data_); |
| 378 | op_data->eager_context = |
| 379 | reinterpret_cast<DelegateData*>(params->delegate->data_) |
| 380 | ->GetEagerContext(); |
| 381 | op_data->buffer_map = reinterpret_cast<DelegateData*>(params->delegate->data_) |
| 382 | ->GetBufferMap(context); |
| 383 | |
| 384 | CHECK(params->output_tensors); |
| 385 | std::set<int> output_set; |
| 386 | for (auto tensor_index : TfLiteIntArrayView(params->output_tensors)) { |
| 387 | op_data->subgraph_outputs.push_back(tensor_index); |
| 388 | output_set.insert(tensor_index); |
| 389 | } |
| 390 | |
| 391 | CHECK(params->input_tensors); |
| 392 | for (auto tensor_index : TfLiteIntArrayView(params->input_tensors)) { |
| 393 | op_data->subgraph_inputs.push_back(tensor_index); |
| 394 | } |
| 395 | |
| 396 | op_data->nodes.reserve(params->nodes_to_replace->size); |
| 397 | |
| 398 | CHECK(params->nodes_to_replace); |
| 399 | tensorflow::Status status; |
| 400 | for (auto node_index : TfLiteIntArrayView(params->nodes_to_replace)) { |
| 401 | TfLiteNode* node; |
| 402 | TfLiteRegistration* reg; |
| 403 | context->GetNodeAndRegistration(context, node_index, &node, ®); |
| 404 | |
| 405 | op_data->nodes.emplace_back(new OpNode(node->inputs, node->outputs)); |
| 406 | OpNode& node_data = *op_data->nodes.back(); |
| 407 | |
| 408 | node_data.set_index(node_index); |
| 409 | node_data.set_name(""); |
| 410 | |
| 411 | status = node_data.InitializeNodeDef(node->custom_initial_data, |
| 412 | node->custom_initial_data_size); |
| 413 | if (!status.ok()) break; |
| 414 | status = node_data.BuildEagerOp(op_data->eager_context); |
| 415 | if (!status.ok()) break; |
| 416 | } |
| 417 | |
| 418 | if (ConvertStatus(context, status) != kTfLiteOk) { |
| 419 | // We can't return an error from this function but ConvertStatus will |
| 420 | // report them and we will stop processing in Prepare() if anything went |
| 421 | // wrong. |
| 422 | return op_data; |
| 423 | } |
| 424 | |
| 425 | // Given a TfLite tensor index, return the OpNode that produces it, |
| 426 | // along with it index into that OpNodes list of outputs. |
| 427 | std::map<int, TensorSource> tflite_tensor_sources; |