// Copyright 2014 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.

// Simulate end to end streaming.
//
// Input:
// --source=
//   WebM used as the source of video and audio frames.
// --output=
//   File path to writing out the raw event log of the simulation session.
// --sim-id=
//   Unique simulation ID.
//
// Output:
// - Raw event log of the simulation session tagged with the unique test ID,
//   written out to the specified file path.

#include "base/at_exit.h"
#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
#include "base/files/scoped_file.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/thread_task_runner_handle.h"
#include "base/time/tick_clock.h"
#include "base/values.h"
#include "media/base/audio_bus.h"
#include "media/base/media.h"
#include "media/base/video_frame.h"
#include "media/cast/cast_config.h"
#include "media/cast/cast_environment.h"
#include "media/cast/cast_receiver.h"
#include "media/cast/cast_sender.h"
#include "media/cast/logging/encoding_event_subscriber.h"
#include "media/cast/logging/log_serializer.h"
#include "media/cast/logging/logging_defines.h"
#include "media/cast/logging/proto/raw_events.pb.h"
#include "media/cast/logging/raw_event_subscriber_bundle.h"
#include "media/cast/logging/simple_event_subscriber.h"
#include "media/cast/net/cast_transport_config.h"
#include "media/cast/net/cast_transport_defines.h"
#include "media/cast/net/cast_transport_sender.h"
#include "media/cast/net/cast_transport_sender_impl.h"
#include "media/cast/test/fake_media_source.h"
#include "media/cast/test/fake_single_thread_task_runner.h"
#include "media/cast/test/loopback_transport.h"
#include "media/cast/test/proto/network_simulation_model.pb.h"
#include "media/cast/test/skewed_tick_clock.h"
#include "media/cast/test/utility/audio_utility.h"
#include "media/cast/test/utility/default_config.h"
#include "media/cast/test/utility/test_util.h"
#include "media/cast/test/utility/udp_proxy.h"
#include "media/cast/test/utility/video_utility.h"

using media::cast::proto::IPPModel;
using media::cast::proto::NetworkSimulationModel;
using media::cast::proto::NetworkSimulationModelType;

