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

#include "media/cast/test/fake_media_source.h"

#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
#include "media/base/audio_buffer.h"
#include "media/base/audio_bus.h"
#include "media/base/audio_fifo.h"
#include "media/base/audio_timestamp_helper.h"
#include "media/base/media.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
#include "media/cast/cast_sender.h"
#include "media/cast/test/utility/audio_utility.h"
#include "media/cast/test/utility/video_utility.h"
#include "ui/gfx/geometry/size.h"

// TODO(miu): Figure out why _mkdir() and _rmdir() are missing when compiling
// third_party/ffmpeg/libavformat/os_support.h (lines 182, 183).
// http://crbug.com/572986
#if defined(OS_WIN)
#include <direct.h>
#endif  // defined(OS_WIN)
#include "media/ffmpeg/ffmpeg_common.h"
#include "media/ffmpeg/ffmpeg_decoding_loop.h"
#include "media/ffmpeg/ffmpeg_deleters.h"
#include "media/filters/ffmpeg_glue.h"
#include "media/filters/in_memory_url_protocol.h"

namespace {

static const int kSoundFrequency = 440;  // Frequency of sinusoid wave.
static const float kSoundVolume = 0.10f;
static const int kAudioFrameMs = 10;  // Each audio frame is exactly 10ms.
static const int kAudioPacketsPerSecond = 1000 / kAudioFrameMs;

// Bounds for variable frame size mode.
static const int kMinFakeFrameWidth = 60;
static const int kMinFakeFrameHeight = 34;
static const int kStartingFakeFrameWidth = 854;
static const int kStartingFakeFrameHeight = 480;
static const int kMaxFakeFrameWidth = 1280;
static const int kMaxFakeFrameHeight = 720;
static const int kMaxFrameSizeChangeMillis = 5000;

void AVFreeFrame(AVFrame* frame) {
  av_frame_free(&frame);
}

base::TimeDelta PtsToTimeDelta(int64_t pts, const AVRational& time_base) {
  return pts * base::Seconds(1) * time_base.num / time_base.den;
}

int64_t TimeDeltaToPts(base::TimeDelta delta, const AVRational& time_base) {
  return static_cast<int64_t>(
      delta.InSecondsF() * time_base.den / time_base.num + 0.5 /* rounding */);
}

}  // namespace

