* Decoding implementation, shared across V1 and V2 ops. Creates a new * output in the context. */
| 42 | * output in the context. |
| 43 | */ |
| 44 | void Decode(OpKernelContext* context, |
| 45 | const tensorflow::StringPiece& file_contents, |
| 46 | const string& file_format, const int32 samples_per_second, |
| 47 | const int32 channel_count, const string& stream) { |
| 48 | // Write the input data to a temp file. |
| 49 | const string temp_filename = io::GetTempFilename(file_format); |
| 50 | OP_REQUIRES_OK(context, WriteFile(temp_filename, file_contents)); |
| 51 | FileDeleter deleter(temp_filename); |
| 52 | |
| 53 | // Run FFmpeg on the data and verify results. |
| 54 | std::vector<float> output_samples; |
| 55 | Status result = |
| 56 | ffmpeg::ReadAudioFile(temp_filename, file_format, samples_per_second, |
| 57 | channel_count, stream, &output_samples); |
| 58 | if (result.code() == error::Code::NOT_FOUND) { |
| 59 | OP_REQUIRES( |
| 60 | context, result.ok(), |
| 61 | errors::Unavailable("FFmpeg must be installed to run this op. FFmpeg " |
| 62 | "can be found at http://www.ffmpeg.org.")); |
| 63 | } else if (result.code() == error::UNKNOWN) { |
| 64 | LOG(ERROR) << "Ffmpeg failed with error '" << result.error_message() |
| 65 | << "'. Returning empty tensor."; |
| 66 | Tensor* output = nullptr; |
| 67 | OP_REQUIRES_OK(context, |
| 68 | context->allocate_output(0, TensorShape({0, 0}), &output)); |
| 69 | return; |
| 70 | } else { |
| 71 | OP_REQUIRES_OK(context, result); |
| 72 | } |
| 73 | OP_REQUIRES(context, !output_samples.empty(), |
| 74 | errors::Unknown("No output created by FFmpeg.")); |
| 75 | OP_REQUIRES( |
| 76 | context, output_samples.size() % channel_count == 0, |
| 77 | errors::Unknown("FFmpeg created non-integer number of audio frames.")); |
| 78 | |
| 79 | // Copy the output data to the output Tensor. |
| 80 | Tensor* output = nullptr; |
| 81 | const int64 frame_count = output_samples.size() / channel_count; |
| 82 | OP_REQUIRES_OK(context, |
| 83 | context->allocate_output( |
| 84 | 0, TensorShape({frame_count, channel_count}), &output)); |
| 85 | auto matrix = output->tensor<float, 2>(); |
| 86 | for (int32 frame = 0; frame < frame_count; ++frame) { |
| 87 | for (int32 channel = 0; channel < channel_count; ++channel) { |
| 88 | matrix(frame, channel) = output_samples[frame * channel_count + channel]; |
| 89 | } |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | } // namespace |
| 94 |
no test coverage detected