void Compute()

in tensorflow_io/core/kernels/audio_video_flac_kernels.cc [400:530]


  void Compute(OpKernelContext* context) override {
    const Tensor* input_tensor;
    OP_REQUIRES_OK(context, context->input("input", &input_tensor));

    const Tensor* rate_tensor;
    OP_REQUIRES_OK(context, context->input("rate", &rate_tensor));

    const int64 rate = rate_tensor->scalar<int64>()();
    const int64 samples = input_tensor->shape().dim_size(0);
    const int64 channels = input_tensor->shape().dim_size(1);

    int64 bytes_per_sample;
    switch (input_tensor->dtype()) {
      case DT_UINT8:
        bytes_per_sample = 1;
        break;
      case DT_INT16:
        bytes_per_sample = 2;
        break;
      case DT_INT32:
        bytes_per_sample = 3;
        break;
      default:
        OP_REQUIRES(context, false,
                    errors::InvalidArgument(
                        "data type ", DataTypeString(input_tensor->dtype()),
                        " not supported"));
    }

    std::unique_ptr<FLAC__StreamEncoder, void (*)(FLAC__StreamEncoder*)>
        encoder(nullptr, [](FLAC__StreamEncoder* p) {
          if (p != nullptr) {
            FLAC__stream_encoder_delete(p);
          }
        });
    encoder.reset(FLAC__stream_encoder_new());

    FLAC__bool ok;

    ok = FLAC__stream_encoder_set_verify(encoder.get(), true);
    OP_REQUIRES(context, ok, errors::InvalidArgument("unable to set verify"));

    // TODO: compression level could be a input tensor node passed in.
    // ok = FLAC__stream_encoder_set_compression_level(encoder.get(), 5);
    // OP_REQUIRES(context, ok, errors::InvalidArgument("unable to set
    // compression level"));

    ok = FLAC__stream_encoder_set_channels(encoder.get(), channels);
    OP_REQUIRES(context, ok, errors::InvalidArgument("unable to set channels"));

    ok = FLAC__stream_encoder_set_bits_per_sample(encoder.get(),
                                                  bytes_per_sample * 8);
    OP_REQUIRES(context, ok,
                errors::InvalidArgument("unable to set bits per sample"));

    ok = FLAC__stream_encoder_set_sample_rate(encoder.get(), rate);
    OP_REQUIRES(context, ok, errors::InvalidArgument("unable to set rate"));

    ok =
        FLAC__stream_encoder_set_total_samples_estimate(encoder.get(), samples);
    OP_REQUIRES(
        context, ok,
        errors::InvalidArgument("unable to set total samples estimate"));

    Tensor* output_tensor = nullptr;
    OP_REQUIRES_OK(
        context, context->allocate_output(0, TensorShape({}), &output_tensor));

    tstring& output = output_tensor->scalar<tstring>()();

    std::unique_ptr<FlacStreamEncoder> stream_encoder;
    stream_encoder.reset(new FlacStreamEncoder(&output));

    FLAC__StreamEncoderInitStatus s = FLAC__stream_encoder_init_stream(
        encoder.get(), FlacStreamEncoder::WriteCallback,
        FlacStreamEncoder::SeekCallback, FlacStreamEncoder::TellCallback,
        FlacStreamEncoder::MetadataCallback, stream_encoder.get());
    OP_REQUIRES(context, (s == FLAC__STREAM_ENCODER_INIT_STATUS_OK),
                errors::InvalidArgument("unable to initialize stream: ", s));

    std::unique_ptr<FLAC__int32[]> pcm(
        new FLAC__int32[FlacStreamEncoder::kSampleBufferCount * channels]);

    int64 count = 0;
    while (count < samples) {
      int64 chunk = (count + FlacStreamEncoder::kSampleBufferCount < samples)
                        ? (FlacStreamEncoder::kSampleBufferCount)
                        : (samples - count);
      switch (input_tensor->dtype()) {
        case DT_UINT8:
          // convert to signed by sub 0x80
          for (int64 i = 0; i < chunk; i++) {
            for (int64 c = 0; c < channels; c++) {
              pcm.get()[i * channels + c] =
                  static_cast<int32>(
                      input_tensor->flat<uint8>()((count + i) * channels + c)) -
                  0x80;
            }
          }
          break;
        case DT_INT16:
          for (int64 i = 0; i < chunk; i++) {
            for (int64 c = 0; c < channels; c++) {
              pcm.get()[i * channels + c] =
                  input_tensor->flat<int16>()((count + i) * channels + c);
            }
          }
          break;
        case DT_INT32:
          // right shift 8 bit as int32 was filled
          for (int64 i = 0; i < chunk; i++) {
            for (int64 c = 0; c < channels; c++) {
              pcm.get()[i * channels + c] =
                  (input_tensor->flat<int32>()((count + i) * channels + c) >>
                   8);
            }
          }
          break;
      }
      ok = FLAC__stream_encoder_process_interleaved(encoder.get(), pcm.get(),
                                                    chunk);
      OP_REQUIRES(
          context, ok,
          errors::InvalidArgument("unable to process interleaved stream"));
      count += chunk;
    }

    ok = FLAC__stream_encoder_finish(encoder.get());
    OP_REQUIRES(context, ok,
                errors::InvalidArgument("unable to finish stream"));
  }