// 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/audio/win/audio_low_latency_input_win.h"

#include <mmsystem.h>
#include <stddef.h>
#include <stdint.h>
#include <windows.h>

#include <memory>

#include "base/bind.h"
#include "base/environment.h"
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/test/test_timeouts.h"
#include "base/win/scoped_com_initializer.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/audio_device_info_accessor_for_tests.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_manager.h"
#include "media/audio/audio_unittest_util.h"
#include "media/audio/test_audio_thread.h"
#include "media/audio/win/core_audio_util_win.h"
#include "media/base/seekable_buffer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::_;
using ::testing::AnyNumber;
using ::testing::AtLeast;
using ::testing::Gt;
using ::testing::NotNull;

namespace media {

namespace {

constexpr SampleFormat kSampleFormat = kSampleFormatS16;

void LogCallbackDummy(const std::string& /* message */) {}

}  // namespace

ACTION_P4(CheckCountAndPostQuitTask, count, limit, task_runner, quit_closure) {
  if (++*count >= limit)
    task_runner->PostTask(FROM_HERE, quit_closure);
}

class MockAudioInputCallback : public AudioInputStream::AudioInputCallback {
 public:
  MOCK_METHOD3(OnData,
               void(const AudioBus* src,
                    base::TimeTicks capture_time,
                    double volume));
  MOCK_METHOD0(OnError, void());
};

class FakeAudioInputCallback : public AudioInputStream::AudioInputCallback {
 public:
  FakeAudioInputCallback()
      : num_received_audio_frames_(0),
        data_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                    base::WaitableEvent::InitialState::NOT_SIGNALED),
        error_(false) {}

  bool error() const { return error_; }
  int num_received_audio_frames() const { return num_received_audio_frames_; }

  // Waits until OnData() is called on another thread.
  void WaitForData() { data_event_.Wait(); }

  void OnData(const AudioBus* src,
              base::TimeTicks capture_time,
              double volume) override {
    EXPECT_GE(capture_time, base::TimeTicks());
    num_received_audio_frames_ += src->frames();
    data_event_.Signal();
  }

  void OnError() override { error_ = true; }

 private:
  int num_received_audio_frames_;
  base::WaitableEvent data_event_;
  bool error_;

  DISALLOW_COPY_AND_ASSIGN(FakeAudioInputCallback);
};

// This audio sink implementation should be used for manual tests only since
// the recorded data is stored on a raw binary data file.
class WriteToFileAudioSink : public AudioInputStream::AudioInputCallback {
 public:
  // Allocate space for ~10 seconds of data @ 48kHz in stereo:
  // 2 bytes per sample, 2 channels, 10ms @ 48kHz, 10 seconds <=> 1920000 bytes.
  static const size_t kMaxBufferSize = 2 * 2 * 480 * 100 * 10;

  explicit WriteToFileAudioSink(const char* file_name)
      : buffer_(0, kMaxBufferSize), bytes_to_write_(0) {
    base::FilePath file_path;
    EXPECT_TRUE(base::PathService::Get(base::DIR_EXE, &file_path));
    file_path = file_path.AppendASCII(file_name);
    binary_file_ = base::OpenFile(file_path, "wb");
    DLOG_IF(ERROR, !binary_file_) << "Failed to open binary PCM data file.";
    VLOG(0) << ">> Output file: " << file_path.value() << " has been created.";
  }

  ~WriteToFileAudioSink() override {
    size_t bytes_written = 0;
    while (bytes_written < bytes_to_write_) {
      const uint8_t* chunk;
      int chunk_size;

      // Stop writing if no more data is available.
      if (!buffer_.GetCurrentChunk(&chunk, &chunk_size))
        break;

      // Write recorded data chunk to the file and prepare for next chunk.
      fwrite(chunk, 1, chunk_size, binary_file_);
      buffer_.Seek(chunk_size);
      bytes_written += chunk_size;
    }
    base::CloseFile(binary_file_);
  }

