// 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 <stdint.h>

#include <memory>

#include "base/bind.h"
#include "base/environment.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/task_environment.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.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_base.h"
#include "media/audio/audio_unittest_util.h"
#include "media/audio/mac/audio_low_latency_input_mac.h"
#include "media/audio/test_audio_thread.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::Ge;
using ::testing::NotNull;

namespace media {

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

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

// This audio sink implementation should be used for manual tests only since
// the recorded data is stored on a raw binary data file.
// The last test (WriteToFileAudioSink) - which is disabled by default -
// can use this audio sink to store the captured data on a file for offline
// analysis.
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 int kMaxBufferSize = 2 * 2 * 480 * 100 * 10;

  explicit WriteToFileAudioSink(const char* file_name)
      : buffer_(0, kMaxBufferSize),
        file_(fopen(file_name, "wb")),
        bytes_to_write_(0) {
  }

  ~WriteToFileAudioSink() override {
    int 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, file_);
      buffer_.Seek(chunk_size);
      bytes_written += chunk_size;
    }
    fclose(file_);
  }

  // AudioInputStream::AudioInputCallback implementation.
  void OnData(const AudioBus* src,
              base::TimeTicks capture_time,
              double volume) override {
    const int num_samples = src->frames() * src->channels();
    std::unique_ptr<int16_t> interleaved(new int16_t[num_samples]);
    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 bytes_per_sample = sizeof(*interleaved);
    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* file_;
  int bytes_to_write_;
};

class MacAudioInputTest : public testing::Test {
 protected:
  MacAudioInputTest()
      : task_environment_(
            base::test::SingleThreadTaskEnvironment::MainThreadType::UI),
        audio_manager_(AudioManager::CreateForTesting(
            std::make_unique<TestAudioThread>())) {
    // Wait for the AudioManager to finish any initialization on the audio loop.
    base::RunLoop().RunUntilIdle();
  }

  ~MacAudioInputTest() override { audio_manager_->Shutdown(); }

  bool InputDevicesAvailable() {
#if defined(OS_MAC) && defined(ARCH_CPU_ARM64)
    // TODO(crbug.com/1128458): macOS on ARM64 says it has devices, but won't
    // let any of them be opened or listed.
    return false;
#else
    return AudioDeviceInfoAccessorForTests(audio_manager_.get())
        .HasAudioInputDevices();
#endif
  }

  // Convenience method which creates a default AudioInputStream object using
  // a 10ms frame size and a sample rate which is set to the hardware sample
  // rate.
  AudioInputStream* CreateDefaultAudioInputStream() {
    int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate());
    int samples_per_packet = fs / 100;
    AudioInputStream* ais = audio_manager_->MakeAudioInputStream(
        AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
                        CHANNEL_LAYOUT_STEREO, fs, samples_per_packet),
        AudioDeviceDescription::kDefaultDeviceId,
        base::BindRepeating(&MacAudioInputTest::OnLogMessage,
                            base::Unretained(this)));
    EXPECT_TRUE(ais);
    return ais;
  }

  // Convenience method which creates an AudioInputStream object with a
  // specified channel layout.
  AudioInputStream* CreateAudioInputStream(ChannelLayout channel_layout) {
    int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate());
    int samples_per_packet = fs / 100;
    AudioInputStream* ais = audio_manager_->MakeAudioInputStream(
        AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
                        fs, samples_per_packet),
        AudioDeviceDescription::kDefaultDeviceId,
        base::BindRepeating(&MacAudioInputTest::OnLogMessage,
                            base::Unretained(this)));
    EXPECT_TRUE(ais);
    return ais;
  }

  void OnLogMessage(const std::string& message) { log_message_ = message; }

  base::test::SingleThreadTaskEnvironment task_environment_;
  std::unique_ptr<AudioManager> audio_manager_;
  std::string log_message_;
};

// Test Create(), Close().
TEST_F(MacAudioInputTest, AUAudioInputStreamCreateAndClose) {
  ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
  AudioInputStream* ais = CreateDefaultAudioInputStream();
  ais->Close();
}

// Test Open(), Close().
TEST_F(MacAudioInputTest, AUAudioInputStreamOpenAndClose) {
  ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
  AudioInputStream* ais = CreateDefaultAudioInputStream();
  EXPECT_EQ(ais->Open(), AudioInputStream::OpenOutcome::kSuccess);
  ais->Close();
}

// Test Open(), Start(), Close().
TEST_F(MacAudioInputTest, AUAudioInputStreamOpenStartAndClose) {
  ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
  AudioInputStream* ais = CreateDefaultAudioInputStream();
  EXPECT_EQ(ais->Open(), AudioInputStream::OpenOutcome::kSuccess);
  MockAudioInputCallback sink;
  ais->Start(&sink);
  ais->Close();
}

// Test Open(), Start(), Stop(), Close().
TEST_F(MacAudioInputTest, AUAudioInputStreamOpenStartStopAndClose) {
  ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
  AudioInputStream* ais = CreateDefaultAudioInputStream();
  EXPECT_EQ(ais->Open(), AudioInputStream::OpenOutcome::kSuccess);
  MockAudioInputCallback sink;
  ais->Start(&sink);
  ais->Stop();
  ais->Close();
}

