/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <stdio.h>

#include <map>
#include <sstream>

#include "gflags/gflags.h"
#include "testing/gtest/include/gtest/gtest.h"

#include "webrtc/base/checks.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/call.h"
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/sleep.h"
#include "webrtc/test/encoder_settings.h"
#include "webrtc/test/null_transport.h"
#include "webrtc/test/fake_decoder.h"
#include "webrtc/test/rtp_file_reader.h"
#include "webrtc/test/run_loop.h"
#include "webrtc/test/run_test.h"
#include "webrtc/test/video_capturer.h"
#include "webrtc/test/video_renderer.h"
#include "webrtc/typedefs.h"
#include "webrtc/video_decoder.h"

namespace webrtc {
namespace flags {

// TODO(pbos): Multiple receivers.

// Flag for payload type.
static bool ValidatePayloadType(const char* flagname, int32_t payload_type) {
  return payload_type > 0 && payload_type <= 127;
}
DEFINE_int32(payload_type, 0, "Payload type");
static int PayloadType() { return static_cast<int>(FLAGS_payload_type); }
static const bool payload_dummy =
    google::RegisterFlagValidator(&FLAGS_payload_type, &ValidatePayloadType);

// Flag for SSRC.
static bool ValidateSsrc(const char* flagname, uint64_t ssrc) {
  return ssrc > 0 && ssrc <= 0xFFFFFFFFu;
}

DEFINE_uint64(ssrc, 0, "Incoming SSRC");
static uint32_t Ssrc() { return static_cast<uint32_t>(FLAGS_ssrc); }
static const bool ssrc_dummy =
    google::RegisterFlagValidator(&FLAGS_ssrc, &ValidateSsrc);

static bool ValidateOptionalPayloadType(const char* flagname,
                                        int32_t payload_type) {
  return payload_type == -1 || ValidatePayloadType(flagname, payload_type);
}

// Flag for RED payload type.
DEFINE_int32(red_payload_type, -1, "RED payload type");
static int RedPayloadType() {
  return static_cast<int>(FLAGS_red_payload_type);
}
static const bool red_dummy =
    google::RegisterFlagValidator(&FLAGS_red_payload_type,
                                  &ValidateOptionalPayloadType);

// Flag for ULPFEC payload type.
DEFINE_int32(fec_payload_type, -1, "ULPFEC payload type");
static int FecPayloadType() {
  return static_cast<int>(FLAGS_fec_payload_type);
}
static const bool fec_dummy =
    google::RegisterFlagValidator(&FLAGS_fec_payload_type,
                                  &ValidateOptionalPayloadType);

// Flag for abs-send-time id.
static bool ValidateRtpHeaderExtensionId(const char* flagname,
                                         int32_t extension_id) {
  return extension_id >= -1 || extension_id < 15;
}
DEFINE_int32(abs_send_time_id, -1, "RTP extension ID for abs-send-time");
static int AbsSendTimeId() { return static_cast<int>(FLAGS_abs_send_time_id); }
static const bool abs_send_time_dummy =
    google::RegisterFlagValidator(&FLAGS_abs_send_time_id,
                                  &ValidateRtpHeaderExtensionId);

// Flag for transmission-offset id.
DEFINE_int32(transmission_offset_id,
             -1,
             "RTP extension ID for transmission-offset");
static int TransmissionOffsetId() {
  return static_cast<int>(FLAGS_transmission_offset_id);
}
static const bool timestamp_offset_dummy =
    google::RegisterFlagValidator(&FLAGS_transmission_offset_id,
                                  &ValidateRtpHeaderExtensionId);

// Flag for rtpdump input file.
bool ValidateInputFilenameNotEmpty(const char* flagname,
                                   const std::string& string) {
  return !string.empty();
}

DEFINE_string(input_file, "", "input file");
static std::string InputFile() {
  return static_cast<std::string>(FLAGS_input_file);
}
static const bool input_file_dummy =
    google::RegisterFlagValidator(&FLAGS_input_file,
                                  &ValidateInputFilenameNotEmpty);

// Flag for raw output files.
DEFINE_string(out_base, "", "Basename (excluding .yuv) for raw output");
static std::string OutBase() {
  return static_cast<std::string>(FLAGS_out_base);
}

DEFINE_string(decoder_bitstream_filename, "", "Decoder bitstream output file");
static std::string DecoderBitstreamFilename() {
  return static_cast<std::string>(FLAGS_decoder_bitstream_filename);
}

// Flag for video codec.
DEFINE_string(codec, "VP8", "Video codec");
static std::string Codec() { return static_cast<std::string>(FLAGS_codec); }

}  // namespace flags

static const uint32_t kReceiverLocalSsrc = 0x123456;

class FileRenderPassthrough : public VideoRenderer {
 public:
  FileRenderPassthrough(const std::string& basename, VideoRenderer* renderer)
      : basename_(basename),
        renderer_(renderer),
        file_(nullptr),
        count_(0),
        last_width_(0),
        last_height_(0) {}