  // AudioInputStream::AudioInputCallback implementation.
  void OnData(const AudioBus* src,
              base::TimeTicks capture_time,
              double volume) override {
    const int num_samples = src->frames() * src->channels();
    auto interleaved = std::make_unique<int16_t[]>(num_samples);
    const int bytes_per_sample = sizeof(interleaved[0]);
    src->ToInterleaved<SignedInt16SampleTypeTraits>(src->frames(),
                                                    interleaved.get());

    // Store data data in a temporary buffer to avoid making blocking
    // fwrite() calls in the audio callback. The complete buffer will be
    // written to file in the destructor.
    const int size = bytes_per_sample * num_samples;
    if (buffer_.Append((const uint8_t*)interleaved.get(), size)) {
      bytes_to_write_ += size;
    }
  }

  void OnError() override {}

 private:
  media::SeekableBuffer buffer_;
  FILE* binary_file_;
  size_t bytes_to_write_;
};

static bool HasCoreAudioAndInputDevices(AudioManager* audio_man) {
  // The low-latency (WASAPI-based) version requires Windows Vista or higher.
  // TODO(henrika): note that we use Wave today to query the number of
  // existing input devices.
  return CoreAudioUtil::IsSupported() &&
         AudioDeviceInfoAccessorForTests(audio_man).HasAudioInputDevices();
}

// Convenience method which creates a default AudioInputStream object but
// also allows the user to modify the default settings.
class AudioInputStreamWrapper {
 public:
  explicit AudioInputStreamWrapper(AudioManager* audio_manager,
                                   bool use_voice_processing)
      : audio_man_(audio_manager) {
    EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters(
        AudioDeviceDescription::kDefaultDeviceId, false, &default_params_)));
    EXPECT_EQ(format(), AudioParameters::AUDIO_PCM_LOW_LATENCY);
    if (use_voice_processing) {
      default_params_.set_effects(default_params_.effects() |
                                  AudioParameters::ECHO_CANCELLER);
    }
    frames_per_buffer_ = default_params_.frames_per_buffer();
  }

  AudioInputStreamWrapper(AudioManager* audio_manager,
                          const AudioParameters& default_params)
      : audio_man_(audio_manager), default_params_(default_params) {
    EXPECT_EQ(format(), AudioParameters::AUDIO_PCM_LOW_LATENCY);
    frames_per_buffer_ = default_params_.frames_per_buffer();
  }

  ~AudioInputStreamWrapper() {}

  // Creates AudioInputStream object using default parameters.
  AudioInputStream* Create() { return CreateInputStream(); }

  // Creates AudioInputStream object using non-default parameters where the
  // frame size is modified.
  AudioInputStream* Create(int frames_per_buffer) {
    frames_per_buffer_ = frames_per_buffer;
    return CreateInputStream();
  }

  AudioParameters::Format format() const { return default_params_.format(); }
  int channels() const {
    return ChannelLayoutToChannelCount(default_params_.channel_layout());
  }
  int sample_rate() const { return default_params_.sample_rate(); }
  int frames_per_buffer() const { return frames_per_buffer_; }

 private:
  AudioInputStream* CreateInputStream() {
    AudioParameters params = default_params_;
    params.set_frames_per_buffer(frames_per_buffer_);
    AudioInputStream* ais = audio_man_->MakeAudioInputStream(
        params, AudioDeviceDescription::kDefaultDeviceId,
        base::BindRepeating(&LogCallbackDummy));
    EXPECT_TRUE(ais);
    return ais;
  }

  AudioManager* audio_man_;
  AudioParameters default_params_;
  int frames_per_buffer_;
};

// Convenience method which creates a default AudioInputStream object.
static AudioInputStream* CreateDefaultAudioInputStream(
    AudioManager* audio_manager,
    bool use_voice_processing) {
  AudioInputStreamWrapper aisw(audio_manager, use_voice_processing);
  AudioInputStream* ais = aisw.Create();
  return ais;
}

class ScopedAudioInputStream {
 public:
  explicit ScopedAudioInputStream(AudioInputStream* stream) : stream_(stream) {}