namespace media {
namespace cast {

FakeMediaSource::FakeMediaSource(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
    const base::TickClock* clock,
    const FrameSenderConfig& audio_config,
    const FrameSenderConfig& video_config,
    bool keep_frames)
    : task_runner_(task_runner),
      output_audio_params_(AudioParameters::AUDIO_PCM_LINEAR,
                           media::GuessChannelLayout(audio_config.channels),
                           audio_config.rtp_timebase,
                           audio_config.rtp_timebase / kAudioPacketsPerSecond),
      video_config_(video_config),
      keep_frames_(keep_frames),
      variable_frame_size_mode_(false),
      synthetic_count_(0),
      clock_(clock),
      audio_frame_count_(0),
      video_frame_count_(0),
      av_format_context_(nullptr),
      audio_stream_index_(-1),
      playback_rate_(1.0),
      video_stream_index_(-1),
      video_frame_rate_numerator_(video_config.max_frame_rate),
      video_frame_rate_denominator_(1),
      audio_algo_(&media_log_),
      video_first_pts_(0),
      video_first_pts_set_(false) {
  CHECK(output_audio_params_.IsValid());
  audio_bus_factory_ = std::make_unique<TestAudioBusFactory>(
      audio_config.channels, audio_config.rtp_timebase, kSoundFrequency,
      kSoundVolume);
}

FakeMediaSource::~FakeMediaSource() = default;

void FakeMediaSource::SetSourceFile(const base::FilePath& video_file,
                                    int final_fps) {
  DCHECK(!video_file.empty());

  LOG(INFO) << "Source: " << video_file.value();
  if (!file_data_.Initialize(video_file)) {
    LOG(ERROR) << "Cannot load file.";
    return;
  }
  protocol_ = std::make_unique<InMemoryUrlProtocol>(file_data_.data(),
                                                    file_data_.length(), false);
  glue_ = std::make_unique<FFmpegGlue>(protocol_.get());

  if (!glue_->OpenContext()) {
    LOG(ERROR) << "Cannot open file.";
    return;
  }

  // AVFormatContext is owned by the glue.
  av_format_context_ = glue_->format_context();
  if (avformat_find_stream_info(av_format_context_, NULL) < 0) {
    LOG(ERROR) << "Cannot find stream information.";
    return;
  }

  // Prepare FFmpeg decoders.
  for (unsigned int i = 0; i < av_format_context_->nb_streams; ++i) {
    AVStream* av_stream = av_format_context_->streams[i];
    std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> av_codec_context(
        AVStreamToAVCodecContext(av_stream));
    if (!av_codec_context) {
      LOG(ERROR) << "Cannot get a codec context for the codec: "
                 << av_stream->codecpar->codec_id;
      continue;
    }

    const AVCodec* av_codec = avcodec_find_decoder(av_codec_context->codec_id);

    if (!av_codec) {
      LOG(ERROR) << "Cannot find decoder for the codec: "
                 << av_codec_context->codec_id;
      continue;
    }

    // Number of threads for decoding.
    av_codec_context->thread_count = 2;
    av_codec_context->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
    av_codec_context->request_sample_fmt = AV_SAMPLE_FMT_S16;

    if (avcodec_open2(av_codec_context.get(), av_codec, nullptr) < 0) {
      LOG(ERROR) << "Cannot open AVCodecContext for the codec: "
                 << av_codec_context->codec_id;
      return;
    }

    if (av_codec->type == AVMEDIA_TYPE_AUDIO) {
      if (av_codec_context->sample_fmt == AV_SAMPLE_FMT_S16P) {
        LOG(ERROR) << "Audio format not supported.";
        continue;
      }
      ChannelLayout layout = ChannelLayoutToChromeChannelLayout(
          av_codec_context->channel_layout,
          av_codec_context->channels);
      if (layout == CHANNEL_LAYOUT_UNSUPPORTED) {
        LOG(ERROR) << "Unsupported audio channels layout.";
        continue;
      }
      if (audio_stream_index_ != -1) {
        LOG(WARNING) << "Found multiple audio streams.";
      }
      audio_stream_index_ = static_cast<int>(i);
      av_audio_context_ = std::move(av_codec_context);
      source_audio_params_.Reset(
          AudioParameters::AUDIO_PCM_LINEAR, layout,
          av_audio_context_->sample_rate,
          av_audio_context_->sample_rate / kAudioPacketsPerSecond);
      source_audio_params_.set_channels_for_discrete(
          av_audio_context_->channels);
      CHECK(source_audio_params_.IsValid());
      LOG(INFO) << "Source file has audio.";
      audio_decoding_loop_ =
          std::make_unique<FFmpegDecodingLoop>(av_audio_context_.get());
    } else if (av_codec->type == AVMEDIA_TYPE_VIDEO) {
      VideoPixelFormat format =
          AVPixelFormatToVideoPixelFormat(av_codec_context->pix_fmt);
      if (format != PIXEL_FORMAT_I420) {
        LOG(ERROR) << "Cannot handle non YV12 video format: " << format;
        continue;
      }
      if (video_stream_index_ != -1) {
        LOG(WARNING) << "Found multiple video streams.";
      }
      video_stream_index_ = static_cast<int>(i);
      av_video_context_ = std::move(av_codec_context);
      video_decoding_loop_ =
          std::make_unique<FFmpegDecodingLoop>(av_video_context_.get());
      if (final_fps > 0) {
        // If video is played at a manual speed audio needs to match.
        playback_rate_ = 1.0 * final_fps *
            av_stream->r_frame_rate.den / av_stream->r_frame_rate.num;
        video_frame_rate_numerator_ = final_fps;
        video_frame_rate_denominator_ = 1;
      } else {
        playback_rate_ = 1.0;
        video_frame_rate_numerator_ = av_stream->r_frame_rate.num;
        video_frame_rate_denominator_ = av_stream->r_frame_rate.den;
      }
      LOG(INFO) << "Source file has video.";
    } else {
      LOG(ERROR) << "Unknown stream type; ignore.";
    }
  }

  Rewind();
}

void FakeMediaSource::SetVariableFrameSizeMode(bool enabled) {
  variable_frame_size_mode_ = enabled;
}

void FakeMediaSource::Start(scoped_refptr<AudioFrameInput> audio_frame_input,
                            scoped_refptr<VideoFrameInput> video_frame_input) {
  audio_frame_input_ = audio_frame_input;
  video_frame_input_ = video_frame_input;

  LOG(INFO) << "Max Frame rate: " << video_config_.max_frame_rate;
  LOG(INFO) << "Source Frame rate: "
            << video_frame_rate_numerator_ << "/"
            << video_frame_rate_denominator_ << " fps.";
  LOG(INFO) << "Audio playback rate: " << playback_rate_;

  if (start_time_.is_null())
    start_time_ = clock_->NowTicks();

  if (!is_transcoding_audio() && !is_transcoding_video()) {
    // Send fake patterns.
    task_runner_->PostTask(FROM_HERE,
                           base::BindOnce(&FakeMediaSource::SendNextFakeFrame,
                                          weak_factory_.GetWeakPtr()));
    return;
  }

  // Send transcoding streams.
  bool is_encrypted = false;
  audio_algo_.Initialize(source_audio_params_, is_encrypted);
  audio_algo_.FlushBuffers();
  audio_fifo_input_bus_ = AudioBus::Create(
      source_audio_params_.channels(),
      source_audio_params_.frames_per_buffer());
  // Audio FIFO can carry all data fron AudioRendererAlgorithm.
  audio_fifo_ = std::make_unique<AudioFifo>(source_audio_params_.channels(),
                                            audio_algo_.QueueCapacity());
  audio_converter_ = std::make_unique<media::AudioConverter>(
      source_audio_params_, output_audio_params_, true);
  audio_converter_->AddInput(this);
  task_runner_->PostTask(FROM_HERE,
                         base::BindOnce(&FakeMediaSource::SendNextFrame,
                                        weak_factory_.GetWeakPtr()));
}

void FakeMediaSource::SendNextFakeFrame() {
  UpdateNextFrameSize();
  scoped_refptr<VideoFrame> video_frame =
      VideoFrame::CreateBlackFrame(current_frame_size_);
  PopulateVideoFrame(video_frame.get(), synthetic_count_);
  ++synthetic_count_;

  const base::TimeTicks now = clock_->NowTicks();

  base::TimeDelta video_time = VideoFrameTime(++video_frame_count_);
  video_frame->set_timestamp(video_time);
  if (keep_frames_)
    inserted_video_frame_queue_.push(video_frame);
  video_frame_input_->InsertRawVideoFrame(video_frame,
                                          start_time_ + video_time);

  // Send just enough audio data to match next video frame's time.
  base::TimeDelta audio_time = AudioFrameTime(audio_frame_count_);
  while (audio_time < video_time) {
    if (is_transcoding_audio()) {
      Decode(true);
      CHECK(!audio_bus_queue_.empty()) << "No audio decoded.";
      std::unique_ptr<AudioBus> bus(audio_bus_queue_.front());
      audio_bus_queue_.pop();
      audio_frame_input_->InsertAudio(std::move(bus), start_time_ + audio_time);
    } else {
      audio_frame_input_->InsertAudio(
          audio_bus_factory_->NextAudioBus(base::Milliseconds(kAudioFrameMs)),
          start_time_ + audio_time);
    }
    audio_time = AudioFrameTime(++audio_frame_count_);
  }

  // This is the time since FakeMediaSource was started.
  const base::TimeDelta elapsed_time = now - start_time_;

  // Handle the case when frame generation cannot keep up.
  // Move the time ahead to match the next frame.
  while (video_time < elapsed_time) {
    LOG(WARNING) << "Skipping one frame.";
    video_time = VideoFrameTime(++video_frame_count_);
  }

  task_runner_->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&FakeMediaSource::SendNextFakeFrame,
                     weak_factory_.GetWeakPtr()),
      video_time - elapsed_time);
}

