| 36 | explicit DecodeVideoOp(OpKernelConstruction* context) : OpKernel(context) {} |
| 37 | |
| 38 | void Compute(OpKernelContext* context) override { |
| 39 | OP_REQUIRES( |
| 40 | context, context->num_inputs() == 1, |
| 41 | errors::InvalidArgument("DecodeVideo requires exactly 1 input.")); |
| 42 | const Tensor& contents_tensor = context->input(0); |
| 43 | |
| 44 | OP_REQUIRES(context, TensorShapeUtils::IsScalar(contents_tensor.shape()), |
| 45 | errors::InvalidArgument( |
| 46 | "contents must be a rank-0 tensor but got shape ", |
| 47 | contents_tensor.shape().DebugString())); |
| 48 | const tensorflow::StringPiece contents = |
| 49 | contents_tensor.scalar<tstring>()(); |
| 50 | |
| 51 | // Write the input data to a temp file. |
| 52 | string extension; |
| 53 | const string temp_filename = io::GetTempFilename(extension); |
| 54 | OP_REQUIRES_OK(context, WriteFile(temp_filename, contents)); |
| 55 | FileDeleter deleter(temp_filename); |
| 56 | |
| 57 | uint32 width = 0; |
| 58 | uint32 height = 0; |
| 59 | uint32 frames = 0; |
| 60 | |
| 61 | // Run FFmpeg on the data and verify results. |
| 62 | std::vector<uint8> output_data; |
| 63 | const Status result = ffmpeg::ReadVideoFile(temp_filename, &output_data, |
| 64 | &width, &height, &frames); |
| 65 | if (result.code() == error::Code::NOT_FOUND) { |
| 66 | OP_REQUIRES( |
| 67 | context, result.ok(), |
| 68 | errors::Unavailable("FFmpeg must be installed to run this op. FFmpeg " |
| 69 | "can be found at http://www.ffmpeg.org.")); |
| 70 | } else if (result.code() == error::UNKNOWN) { |
| 71 | LOG(ERROR) << "Ffmpeg failed with error '" << result.error_message() |
| 72 | << "'. Returning empty tensor."; |
| 73 | Tensor* output = nullptr; |
| 74 | OP_REQUIRES_OK(context, |
| 75 | context->allocate_output(0, TensorShape({0, 0}), &output)); |
| 76 | return; |
| 77 | } else { |
| 78 | OP_REQUIRES_OK(context, result); |
| 79 | } |
| 80 | OP_REQUIRES(context, !output_data.empty(), |
| 81 | errors::Unknown("No output created by FFmpeg.")); |
| 82 | OP_REQUIRES( |
| 83 | context, output_data.size() == (frames * height * width * 3), |
| 84 | errors::Unknown("Output created by FFmpeg [", output_data.size(), |
| 85 | "] does not match description [", frames, ", ", height, |
| 86 | ", ", width, ", 3]")); |
| 87 | Tensor* output = nullptr; |
| 88 | OP_REQUIRES_OK(context, |
| 89 | context->allocate_output( |
| 90 | 0, TensorShape({frames, height, width, 3}), &output)); |
| 91 | auto output_flat = output->flat<uint8>(); |
| 92 | std::copy_n(output_data.begin(), output_data.size(), &output_flat(0)); |
| 93 | } |
| 94 | }; |
| 95 |
nothing calls this directly
no test coverage detected