  ~ScopedAudioInputStream() {
    if (stream_)
      stream_->Close();
  }

  void Close() {
    if (stream_)
      stream_->Close();
    stream_ = nullptr;
  }

  AudioInputStream* operator->() { return stream_; }

  AudioInputStream* get() const { return stream_; }

  void Reset(AudioInputStream* new_stream) {
    Close();
    stream_ = new_stream;
  }

 private:
  AudioInputStream* stream_;

  DISALLOW_COPY_AND_ASSIGN(ScopedAudioInputStream);
};

// The test class. The boolean parameter specifies if voice processing should be
// used.
class WinAudioInputTest : public ::testing::TestWithParam<bool> {
 public:
  WinAudioInputTest() {
    audio_manager_ =
        AudioManager::CreateForTesting(std::make_unique<TestAudioThread>());
    base::RunLoop().RunUntilIdle();
  }
  ~WinAudioInputTest() override { audio_manager_->Shutdown(); }

 protected:
  base::MessageLoop message_loop_;
  std::unique_ptr<AudioManager> audio_manager_;
};

// Verify that we can retrieve the current hardware/mixing sample rate
// for all available input devices.
TEST_F(WinAudioInputTest, WASAPIAudioInputStreamHardwareSampleRate) {
  ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));

  // Retrieve a list of all available input devices.
  media::AudioDeviceDescriptions device_descriptions;
  AudioDeviceInfoAccessorForTests(audio_manager_.get())
      .GetAudioInputDeviceDescriptions(&device_descriptions);

  // Scan all available input devices and repeat the same test for all of them.
  for (const auto& device : device_descriptions) {
    // Retrieve the hardware sample rate given a specified audio input device.
    AudioParameters params;
    ASSERT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters(
        device.unique_id, false, &params)));
    EXPECT_GE(params.sample_rate(), 0);
  }
}

// Test Create(), Close() calling sequence.
TEST_P(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) {
  ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
  ScopedAudioInputStream ais(
      CreateDefaultAudioInputStream(audio_manager_.get(), GetParam()));
  ais.Close();
}

// Test Open(), Close() calling sequence.
TEST_P(WinAudioInputTest, WASAPIAudioInputStreamOpenAndClose) {
  ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
  ScopedAudioInputStream ais(
      CreateDefaultAudioInputStream(audio_manager_.get(), GetParam()));
  EXPECT_TRUE(ais->Open());
  ais.Close();
}

// Test Open(), Start(), Close() calling sequence.
TEST_P(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) {
  ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
  ScopedAudioInputStream ais(
      CreateDefaultAudioInputStream(audio_manager_.get(), GetParam()));
  EXPECT_TRUE(ais->Open());
  MockAudioInputCallback sink;
  ais->Start(&sink);
  ais.Close();
}

// Test Open(), Start(), Stop(), Close() calling sequence.
TEST_P(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) {
  ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
  ScopedAudioInputStream ais(
      CreateDefaultAudioInputStream(audio_manager_.get(), GetParam()));
  EXPECT_TRUE(ais->Open());
  MockAudioInputCallback sink;
  ais->Start(&sink);
  ais->Stop();
  ais.Close();
}

// Test some additional calling sequences.
TEST_P(WinAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) {
  ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
  ScopedAudioInputStream ais(
      CreateDefaultAudioInputStream(audio_manager_.get(), GetParam()));

  // Open(), Open() should fail the second time.
  EXPECT_TRUE(ais->Open());
  EXPECT_FALSE(ais->Open());

  FakeAudioInputCallback sink;

  // Start(), Start() is a valid calling sequence (second call does nothing).
  ais->Start(&sink);
  sink.WaitForData();
  ais->Start(&sink);
  // Ensure the stream is still started.
  sink.WaitForData();
  sink.WaitForData();

  // Stop(), Stop() is a valid calling sequence (second call does nothing).
  ais->Stop();
  ais->Stop();
  ais.Close();
}