void FakeMediaSource::UpdateNextFrameSize() {
  if (variable_frame_size_mode_) {
    bool update_size_change_time = false;
    if (current_frame_size_.IsEmpty()) {
      current_frame_size_ = gfx::Size(kStartingFakeFrameWidth,
                                      kStartingFakeFrameHeight);
      update_size_change_time = true;
    } else if (clock_->NowTicks() >= next_frame_size_change_time_) {
      current_frame_size_ = gfx::Size(
          base::RandInt(kMinFakeFrameWidth, kMaxFakeFrameWidth),
          base::RandInt(kMinFakeFrameHeight, kMaxFakeFrameHeight));
      update_size_change_time = true;
    }

    if (update_size_change_time) {
      next_frame_size_change_time_ =
          clock_->NowTicks() +
          base::Milliseconds(base::RandDouble() * kMaxFrameSizeChangeMillis);
    }
  } else {
    current_frame_size_ = gfx::Size(kStartingFakeFrameWidth,
                                    kStartingFakeFrameHeight);
    next_frame_size_change_time_ = base::TimeTicks();
  }
}

bool FakeMediaSource::SendNextTranscodedVideo(base::TimeDelta elapsed_time) {
  if (!is_transcoding_video())
    return false;

  Decode(false);
  if (video_frame_queue_.empty())
    return false;

  const scoped_refptr<VideoFrame> video_frame = video_frame_queue_.front();
  if (elapsed_time < video_frame->timestamp())
    return false;
  video_frame_queue_.pop();

  // Use the timestamp from the file if we're transcoding.
  video_frame->set_timestamp(ScaleTimestamp(video_frame->timestamp()));
  if (keep_frames_)
    inserted_video_frame_queue_.push(video_frame);
  video_frame_input_->InsertRawVideoFrame(
      video_frame, start_time_ + video_frame->timestamp());

  // Make sure queue is not empty.
  Decode(false);
  return true;
}

