// Copyright 2017 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 "content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.h"

#include <utility>

#include "base/bind.h"
#include "base/memory/shared_memory.h"
#include "base/memory/shared_memory_handle.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/sync_socket.h"
#include "base/task/post_task.h"
#include "cc/base/math_util.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/common/media/renderer_audio_output_stream_factory.mojom.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "content/renderer/media/audio/mojo_audio_output_ipc.h"
#include "media/audio/audio_manager_base.h"
#include "media/audio/audio_output_controller.h"
#include "media/audio/audio_output_device.h"
#include "media/audio/audio_system_impl.h"
#include "media/audio/audio_thread_impl.h"
#include "media/audio/mock_audio_manager.h"
#include "media/audio/simple_sources.h"
#include "media/base/audio_parameters.h"
#include "media/base/media_switches.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace content {

namespace {

using testing::_;
using testing::StrictMock;
using testing::Return;
using testing::Test;

const int kRenderProcessId = 42;
const int kRenderFrameId = 24;
const float kWaveFrequency = 440.f;
const int kChannels = 1;
const int kBuffers = 100;
const int kSampleFrequency = 8000;
const int kSamplesPerBuffer = kSampleFrequency / 10;

std::unique_ptr<media::AudioOutputStream::AudioSourceCallback>
GetTestAudioSource() {
  return std::make_unique<media::SineWaveAudioSource>(kChannels, kWaveFrequency,
                                                      kSampleFrequency);
}

media::AudioParameters GetTestAudioParameters() {
  return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
                                media::CHANNEL_LAYOUT_MONO, kSampleFrequency,
                                kSamplesPerBuffer);
}

void SyncWith(scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
  CHECK(task_runner);
  CHECK(!task_runner->BelongsToCurrentThread());
  base::WaitableEvent e = {base::WaitableEvent::ResetPolicy::MANUAL,
                           base::WaitableEvent::InitialState::NOT_SIGNALED};
  task_runner->PostTask(FROM_HERE, base::BindOnce(&base::WaitableEvent::Signal,
                                                  base::Unretained(&e)));
  e.Wait();
}

void SyncWithAllThreads() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  // New tasks might be posted while we are syncing, but in every iteration at
  // least one task will be run. 20 iterations should be enough for our code.
  for (int i = 0; i < 20; ++i) {
    base::RunLoop(base::RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();
    SyncWith(base::CreateSingleThreadTaskRunner({BrowserThread::IO}));
    SyncWith(media::AudioManager::Get()->GetWorkerTaskRunner());
  }
}

class MockAudioOutputStream : public media::AudioOutputStream,
                              public base::PlatformThread::Delegate {
 public:
  MockAudioOutputStream()
      : done_(base::WaitableEvent::ResetPolicy::MANUAL,
              base::WaitableEvent::InitialState::NOT_SIGNALED) {}

  ~MockAudioOutputStream() override {
    base::PlatformThread::Join(thread_handle_);
  }

  void Wait() { done_.Wait(); }

  void Start(AudioSourceCallback* callback) override {
    callback_ = callback;
    EXPECT_TRUE(base::PlatformThread::CreateWithPriority(
        0, this, &thread_handle_, base::ThreadPriority::REALTIME_AUDIO));
  }

  void Stop() override {
    done_.Wait();
    callback_ = nullptr;
  }

  bool Open() override { return true; }
  void SetVolume(double volume) override {}
  void GetVolume(double* volume) override { *volume = 1; }
  void Close() override {
    Stop();
    delete this;
  }
  void Flush() override {}

  void ThreadMain() override {
    std::unique_ptr<media::AudioOutputStream::AudioSourceCallback>
        expected_audio = GetTestAudioSource();
    media::AudioParameters params = GetTestAudioParameters();
    std::unique_ptr<media::AudioBus> dest = media::AudioBus::Create(params);
    std::unique_ptr<media::AudioBus> expected_buffer =
        media::AudioBus::Create(params);
    for (int i = 0; i < kBuffers; ++i) {
      expected_audio->OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), 0,
                                 expected_buffer.get());
      callback_->OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), 0,
                            dest.get());
      for (int frame = 0; frame < params.frames_per_buffer(); ++frame) {
        // Using EXPECT here causes massive log spam in case of a broken test,
        // and ASSERT causes it to hang, so we use CHECK.
        CHECK(cc::MathUtil::IsFloatNearlyTheSame(
            expected_buffer->channel(0)[frame], dest->channel(0)[frame]))
            << "Got " << dest->channel(0)[frame] << ", expected "
            << expected_buffer->channel(0)[frame];
      }
    }
    done_.Signal();
  }

 private:
  base::OnceClosure sync_closure_;
  base::PlatformThreadHandle thread_handle_;
  base::WaitableEvent done_;
  AudioSourceCallback* callback_;
};

class TestRenderCallback : public media::AudioRendererSink::RenderCallback {
 public:
  TestRenderCallback() : source_(GetTestAudioSource()) {}

  ~TestRenderCallback() override {}

  int Render(base::TimeDelta delay,
             base::TimeTicks delay_timestamp,
             int prior_frames_skipped,
             media::AudioBus* dest) override {
    return source_->OnMoreData(delay, delay_timestamp, prior_frames_skipped,
                               dest);
  }