  ~FileRenderPassthrough() {
    if (file_ != nullptr)
      fclose(file_);
  }

 private:
  void RenderFrame(const VideoFrame& video_frame,
                   int time_to_render_ms) override {
    if (renderer_ != nullptr)
      renderer_->RenderFrame(video_frame, time_to_render_ms);
    if (basename_.empty())
      return;
    if (last_width_ != video_frame.width() ||
        last_height_ != video_frame.height()) {
      if (file_ != nullptr)
        fclose(file_);
      std::stringstream filename;
      filename << basename_;
      if (++count_ > 1)
        filename << '-' << count_;
      filename << '_' << video_frame.width() << 'x' << video_frame.height()
               << ".yuv";
      file_ = fopen(filename.str().c_str(), "wb");
      if (file_ == nullptr) {
        fprintf(stderr,
                "Couldn't open file for writing: %s\n",
                filename.str().c_str());
      }
    }
    last_width_ = video_frame.width();
    last_height_ = video_frame.height();
    if (file_ == nullptr)
      return;
    PrintVideoFrame(video_frame, file_);
  }

  bool IsTextureSupported() const override { return false; }

  const std::string basename_;
  VideoRenderer* const renderer_;
  FILE* file_;
  size_t count_;
  int last_width_;
  int last_height_;
};

class DecoderBitstreamFileWriter : public EncodedFrameObserver {
 public:
  explicit DecoderBitstreamFileWriter(const char* filename)
      : file_(fopen(filename, "wb")) {
    DCHECK(file_ != nullptr);
  }
  ~DecoderBitstreamFileWriter() { fclose(file_); }

  virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
    fwrite(encoded_frame.data_, 1, encoded_frame.length_, file_);
  }

 private:
  FILE* file_;
};