bool FakeMediaSource::SendNextTranscodedAudio(base::TimeDelta elapsed_time) {
  if (!is_transcoding_audio())
    return false;

  Decode(true);
  if (audio_bus_queue_.empty())
    return false;

  base::TimeDelta audio_time = audio_sent_ts_->GetTimestamp();
  if (elapsed_time < audio_time)
    return false;
  std::unique_ptr<AudioBus> bus(audio_bus_queue_.front());
  audio_bus_queue_.pop();
  audio_sent_ts_->AddFrames(bus->frames());
  audio_frame_input_->InsertAudio(std::move(bus), start_time_ + audio_time);

  // Make sure queue is not empty.
  Decode(true);
  return true;
}

void FakeMediaSource::SendNextFrame() {
  // Send as much as possible. Audio is sent according to
  // system time.
  while (SendNextTranscodedAudio(clock_->NowTicks() - start_time_)) {
  }

  // Video is sync'ed to audio.
  while (SendNextTranscodedVideo(audio_sent_ts_->GetTimestamp())) {
  }

  if (audio_bus_queue_.empty() && video_frame_queue_.empty()) {
    // Both queues are empty can only mean that we have reached
    // the end of the stream.
    LOG(INFO) << "Rewind.";
    Rewind();
  }

  // Send next send.
  task_runner_->PostDelayedTask(FROM_HERE,
                                base::BindOnce(&FakeMediaSource::SendNextFrame,
                                               weak_factory_.GetWeakPtr()),
                                base::Milliseconds(kAudioFrameMs));
}

base::TimeDelta FakeMediaSource::VideoFrameTime(int frame_number) {
  return frame_number * base::Seconds(1) * video_frame_rate_denominator_ /
         video_frame_rate_numerator_;
}