// Verify that recording starts and stops correctly in mono using mocked sink.
TEST_F(MacAudioInputTest, AUAudioInputStreamVerifyMonoRecording) {
  ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());

  int count = 0;

  // Create an audio input stream which records in mono.
  AudioInputStream* ais = CreateAudioInputStream(CHANNEL_LAYOUT_MONO);
  EXPECT_EQ(ais->Open(), AudioInputStream::OpenOutcome::kSuccess);

  MockAudioInputCallback sink;

  // 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, task_environment_.GetMainThreadTaskRunner(),
          run_loop.QuitClosure()));
  ais->Start(&sink);
  run_loop.Run();
  ais->Stop();
  ais->Close();

  EXPECT_FALSE(log_message_.empty());
}

// Verify that recording starts and stops correctly in mono using mocked sink.
TEST_F(MacAudioInputTest, AUAudioInputStreamVerifyStereoRecording) {
  ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());

  int count = 0;

  // Create an audio input stream which records in stereo.
  AudioInputStream* ais = CreateAudioInputStream(CHANNEL_LAYOUT_STEREO);
  EXPECT_EQ(ais->Open(), AudioInputStream::OpenOutcome::kSuccess);

  MockAudioInputCallback sink;

  // 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.
  // TODO(henrika): http://crbug.com/154352 forced us to run the capture side
  // using a native buffer size of 128 audio frames and combine it with a FIFO
  // to match the requested size by the client. This change might also have
  // modified the delay estimates since the existing Ge(bytes_per_packet) for
  // parameter #4 does no longer pass. I am removing this restriction here to
  // ensure that we can land the patch but will revisit this test again when
  // more analysis of the delay estimates are done.
  base::RunLoop run_loop;
  EXPECT_CALL(sink, OnData(NotNull(), _, _))
      .Times(AtLeast(10))
      .WillRepeatedly(CheckCountAndPostQuitTask(
          &count, 10, task_environment_.GetMainThreadTaskRunner(),
          run_loop.QuitClosure()));
  ais->Start(&sink);
  run_loop.Run();
  ais->Stop();
  ais->Close();

  EXPECT_FALSE(log_message_.empty());
}

// 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_F(MacAudioInputTest, DISABLED_AUAudioInputStreamRecordToFile) {
  ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable());
  const char* file_name = "out_stereo_10sec.pcm";

  int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate());
  AudioInputStream* ais = CreateDefaultAudioInputStream();
  EXPECT_EQ(ais->Open(), AudioInputStream::OpenOutcome::kSuccess);

  fprintf(stderr, "               File name  : %s\n", file_name);
  fprintf(stderr, "               Sample rate: %d\n", fs);
  WriteToFileAudioSink file_sink(file_name);
  fprintf(stderr, "               >> Speak into the mic while recording...\n");
  ais->Start(&file_sink);
  base::PlatformThread::Sleep(TestTimeouts::action_timeout());
  ais->Stop();
  fprintf(stderr, "               >> Recording has stopped.\n");
  ais->Close();
}

TEST(MacAudioInputUpmixerTest, Upmix16bit) {
  constexpr int kNumFrames = 512;
  constexpr int kBytesPerSample = sizeof(int16_t);
  int16_t mono[kNumFrames];
  int16_t stereo[kNumFrames * 2];

  // Fill the mono buffer and the first half of the stereo buffer with data
  for (int i = 0; i != kNumFrames; ++i) {
    mono[i] = i;
    stereo[i] = i;
  }

  AudioBuffer audio_buffer;
  audio_buffer.mNumberChannels = 2;
  audio_buffer.mDataByteSize = kNumFrames * kBytesPerSample * 2;
  audio_buffer.mData = stereo;
  AUAudioInputStream::UpmixMonoToStereoInPlace(&audio_buffer, kBytesPerSample);

  // Assert that the samples have been distributed properly
  for (int i = 0; i != kNumFrames; ++i) {
    ASSERT_EQ(mono[i], stereo[i * 2]);
    ASSERT_EQ(mono[i], stereo[i * 2 + 1]);
  }
}

TEST(MacAudioInputUpmixerTest, Upmix32bit) {
  constexpr int kNumFrames = 512;
  constexpr int kBytesPerSample = sizeof(int32_t);
  int32_t mono[kNumFrames];
  int32_t stereo[kNumFrames * 2];

  // Fill the mono buffer and the first half of the stereo buffer with data
  for (int i = 0; i != kNumFrames; ++i) {
    mono[i] = i;
    stereo[i] = i;
  }

  AudioBuffer audio_buffer;
  audio_buffer.mNumberChannels = 2;
  audio_buffer.mDataByteSize = kNumFrames * kBytesPerSample * 2;
  audio_buffer.mData = stereo;
  AUAudioInputStream::UpmixMonoToStereoInPlace(&audio_buffer, kBytesPerSample);

  // Assert that the samples have been distributed properly
  for (int i = 0; i != kNumFrames; ++i) {
    ASSERT_EQ(mono[i], stereo[i * 2]);
    ASSERT_EQ(mono[i], stereo[i * 2 + 1]);
  }
}

}  // namespace media