void RtpReplay() {
  rtc::scoped_ptr<test::VideoRenderer> playback_video(
      test::VideoRenderer::Create("Playback Video", 640, 480));
  FileRenderPassthrough file_passthrough(flags::OutBase(),
                                         playback_video.get());

  rtc::scoped_ptr<Call> call(Call::Create(Call::Config()));

  test::NullTransport transport;
  VideoReceiveStream::Config receive_config(&transport);
  receive_config.rtp.remote_ssrc = flags::Ssrc();
  receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
  receive_config.rtp.fec.ulpfec_payload_type = flags::FecPayloadType();
  receive_config.rtp.fec.red_payload_type = flags::RedPayloadType();
  receive_config.rtp.nack.rtp_history_ms = 1000;
  if (flags::TransmissionOffsetId() != -1) {
    receive_config.rtp.extensions.push_back(
        RtpExtension(RtpExtension::kTOffset, flags::TransmissionOffsetId()));
  }
  if (flags::AbsSendTimeId() != -1) {
    receive_config.rtp.extensions.push_back(
        RtpExtension(RtpExtension::kAbsSendTime, flags::AbsSendTimeId()));
  }
  receive_config.renderer = &file_passthrough;

  VideoSendStream::Config::EncoderSettings encoder_settings;
  encoder_settings.payload_name = flags::Codec();
  encoder_settings.payload_type = flags::PayloadType();
  VideoReceiveStream::Decoder decoder;
  rtc::scoped_ptr<DecoderBitstreamFileWriter> bitstream_writer;
  if (!flags::DecoderBitstreamFilename().empty()) {
    bitstream_writer.reset(new DecoderBitstreamFileWriter(
        flags::DecoderBitstreamFilename().c_str()));
    receive_config.pre_decode_callback = bitstream_writer.get();
  }
  decoder = test::CreateMatchingDecoder(encoder_settings);
  if (!flags::DecoderBitstreamFilename().empty()) {
    // Replace with a null decoder if we're writing the bitstream to a file
    // instead.
    delete decoder.decoder;
    decoder.decoder = new test::FakeNullDecoder();
  }
  receive_config.decoders.push_back(decoder);

  VideoReceiveStream* receive_stream =
      call->CreateVideoReceiveStream(receive_config);

  rtc::scoped_ptr<test::RtpFileReader> rtp_reader(test::RtpFileReader::Create(
      test::RtpFileReader::kRtpDump, flags::InputFile()));
  if (rtp_reader.get() == nullptr) {
    rtp_reader.reset(test::RtpFileReader::Create(test::RtpFileReader::kPcap,
                                                 flags::InputFile()));
    if (rtp_reader.get() == nullptr) {
      fprintf(stderr,
              "Couldn't open input file as either a rtpdump or .pcap. Note "
              "that .pcapng is not supported.\nTrying to interpret the file as "
              "length/packet interleaved.\n");
      rtp_reader.reset(test::RtpFileReader::Create(
          test::RtpFileReader::kLengthPacketInterleaved, flags::InputFile()));
      if (rtp_reader.get() == nullptr) {
        fprintf(stderr,
                "Unable to open input file with any supported format\n");
        return;
      }
    }
  }
  receive_stream->Start();

  uint32_t last_time_ms = 0;
  int num_packets = 0;
  std::map<uint32_t, int> unknown_packets;
  while (true) {
    test::RtpPacket packet;
    if (!rtp_reader->NextPacket(&packet))
      break;
    ++num_packets;
    switch (call->Receiver()->DeliverPacket(webrtc::MediaType::ANY, packet.data,
                                            packet.length, PacketTime())) {
      case PacketReceiver::DELIVERY_OK:
        break;
      case PacketReceiver::DELIVERY_UNKNOWN_SSRC: {
        RTPHeader header;
        rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
        parser->Parse(packet.data, packet.length, &header);
        if (unknown_packets[header.ssrc] == 0)
          fprintf(stderr, "Unknown SSRC: %u!\n", header.ssrc);
        ++unknown_packets[header.ssrc];
        break;
      }
      case PacketReceiver::DELIVERY_PACKET_ERROR:
        fprintf(stderr, "Packet error, corrupt packets or incorrect setup?\n");
        break;
    }
    if (last_time_ms != 0 && last_time_ms != packet.time_ms) {
      SleepMs(packet.time_ms - last_time_ms);
    }
    last_time_ms = packet.time_ms;
  }
  fprintf(stderr, "num_packets: %d\n", num_packets);

  for (std::map<uint32_t, int>::const_iterator it = unknown_packets.begin();
       it != unknown_packets.end();
       ++it) {
    fprintf(
        stderr, "Packets for unknown ssrc '%u': %d\n", it->first, it->second);
  }

  call->DestroyVideoReceiveStream(receive_stream);

  delete decoder.decoder;
}
}  // namespace webrtc

int main(int argc, char* argv[]) {
  ::testing::InitGoogleTest(&argc, argv);
  google::ParseCommandLineFlags(&argc, &argv, true);

  webrtc::test::RunTest(webrtc::RtpReplay);
  return 0;
}