namespace media {
namespace cast {
namespace {
const int kTargetDelay = 300;
const char kSourcePath[] = "source";
const char kModelPath[] = "model";
const char kOutputPath[] = "output";
const char kSimulationId[] = "sim-id";
const char kLibDir[] = "lib-dir";

void UpdateCastTransportStatus(CastTransportStatus status) {
  LOG(INFO) << "Cast transport status: " << status;
}

void AudioInitializationStatus(CastInitializationStatus status) {
  LOG(INFO) << "Audio status: " << status;
}

void VideoInitializationStatus(CastInitializationStatus status) {
  LOG(INFO) << "Video status: " << status;
}

void LogTransportEvents(const scoped_refptr<CastEnvironment>& env,
                        const std::vector<PacketEvent>& packet_events) {
  for (std::vector<media::cast::PacketEvent>::const_iterator it =
           packet_events.begin();
       it != packet_events.end();
       ++it) {
    env->Logging()->InsertPacketEvent(it->timestamp,
                                      it->type,
                                      it->media_type,
                                      it->rtp_timestamp,
                                      it->frame_id,
                                      it->packet_id,
                                      it->max_packet_id,
                                      it->size);
  }
}

void GotVideoFrame(
    int* counter,
    CastReceiver* cast_receiver,
    const scoped_refptr<media::VideoFrame>& video_frame,
    const base::TimeTicks& render_time,
    bool continuous) {
  ++*counter;
  cast_receiver->RequestDecodedVideoFrame(
      base::Bind(&GotVideoFrame, counter, cast_receiver));
}

void GotAudioFrame(
    int* counter,
    CastReceiver* cast_receiver,
    scoped_ptr<AudioBus> audio_bus,
    const base::TimeTicks& playout_time,
    bool is_continuous) {
  ++*counter;
  cast_receiver->RequestDecodedAudioFrame(
      base::Bind(&GotAudioFrame, counter, cast_receiver));
}

void AppendLog(EncodingEventSubscriber* subscriber,
               const std::string& extra_data,
               const base::FilePath& output_path) {
  media::cast::proto::LogMetadata metadata;
  metadata.set_extra_data(extra_data);

  media::cast::FrameEventList frame_events;
  media::cast::PacketEventList packet_events;
  subscriber->GetEventsAndReset(
      &metadata, &frame_events, &packet_events);
  media::cast::proto::GeneralDescription* gen_desc =
      metadata.mutable_general_description();
  gen_desc->set_product("Cast Simulator");
  gen_desc->set_product_version("0.1");

  scoped_ptr<char[]> serialized_log(new char[media::cast::kMaxSerializedBytes]);
  int output_bytes;
  bool success = media::cast::SerializeEvents(metadata,
                                              frame_events,
                                              packet_events,
                                              true,
                                              media::cast::kMaxSerializedBytes,
                                              serialized_log.get(),
                                              &output_bytes);

  if (!success) {
    LOG(ERROR) << "Failed to serialize log.";
    return;
  }

  if (AppendToFile(output_path, serialized_log.get(), output_bytes) == -1) {
    LOG(ERROR) << "Failed to append to log.";
  }
}

// Run simulation once.
//
// |output_path| is the path to write serialized log.
// |extra_data| is extra tagging information to write to log.
void RunSimulation(const base::FilePath& source_path,
                   const base::FilePath& output_path,
                   const std::string& extra_data,
                   const NetworkSimulationModel& model) {
  // Fake clock. Make sure start time is non zero.
  base::SimpleTestTickClock testing_clock;
  testing_clock.Advance(base::TimeDelta::FromSeconds(1));

  // Task runner.
  scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner =
      new test::FakeSingleThreadTaskRunner(&testing_clock);
  base::ThreadTaskRunnerHandle task_runner_handle(task_runner);

  // CastEnvironments.
  scoped_refptr<CastEnvironment> sender_env =
      new CastEnvironment(
          scoped_ptr<base::TickClock>(
              new test::SkewedTickClock(&testing_clock)).Pass(),
          task_runner,
          task_runner,
          task_runner);
  scoped_refptr<CastEnvironment> receiver_env =
      new CastEnvironment(
          scoped_ptr<base::TickClock>(
              new test::SkewedTickClock(&testing_clock)).Pass(),
          task_runner,
          task_runner,
          task_runner);

  // Event subscriber. Store at most 1 hour of events.
  EncodingEventSubscriber audio_event_subscriber(AUDIO_EVENT,
                                                 100 * 60 * 60);
  EncodingEventSubscriber video_event_subscriber(VIDEO_EVENT,
                                                 30 * 60 * 60);
  sender_env->Logging()->AddRawEventSubscriber(&audio_event_subscriber);
  sender_env->Logging()->AddRawEventSubscriber(&video_event_subscriber);

  // Audio sender config.
  AudioSenderConfig audio_sender_config = GetDefaultAudioSenderConfig();
  audio_sender_config.target_playout_delay =
      base::TimeDelta::FromMilliseconds(kTargetDelay);

  // Audio receiver config.
  FrameReceiverConfig audio_receiver_config =
      GetDefaultAudioReceiverConfig();
  audio_receiver_config.rtp_max_delay_ms =
      audio_sender_config.target_playout_delay.InMilliseconds();

  // Video sender config.
  VideoSenderConfig video_sender_config = GetDefaultVideoSenderConfig();
  video_sender_config.max_bitrate = 4000000;
  video_sender_config.min_bitrate = 2000000;
  video_sender_config.start_bitrate = 4000000;
  video_sender_config.target_playout_delay =
      base::TimeDelta::FromMilliseconds(kTargetDelay);

  // Video receiver config.
  FrameReceiverConfig video_receiver_config =
      GetDefaultVideoReceiverConfig();
  video_receiver_config.rtp_max_delay_ms =
      video_sender_config.target_playout_delay.InMilliseconds();

  // Loopback transport.
  LoopBackTransport receiver_to_sender(receiver_env);
  LoopBackTransport sender_to_receiver(sender_env);

  // Cast receiver.
  scoped_ptr<CastReceiver> cast_receiver(
      CastReceiver::Create(receiver_env,
                           audio_receiver_config,
                           video_receiver_config,
                           &receiver_to_sender));

  // Cast sender and transport sender.
  scoped_ptr<CastTransportSender> transport_sender(
      new CastTransportSenderImpl(
          NULL,
          &testing_clock,
          net::IPEndPoint(),
          base::Bind(&UpdateCastTransportStatus),
          base::Bind(&LogTransportEvents, sender_env),
          base::TimeDelta::FromSeconds(1),
          task_runner,
          &sender_to_receiver));
  scoped_ptr<CastSender> cast_sender(
      CastSender::Create(sender_env, transport_sender.get()));

  // Build packet pipe.
  if (model.type() != media::cast::proto::INTERRUPTED_POISSON_PROCESS) {
    LOG(ERROR) << "Unknown model type " << model.type() << ".";
    return;
  }

  const IPPModel& ipp_model = model.ipp();

  std::vector<double> average_rates(ipp_model.average_rate_size());
  std::copy(ipp_model.average_rate().begin(), ipp_model.average_rate().end(),
      average_rates.begin());
  test::InterruptedPoissonProcess ipp(average_rates,
      ipp_model.coef_burstiness(), ipp_model.coef_variance(), 0);

  // Connect sender to receiver. This initializes the pipe.
  receiver_to_sender.Initialize(
      ipp.NewBuffer(128 * 1024), cast_sender->packet_receiver(), task_runner,
      &testing_clock);
  sender_to_receiver.Initialize(
      ipp.NewBuffer(128 * 1024), cast_receiver->packet_receiver(), task_runner,
      &testing_clock);

  // Start receiver.
  int audio_frame_count = 0;
  int video_frame_count = 0;
  cast_receiver->RequestDecodedVideoFrame(
      base::Bind(&GotVideoFrame, &video_frame_count, cast_receiver.get()));
  cast_receiver->RequestDecodedAudioFrame(
      base::Bind(&GotAudioFrame, &audio_frame_count, cast_receiver.get()));

  FakeMediaSource media_source(task_runner,
                               &testing_clock,
                               video_sender_config);

  // Initializing audio and video senders.
  cast_sender->InitializeAudio(audio_sender_config,
                               base::Bind(&AudioInitializationStatus));
  cast_sender->InitializeVideo(media_source.get_video_config(),
                               base::Bind(&VideoInitializationStatus),
                               CreateDefaultVideoEncodeAcceleratorCallback(),
                               CreateDefaultVideoEncodeMemoryCallback());

  // Start sending.
  if (!source_path.empty()) {
    // 0 means using the FPS from the file.
    media_source.SetSourceFile(source_path, 0);
  }
  media_source.Start(cast_sender->audio_frame_input(),
                     cast_sender->video_frame_input());

  // Run for 3 minutes.
  base::TimeDelta elapsed_time;
  while (elapsed_time.InMinutes() < 3) {
    // Each step is 100us.
    base::TimeDelta step = base::TimeDelta::FromMicroseconds(100);
    task_runner->Sleep(step);
    elapsed_time += step;
  }

  LOG(INFO) << "Audio frame count: " << audio_frame_count;
  LOG(INFO) << "Video frame count: " << video_frame_count;
  LOG(INFO) << "Writing log: " << output_path.value();

  // Truncate file and then write serialized log.
  {
    base::ScopedFILE file(base::OpenFile(output_path, "wb"));
    if (!file.get()) {
      LOG(INFO) << "Cannot write to log.";
      return;
    }
  }
  AppendLog(&video_event_subscriber, extra_data, output_path);
  AppendLog(&audio_event_subscriber, extra_data, output_path);
}

NetworkSimulationModel DefaultModel() {
  NetworkSimulationModel model;
  model.set_type(cast::proto::INTERRUPTED_POISSON_PROCESS);
  IPPModel* ipp = model.mutable_ipp();
  ipp->set_coef_burstiness(0.609);
  ipp->set_coef_variance(4.1);

  ipp->add_average_rate(0.609);
  ipp->add_average_rate(0.495);
  ipp->add_average_rate(0.561);
  ipp->add_average_rate(0.458);
  ipp->add_average_rate(0.538);
  ipp->add_average_rate(0.513);
  ipp->add_average_rate(0.585);
  ipp->add_average_rate(0.592);
  ipp->add_average_rate(0.658);
  ipp->add_average_rate(0.556);
  ipp->add_average_rate(0.371);
  ipp->add_average_rate(0.595);
  ipp->add_average_rate(0.490);
  ipp->add_average_rate(0.980);
  ipp->add_average_rate(0.781);
  ipp->add_average_rate(0.463);

  return model;
}

bool IsModelValid(const NetworkSimulationModel& model) {
  if (!model.has_type())
    return false;
  NetworkSimulationModelType type = model.type();
  if (type == media::cast::proto::INTERRUPTED_POISSON_PROCESS) {
    if (!model.has_ipp())
      return false;
    const IPPModel& ipp = model.ipp();
    if (ipp.coef_burstiness() <= 0.0 || ipp.coef_variance() <= 0.0)
      return false;
    if (ipp.average_rate_size() == 0)
      return false;
    for (int i = 0; i < ipp.average_rate_size(); i++) {
      if (ipp.average_rate(i) <= 0.0)
        return false;
    }
  }

  return true;
}

NetworkSimulationModel LoadModel(const base::FilePath& model_path) {
  if (model_path.empty()) {
    LOG(ERROR) << "Model path not set.";
    return DefaultModel();
  }
  std::string model_str;
  if (!base::ReadFileToString(model_path, &model_str)) {
    LOG(ERROR) << "Failed to read model file.";
    return DefaultModel();
  }

  NetworkSimulationModel model;
  if (!model.ParseFromString(model_str)) {
    LOG(ERROR) << "Failed to parse model.";
    return DefaultModel();
  }
  if (!IsModelValid(model)) {
    LOG(ERROR) << "Invalid model.";
    return DefaultModel();
  }

  return model;
}

}  // namespace
}  // namespace cast
}  // namespace media