  MOCK_METHOD0(OnRenderError, void());

 private:
  std::unique_ptr<media::AudioOutputStream::AudioSourceCallback> source_;
};

}  // namespace

// TODO(maxmorin): Add test for play, pause and set volume.
class RendererAudioOutputStreamFactoryIntegrationTest : public Test {
 public:
  RendererAudioOutputStreamFactoryIntegrationTest()
      : media_stream_manager_(),
        task_environment_(BrowserTaskEnvironment::Options::REAL_IO_THREAD),
        audio_manager_(std::make_unique<media::AudioThreadImpl>()),
        audio_system_(&audio_manager_) {
    media_stream_manager_ = std::make_unique<MediaStreamManager>(
        &audio_system_, audio_manager_.GetTaskRunner());
  }

  ~RendererAudioOutputStreamFactoryIntegrationTest() override {
    audio_manager_.Shutdown();
  }

  UniqueAudioOutputStreamFactoryPtr CreateAndBindFactory(
      mojom::RendererAudioOutputStreamFactoryRequest request) {
    factory_context_.reset(new RendererAudioOutputStreamFactoryContextImpl(
        kRenderProcessId, &audio_system_, &audio_manager_,
        media_stream_manager_.get()));
    return RenderFrameAudioOutputStreamFactoryHandle::CreateFactory(
        factory_context_.get(), kRenderFrameId, std::move(request));
  }

  std::unique_ptr<MediaStreamManager> media_stream_manager_;
  BrowserTaskEnvironment task_environment_;
  media::MockAudioManager audio_manager_;
  media::AudioSystemImpl audio_system_;
  std::unique_ptr<RendererAudioOutputStreamFactoryContextImpl,
                  BrowserThread::DeleteOnIOThread>
      factory_context_;
};

// It's flaky on the buildbot, http://crbug.com/761214.
TEST_F(RendererAudioOutputStreamFactoryIntegrationTest, StreamIntegrationTest) {
  // Sets up the factory on the IO thread and runs client code on the UI thread.
  // Send a sine wave from the client and makes sure it's received by the output
  // stream.
  MockAudioOutputStream* stream = new MockAudioOutputStream();

  // Make sure the mock audio manager uses our mock stream.
  bool create_stream_called = false;
  audio_manager_.SetMakeOutputStreamCB(base::BindRepeating(
      [](bool* create_stream_called, media::AudioOutputStream* stream,
         const media::AudioParameters& params,
         const std::string& name) -> media::AudioOutputStream* {
        DCHECK(!*create_stream_called);
        DCHECK(stream);
        DCHECK_EQ(name, "default");
        DCHECK_EQ(params.AsHumanReadableString(),
                  GetTestAudioParameters().AsHumanReadableString());
        *create_stream_called = true;
        return stream;
      },
      &create_stream_called, stream));

  mojom::RendererAudioOutputStreamFactoryPtr stream_factory;
  auto factory_handle =
      CreateAndBindFactory(mojo::MakeRequest(&stream_factory));

  base::Thread renderer_side_ipc_thread("Renderer IPC thread");
  ASSERT_TRUE(renderer_side_ipc_thread.Start());
  auto renderer_ipc_task_runner = renderer_side_ipc_thread.task_runner();

  // Bind |stream_factory| to |renderer_ipc_task_runner|.
  mojom::RendererAudioOutputStreamFactory* factory_ptr;
  renderer_ipc_task_runner->PostTask(
      FROM_HERE, base::BindOnce(
                     [](mojom::RendererAudioOutputStreamFactoryPtr* factory,
                        mojom::RendererAudioOutputStreamFactoryPtrInfo info,
                        mojom::RendererAudioOutputStreamFactory** ptr) {
                       factory->Bind(std::move(info));
                       *ptr = factory->get();
                     },
                     base::Unretained(&stream_factory),
                     stream_factory.PassInterface(), &factory_ptr));
  // Wait for factory_ptr to be set.
  SyncWith(renderer_ipc_task_runner);

  auto renderer_side_ipc = std::make_unique<MojoAudioOutputIPC>(
      base::BindRepeating(
          [](mojom::RendererAudioOutputStreamFactory* factory_ptr) {
            return factory_ptr;
          },
          factory_ptr),
      renderer_ipc_task_runner);

  auto device = base::MakeRefCounted<media::AudioOutputDevice>(
      std::move(renderer_side_ipc), renderer_ipc_task_runner,
      media::AudioSinkParameters(), base::TimeDelta());

  StrictMock<TestRenderCallback> source;

  device->Initialize(GetTestAudioParameters(), &source);
  device->Start();
  device->Play();
  // Wait for stream to start.
  SyncWithAllThreads();
  // Wait for stream to finish. Verifies data.
  stream->Wait();
  device->Stop();

  // |stream_factory| must be destroyed on the correct thread.
  renderer_ipc_task_runner->PostTask(
      FROM_HERE,
      base::BindOnce([](mojom::RendererAudioOutputStreamFactoryPtr) {},
                     std::move(stream_factory)));
  SyncWith(renderer_ipc_task_runner);
  // Wait for any clean-up tasks.
  SyncWithAllThreads();
}

}  // namespace content