TEST_P(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) {
  ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));

  int count = 0;

  // 10 ms packet size.

  // Create default WASAPI input stream which records in stereo using
  // the shared mixing rate. The default buffer size is 10ms.
  AudioInputStreamWrapper aisw(audio_manager_.get(), GetParam());
  ScopedAudioInputStream ais(aisw.Create());
  EXPECT_TRUE(ais->Open());

  MockAudioInputCallback sink;

  // Derive the expected size in bytes of each recorded packet.
  uint32_t bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() *
                              SampleFormatToBytesPerChannel(kSampleFormat);

  {
    // We use 10ms packets and will run the test until ten packets are received.
    // All should contain valid packets of the same size and a valid delay
    // estimate.
    base::RunLoop run_loop;
    EXPECT_CALL(sink, OnData(NotNull(), _, _))
        .Times(AtLeast(10))
        .WillRepeatedly(
            CheckCountAndPostQuitTask(&count, 10, message_loop_.task_runner(),
                                      run_loop.QuitWhenIdleClosure()));
    ais->Start(&sink);
    run_loop.Run();
    ais->Stop();
  }

  // Store current packet size (to be used in the subsequent tests).
  int frames_per_buffer_10ms = aisw.frames_per_buffer();

  ais.Close();

  // 20 ms packet size.

  count = 0;
  ais.Reset(aisw.Create(2 * frames_per_buffer_10ms));
  EXPECT_TRUE(ais->Open());
  bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() *
                     SampleFormatToBytesPerChannel(kSampleFormat);

  {
    base::RunLoop run_loop;
    EXPECT_CALL(sink, OnData(NotNull(), _, _))
        .Times(AtLeast(10))
        .WillRepeatedly(
            CheckCountAndPostQuitTask(&count, 10, message_loop_.task_runner(),
                                      run_loop.QuitWhenIdleClosure()));
    ais->Start(&sink);
    run_loop.Run();
    ais->Stop();
    ais.Close();
  }

  // 5 ms packet size.

  count = 0;
  ais.Reset(aisw.Create(frames_per_buffer_10ms / 2));
  EXPECT_TRUE(ais->Open());
  bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() *
                     SampleFormatToBytesPerChannel(kSampleFormat);

  {
    base::RunLoop run_loop;
    EXPECT_CALL(sink, OnData(NotNull(), _, _))
        .Times(AtLeast(10))
        .WillRepeatedly(
            CheckCountAndPostQuitTask(&count, 10, message_loop_.task_runner(),
                                      run_loop.QuitWhenIdleClosure()));
    ais->Start(&sink);
    run_loop.Run();
    ais->Stop();
    ais.Close();
  }
}

// Test that we can capture a stream in loopback.
TEST_P(WinAudioInputTest, WASAPIAudioInputStreamLoopback) {
  AudioDeviceInfoAccessorForTests device_info_accessor(audio_manager_.get());
  ABORT_AUDIO_TEST_IF_NOT(device_info_accessor.HasAudioOutputDevices() &&
                          CoreAudioUtil::IsSupported());
  AudioParameters params = device_info_accessor.GetInputStreamParameters(
      AudioDeviceDescription::kLoopbackInputDeviceId);
  EXPECT_EQ(params.effects(), 0);

  AudioParameters output_params =
      device_info_accessor.GetOutputStreamParameters(std::string());
  EXPECT_EQ(params.sample_rate(), output_params.sample_rate());
  EXPECT_EQ(params.channel_layout(), output_params.channel_layout());

  ScopedAudioInputStream stream(audio_manager_->MakeAudioInputStream(
      params, AudioDeviceDescription::kLoopbackInputDeviceId,
      base::BindRepeating(&LogCallbackDummy)));
  ASSERT_TRUE(stream->Open());
  FakeAudioInputCallback sink;
  stream->Start(&sink);
  ASSERT_FALSE(sink.error());

  sink.WaitForData();
  stream.Close();

  EXPECT_GT(sink.num_received_audio_frames(), 0);
  EXPECT_FALSE(sink.error());
}