int main(int argc, char** argv) {
  base::AtExitManager at_exit;
  CommandLine::Init(argc, argv);
  InitLogging(logging::LoggingSettings());

  const CommandLine* cmd = CommandLine::ForCurrentProcess();
  base::FilePath media_path = cmd->GetSwitchValuePath(media::cast::kLibDir);
  if (media_path.empty()) {
    if (!PathService::Get(base::DIR_MODULE, &media_path)) {
      LOG(ERROR) << "Failed to load FFmpeg.";
      return 1;
    }
  }

  if (!media::InitializeMediaLibrary(media_path)) {
    LOG(ERROR) << "Failed to initialize FFmpeg.";
    return 1;
  }

  base::FilePath source_path = cmd->GetSwitchValuePath(
      media::cast::kSourcePath);
  base::FilePath output_path = cmd->GetSwitchValuePath(
      media::cast::kOutputPath);
  if (output_path.empty()) {
    base::GetTempDir(&output_path);
    output_path = output_path.AppendASCII("sim-events.gz");
  }
  std::string sim_id = cmd->GetSwitchValueASCII(media::cast::kSimulationId);

  NetworkSimulationModel model = media::cast::LoadModel(
      cmd->GetSwitchValuePath(media::cast::kModelPath));

  base::DictionaryValue values;
  values.SetBoolean("sim", true);
  values.SetString("sim-id", sim_id);

  std::string extra_data;
  base::JSONWriter::Write(&values, &extra_data);

  // Run.
  media::cast::RunSimulation(source_path, output_path, extra_data, model);
  return 0;
}
