// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/base/android/webaudio_media_codec_bridge.h"

#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <vector>

#include "base/android/context_utils.h"
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/basictypes.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "jni/WebAudioMediaCodecBridge_jni.h"
#include "media/base/android/webaudio_media_codec_info.h"


using base::android::AttachCurrentThread;

namespace media {

void WebAudioMediaCodecBridge::RunWebAudioMediaCodec(
    base::SharedMemoryHandle encoded_audio_handle,
    base::FileDescriptor pcm_output,
    uint32_t data_size,
    base::Closure on_decode_finished_cb) {
  WebAudioMediaCodecBridge bridge(
      encoded_audio_handle, pcm_output, data_size);

  bridge.DecodeInMemoryAudioFile();
  on_decode_finished_cb.Run();
}

WebAudioMediaCodecBridge::WebAudioMediaCodecBridge(
    base::SharedMemoryHandle encoded_audio_handle,
    base::FileDescriptor pcm_output,
    uint32_t data_size)
    : encoded_audio_handle_(encoded_audio_handle),
      pcm_output_(pcm_output.fd),
      data_size_(data_size) {
  DVLOG(1) << "WebAudioMediaCodecBridge start **********************"
           << " output fd = " << pcm_output.fd;
}

WebAudioMediaCodecBridge::~WebAudioMediaCodecBridge() {
  if (close(pcm_output_)) {
    DVLOG(1) << "Couldn't close output fd " << pcm_output_
             << ": " << strerror(errno);
  }
}

int WebAudioMediaCodecBridge::SaveEncodedAudioToFile(
    JNIEnv* env,
    jobject context) {
  // Create a temporary file where we can save the encoded audio data.
  std::string temporaryFile =
      base::android::ConvertJavaStringToUTF8(
          env,
          Java_WebAudioMediaCodecBridge_createTempFile(env, context).obj());

  // Open the file and unlink it, so that it will be actually removed
  // when we close the file.
  base::ScopedFD fd(open(temporaryFile.c_str(), O_RDWR));
  if (unlink(temporaryFile.c_str())) {
    VLOG(0) << "Couldn't unlink temp file " << temporaryFile
            << ": " << strerror(errno);
  }

  if (!fd.is_valid()) {
    return -1;
  }

  // Create a local mapping of the shared memory containing the
  // encoded audio data, and save the contents to the temporary file.
  base::SharedMemory encoded_data(encoded_audio_handle_, true);

  if (!encoded_data.Map(data_size_)) {
    VLOG(0) << "Unable to map shared memory!";
    return -1;
  }

  if (static_cast<uint32_t>(write(fd.get(), encoded_data.memory(), data_size_))
      != data_size_) {
    VLOG(0) << "Failed to write all audio data to temp file!";
    return -1;
  }

  lseek(fd.get(), 0, SEEK_SET);

  return fd.release();
}

bool WebAudioMediaCodecBridge::DecodeInMemoryAudioFile() {
  JNIEnv* env = AttachCurrentThread();
  CHECK(env);

  jobject context = base::android::GetApplicationContext();

  int sourceFd = SaveEncodedAudioToFile(env, context);

  if (sourceFd < 0)
    return false;

  jboolean decoded = Java_WebAudioMediaCodecBridge_decodeAudioFile(
      env,
      context,
      reinterpret_cast<intptr_t>(this),
      sourceFd,
      data_size_);

  close(sourceFd);

  DVLOG(1) << "decoded = " << (decoded ? "true" : "false");

  return decoded;
}

void WebAudioMediaCodecBridge::InitializeDestination(
    JNIEnv* env,
    const JavaParamRef<jobject>& /*java object*/,
    jint channel_count,
    jint sample_rate,
    jlong duration_microsec) {
  // Send information about this audio file: number of channels,
  // sample rate (Hz), and the number of frames.
  struct WebAudioMediaCodecInfo info = {
    static_cast<unsigned long>(channel_count),
    static_cast<unsigned long>(sample_rate),
    // The number of frames is the duration of the file
    // (in microseconds) times the sample rate.
    static_cast<unsigned long>(
        0.5 + (duration_microsec * 0.000001 *
               sample_rate))
  };

  DVLOG(1) << "InitializeDestination:"
           << "  channel count = " << channel_count
           << "  rate = " << sample_rate
           << "  duration = " << duration_microsec << " microsec";

  HANDLE_EINTR(write(pcm_output_, &info, sizeof(info)));
}

void WebAudioMediaCodecBridge::OnChunkDecoded(
    JNIEnv* env,
    const JavaParamRef<jobject>& /*java object*/,
    const JavaParamRef<jobject>& buf,
    jint buf_size,
    jint input_channel_count,
    jint output_channel_count) {
  if (buf_size <= 0 || !buf)
    return;

  int8_t* buffer =
      static_cast<int8_t*>(env->GetDirectBufferAddress(buf));
  size_t count = static_cast<size_t>(buf_size);
  std::vector<int16_t> decoded_data;

  if (input_channel_count == 1 && output_channel_count == 2) {
    // See crbug.com/266006.  The file has one channel, but the
    // decoder decided to return two channels.  To be consistent with
    // the number of channels in the file, only send one channel (the
    // first).
    int16_t* data = static_cast<int16_t*>(env->GetDirectBufferAddress(buf));
    int frame_count  = buf_size / sizeof(*data) / 2;

    decoded_data.resize(frame_count);
    for (int k = 0; k < frame_count; ++k) {
      decoded_data[k] = *data;
      data += 2;
    }
    buffer = reinterpret_cast<int8_t*>(decoded_data.data());
    DCHECK(buffer);
    count = frame_count * sizeof(*data);
  }

  // Write out the data to the pipe in small chunks if necessary.
  while (count > 0) {
    int bytes_to_write = (count >= PIPE_BUF) ? PIPE_BUF : count;
    ssize_t bytes_written = HANDLE_EINTR(write(pcm_output_,
                                               buffer,
                                               bytes_to_write));
    if (bytes_written == -1)
      break;
    count -= bytes_written;
    buffer += bytes_written;
  }
}

bool WebAudioMediaCodecBridge::RegisterWebAudioMediaCodecBridge(JNIEnv* env) {
  return RegisterNativesImpl(env);
}

} // namespace