// This test is intended for manual tests and should only be enabled
// when it is required to store the captured data on a local file.
// By default, GTest will print out YOU HAVE 1 DISABLED TEST.
// To include disabled tests in test execution, just invoke the test program
// with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS
// environment variable to a value greater than 0.
TEST_P(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) {
  ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));

  // Name of the output PCM file containing captured data. The output file
  // will be stored in the directory containing 'media_unittests.exe'.
  // Example of full name: \src\build\Debug\out_stereo_10sec.pcm.
  const char* file_name = "out_10sec.pcm";

  AudioInputStreamWrapper aisw(audio_manager_.get(), GetParam());
  ScopedAudioInputStream ais(aisw.Create());
  ASSERT_TRUE(ais->Open());

  VLOG(0) << ">> Sample rate: " << aisw.sample_rate() << " [Hz]";
  WriteToFileAudioSink file_sink(file_name);
  VLOG(0) << ">> Speak into the default microphone while recording.";
  ais->Start(&file_sink);
  base::PlatformThread::Sleep(TestTimeouts::action_timeout());
  ais->Stop();
  VLOG(0) << ">> Recording has stopped.";
  ais.Close();
}

TEST_P(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamResampleToFile) {
  ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));

  // This is basically the same test as WASAPIAudioInputStreamRecordToFile
  // except it forces use of a different sample rate than is preferred by
  // the hardware.  This functionality is offered while we still have code
  // that doesn't ask the lower levels for what the preferred audio parameters
  // are (and previously depended on the old Wave API to do this automatically).

  struct TestData {
    const int rate;
    const int frames;
    ChannelLayout layout;
  } tests[] = {
      {8000, 80, CHANNEL_LAYOUT_MONO},
      {8000, 80, CHANNEL_LAYOUT_STEREO},
      {44100, 441, CHANNEL_LAYOUT_MONO},
      {44100, 1024, CHANNEL_LAYOUT_STEREO},
  };

  for (const auto& test : tests) {
    AudioParameters params;
    ASSERT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters(
        AudioDeviceDescription::kDefaultDeviceId, false, &params)));

    VLOG(0) << ">> Hardware sample rate: " << params.sample_rate() << " [Hz]";
    VLOG(0) << ">> Hardware channel layout: "
            << ChannelLayoutToString(params.channel_layout());

    // Pick a somewhat difficult sample rate to convert too.
    // If the sample rate is 8kHz, 16kHz, 32kHz, 48kHz etc, we convert to
    // 44.1kHz.
    // Otherwise (e.g. 44.1kHz, 22.05kHz etc) we convert to 48kHz.
    const int hw_sample_rate = params.sample_rate();
    params.Reset(params.format(), test.layout, test.rate, test.frames);
    if (GetParam())
      params.set_effects(params.effects() | AudioParameters::ECHO_CANCELLER);

    std::string file_name(base::StringPrintf(
        "resampled_10sec_%i_to_%i_%s.pcm", hw_sample_rate, params.sample_rate(),
        ChannelLayoutToString(params.channel_layout())));

    AudioInputStreamWrapper aisw(audio_manager_.get(), params);
    ScopedAudioInputStream ais(aisw.Create());
    ASSERT_TRUE(ais->Open());

    VLOG(0) << ">> Resampled rate will be: " << aisw.sample_rate() << " [Hz]";
    VLOG(0) << ">> New layout will be: "
            << ChannelLayoutToString(params.channel_layout());
    WriteToFileAudioSink file_sink(file_name.c_str());
    VLOG(0) << ">> Speak into the default microphone while recording.";
    ais->Start(&file_sink);
    base::PlatformThread::Sleep(TestTimeouts::action_timeout());
    // base::PlatformThread::Sleep(base::TimeDelta::FromMinutes(10));
    ais->Stop();
    VLOG(0) << ">> Recording has stopped.";
    ais.Close();
  }
}

INSTANTIATE_TEST_CASE_P(/* Intentially left empty */,
                        WinAudioInputTest,
                        ::testing::Bool());

}  // namespace media