base::TimeDelta FakeMediaSource::ScaleTimestamp(base::TimeDelta timestamp) {
  return timestamp / playback_rate_;
}

base::TimeDelta FakeMediaSource::AudioFrameTime(int frame_number) {
  return frame_number * base::Milliseconds(kAudioFrameMs);
}

void FakeMediaSource::Rewind() {
  CHECK(av_seek_frame(av_format_context_, -1, 0, AVSEEK_FLAG_BACKWARD) >= 0)
      << "Failed to rewind to the beginning.";
}

ScopedAVPacket FakeMediaSource::DemuxOnePacket(bool* audio) {
  ScopedAVPacket packet = MakeScopedAVPacket();
  if (av_read_frame(av_format_context_, packet.get()) < 0) {
    VLOG(1) << "Failed to read one AVPacket.";
    packet.reset();
    return packet;
  }

  int stream_index = static_cast<int>(packet->stream_index);
  if (stream_index == audio_stream_index_) {
    *audio = true;
  } else if (stream_index == video_stream_index_) {
    *audio = false;
  } else {
    // Ignore unknown packet.
    LOG(INFO) << "Unknown packet.";
    packet.reset();
  }
  return packet;
}

void FakeMediaSource::DecodeAudio(ScopedAVPacket packet) {
  auto result = audio_decoding_loop_->DecodePacket(
      packet.get(), base::BindRepeating(&FakeMediaSource::OnNewAudioFrame,
                                        base::Unretained(this)));
  CHECK_EQ(result, FFmpegDecodingLoop::DecodeStatus::kOkay)
      << "Failed to decode audio.";

  const int frames_needed_to_scale =
      playback_rate_ * av_audio_context_->sample_rate / kAudioPacketsPerSecond;
  while (frames_needed_to_scale <= audio_algo_.BufferedFrames()) {
    if (!audio_algo_.FillBuffer(audio_fifo_input_bus_.get(), 0,
                                audio_fifo_input_bus_->frames(),
                                playback_rate_)) {
      // Nothing can be scaled. Decode some more.
      return;
    }

    // Prevent overflow of audio data in the FIFO.
    if (audio_fifo_input_bus_->frames() + audio_fifo_->frames() <=
        audio_fifo_->max_frames()) {
      audio_fifo_->Push(audio_fifo_input_bus_.get());
    } else {
      LOG(WARNING) << "Audio FIFO full; dropping samples.";
    }

    // Make sure there's enough data to resample audio.
    if (audio_fifo_->frames() <
        2 * source_audio_params_.sample_rate() / kAudioPacketsPerSecond) {
      continue;
    }

    std::unique_ptr<media::AudioBus> resampled_bus(media::AudioBus::Create(
        output_audio_params_.channels(),
        output_audio_params_.sample_rate() / kAudioPacketsPerSecond));
    audio_converter_->Convert(resampled_bus.get());
    audio_bus_queue_.push(resampled_bus.release());
  }
}

bool FakeMediaSource::OnNewAudioFrame(AVFrame* frame) {
  int frames_read = frame->nb_samples;
  if (frames_read < 0)
    return false;

  if (!audio_sent_ts_) {
    // Initialize the base time to the first packet in the file. This is set to
    // the frequency we send to the receiver. Not the frequency of the source
    // file. This is because we increment the frame count by samples we sent.
    audio_sent_ts_ = std::make_unique<AudioTimestampHelper>(
        output_audio_params_.sample_rate());
    // For some files this is an invalid value.
    base::TimeDelta base_ts;
    audio_sent_ts_->SetBaseTimestamp(base_ts);
  }

  scoped_refptr<AudioBuffer> buffer = AudioBuffer::CopyFrom(
      AVSampleFormatToSampleFormat(av_audio_context_->sample_fmt,
                                   av_audio_context_->codec_id),
      ChannelLayoutToChromeChannelLayout(av_audio_context_->channel_layout,
                                         av_audio_context_->channels),
      av_audio_context_->channels, av_audio_context_->sample_rate, frames_read,
      &frame->data[0],
      PtsToTimeDelta(frame->pts, av_audio_stream()->time_base));
  audio_algo_.EnqueueBuffer(buffer);
  return true;
}

void FakeMediaSource::DecodeVideo(ScopedAVPacket packet) {
  auto result = video_decoding_loop_->DecodePacket(
      packet.get(), base::BindRepeating(&FakeMediaSource::OnNewVideoFrame,
                                        base::Unretained(this)));
  CHECK_EQ(result, FFmpegDecodingLoop::DecodeStatus::kOkay)
      << "Failed to decode video.";
}

bool FakeMediaSource::OnNewVideoFrame(AVFrame* frame) {
  gfx::Size size(av_video_context_->width, av_video_context_->height);

  if (!video_first_pts_set_) {
    video_first_pts_ = frame->pts;
    video_first_pts_set_ = true;
  }
  const AVRational& time_base = av_video_stream()->time_base;
  base::TimeDelta timestamp =
      PtsToTimeDelta(frame->pts - video_first_pts_, time_base);
  if (timestamp < last_video_frame_timestamp_) {
    // Stream has rewound.  Rebase |video_first_pts_|.
    const AVRational& frame_rate = av_video_stream()->r_frame_rate;
    timestamp = last_video_frame_timestamp_ +
                (base::Seconds(1) * frame_rate.den / frame_rate.num);
    const int64_t adjustment_pts = TimeDeltaToPts(timestamp, time_base);
    video_first_pts_ = frame->pts - adjustment_pts;
  }

  AVFrame* shallow_copy = av_frame_clone(frame);
  scoped_refptr<media::VideoFrame> video_frame =
      VideoFrame::WrapExternalYuvData(
          media::PIXEL_FORMAT_I420, size, gfx::Rect(size), size,
          shallow_copy->linesize[0], shallow_copy->linesize[1],
          shallow_copy->linesize[2], shallow_copy->data[0],
          shallow_copy->data[1], shallow_copy->data[2], timestamp);
  if (!video_frame)
    return false;
  video_frame_queue_.push(video_frame);
  video_frame_queue_.back()->AddDestructionObserver(
      base::BindOnce(&AVFreeFrame, shallow_copy));
  last_video_frame_timestamp_ = timestamp;
  return true;
}

void FakeMediaSource::Decode(bool decode_audio) {
  // Read the stream until one video frame can be decoded.
  while (true) {
    if (decode_audio && !audio_bus_queue_.empty())
      return;
    if (!decode_audio && !video_frame_queue_.empty())
      return;

    bool audio_packet = false;
    ScopedAVPacket packet = DemuxOnePacket(&audio_packet);
    if (!packet) {
      VLOG(1) << "End of stream.";
      return;
    }

    if (audio_packet)
      DecodeAudio(std::move(packet));
    else
      DecodeVideo(std::move(packet));
  }
}

double FakeMediaSource::ProvideInput(media::AudioBus* output_bus,
                                     uint32_t frames_delayed) {
  if (audio_fifo_->frames() >= output_bus->frames()) {
    audio_fifo_->Consume(output_bus, 0, output_bus->frames());
    return 1.0;
  } else {
    LOG(WARNING) << "Not enough audio data for resampling.";
    output_bus->Zero();
    return 0.0;
  }
}

scoped_refptr<media::VideoFrame>
FakeMediaSource::PopOldestInsertedVideoFrame() {
  CHECK(!inserted_video_frame_queue_.empty());
  scoped_refptr<media::VideoFrame> video_frame =
      inserted_video_frame_queue_.front();
  inserted_video_frame_queue_.pop();
  return video_frame;
}

AVStream* FakeMediaSource::av_audio_stream() {
  return av_format_context_->streams[audio_stream_index_];
}

AVStream* FakeMediaSource::av_video_stream() {
  return av_format_context_->streams[video_stream_index_];
}

}  // namespace cast
}  // namespace media
