/*
 *  Copyright (c) 2015 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 <iostream>
#include <sstream>
#include <string>

#include "gflags/gflags.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/call/rtc_event_log.h"
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
#include "webrtc/test/rtp_file_writer.h"

// Files generated at build-time by the protobuf compiler.
#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
#include "external/webrtc/webrtc/call/rtc_event_log.pb.h"
#else
#include "webrtc/call/rtc_event_log.pb.h"
#endif

namespace {

DEFINE_bool(noaudio,
            false,
            "Excludes audio packets from the converted RTPdump file.");
DEFINE_bool(novideo,
            false,
            "Excludes video packets from the converted RTPdump file.");
DEFINE_bool(nodata,
            false,
            "Excludes data packets from the converted RTPdump file.");
DEFINE_bool(nortp,
            false,
            "Excludes RTP packets from the converted RTPdump file.");
DEFINE_bool(nortcp,
            false,
            "Excludes RTCP packets from the converted RTPdump file.");
DEFINE_string(ssrc,
              "",
              "Store only packets with this SSRC (decimal or hex, the latter "
              "starting with 0x).");

// Parses the input string for a valid SSRC. If a valid SSRC is found, it is
// written to the output variable |ssrc|, and true is returned. Otherwise,
// false is returned.
// The empty string must be validated as true, because it is the default value
// of the command-line flag. In this case, no value is written to the output
// variable.
bool ParseSsrc(std::string str, uint32_t* ssrc) {
  // If the input string starts with 0x or 0X it indicates a hexadecimal number.
  auto read_mode = std::dec;
  if (str.size() > 2 &&
      (str.substr(0, 2) == "0x" || str.substr(0, 2) == "0X")) {
    read_mode = std::hex;
    str = str.substr(2);
  }
  std::stringstream ss(str);
  ss >> read_mode >> *ssrc;
  return str.empty() || (!ss.fail() && ss.eof());
}

}  // namespace

// This utility will convert a stored event log to the rtpdump format.
int main(int argc, char* argv[]) {
  std::string program_name = argv[0];
  std::string usage =
      "Tool for converting an RtcEventLog file to an RTP dump file.\n"
      "Run " +
      program_name +
      " --helpshort for usage.\n"
      "Example usage:\n" +
      program_name + " input.rel output.rtp\n";
  google::SetUsageMessage(usage);
  google::ParseCommandLineFlags(&argc, &argv, true);

  if (argc != 3) {
    std::cout << google::ProgramUsage();
    return 0;
  }
  std::string input_file = argv[1];
  std::string output_file = argv[2];

  uint32_t ssrc_filter = 0;
  if (!FLAGS_ssrc.empty())
    RTC_CHECK(ParseSsrc(FLAGS_ssrc, &ssrc_filter))
        << "Flag verification has failed.";

  webrtc::rtclog::EventStream event_stream;
  if (!webrtc::RtcEventLog::ParseRtcEventLog(input_file, &event_stream)) {
    std::cerr << "Error while parsing input file: " << input_file << std::endl;
    return -1;
  }

  rtc::scoped_ptr<webrtc::test::RtpFileWriter> rtp_writer(
      webrtc::test::RtpFileWriter::Create(
          webrtc::test::RtpFileWriter::FileFormat::kRtpDump, output_file));

  if (!rtp_writer.get()) {
    std::cerr << "Error while opening output file: " << output_file
              << std::endl;
    return -1;
  }

  std::cout << "Found " << event_stream.stream_size()
            << " events in the input file." << std::endl;
  int rtp_counter = 0, rtcp_counter = 0;
  bool header_only = false;
  // TODO(ivoc): This can be refactored once the packet interpretation
  //             functions are finished.
  for (int i = 0; i < event_stream.stream_size(); i++) {
    const webrtc::rtclog::Event& event = event_stream.stream(i);
    if (!FLAGS_nortp && event.has_type() && event.type() == event.RTP_EVENT) {
      if (event.has_timestamp_us() && event.has_rtp_packet() &&
          event.rtp_packet().has_header() &&
          event.rtp_packet().header().size() >= 12 &&
          event.rtp_packet().has_packet_length() &&
          event.rtp_packet().has_type()) {
        const webrtc::rtclog::RtpPacket& rtp_packet = event.rtp_packet();
        if (FLAGS_noaudio && rtp_packet.type() == webrtc::rtclog::AUDIO)
          continue;
        if (FLAGS_novideo && rtp_packet.type() == webrtc::rtclog::VIDEO)
          continue;
        if (FLAGS_nodata && rtp_packet.type() == webrtc::rtclog::DATA)
          continue;
        if (!FLAGS_ssrc.empty()) {
          const uint32_t packet_ssrc =
              webrtc::ByteReader<uint32_t>::ReadBigEndian(
                  reinterpret_cast<const uint8_t*>(rtp_packet.header().data() +
                                                   8));
          if (packet_ssrc != ssrc_filter)
            continue;
        }

        webrtc::test::RtpPacket packet;
        packet.length = rtp_packet.header().size();
        if (packet.length > packet.kMaxPacketBufferSize) {
          std::cout << "Skipping packet with size " << packet.length
                    << ", the maximum supported size is "
                    << packet.kMaxPacketBufferSize << std::endl;
          continue;
        }
        packet.original_length = rtp_packet.packet_length();
        if (packet.original_length > packet.length)
          header_only = true;
        packet.time_ms = event.timestamp_us() / 1000;
        memcpy(packet.data, rtp_packet.header().data(), packet.length);
        rtp_writer->WritePacket(&packet);
        rtp_counter++;
      } else {
        std::cout << "Skipping malformed event." << std::endl;
      }
    }
    if (!FLAGS_nortcp && event.has_type() && event.type() == event.RTCP_EVENT) {
      if (event.has_timestamp_us() && event.has_rtcp_packet() &&
          event.rtcp_packet().has_type() &&
          event.rtcp_packet().has_packet_data() &&
          event.rtcp_packet().packet_data().size() > 0) {
        const webrtc::rtclog::RtcpPacket& rtcp_packet = event.rtcp_packet();
        if (FLAGS_noaudio && rtcp_packet.type() == webrtc::rtclog::AUDIO)
          continue;
        if (FLAGS_novideo && rtcp_packet.type() == webrtc::rtclog::VIDEO)
          continue;
        if (FLAGS_nodata && rtcp_packet.type() == webrtc::rtclog::DATA)
          continue;
        if (!FLAGS_ssrc.empty()) {
          const uint32_t packet_ssrc =
              webrtc::ByteReader<uint32_t>::ReadBigEndian(
                  reinterpret_cast<const uint8_t*>(
                      rtcp_packet.packet_data().data() + 4));
          if (packet_ssrc != ssrc_filter)
            continue;
        }

        webrtc::test::RtpPacket packet;
        packet.length = rtcp_packet.packet_data().size();
        if (packet.length > packet.kMaxPacketBufferSize) {
          std::cout << "Skipping packet with size " << packet.length
                    << ", the maximum supported size is "
                    << packet.kMaxPacketBufferSize << std::endl;
          continue;
        }
        // For RTCP packets the original_length should be set to 0 in the
        // RTPdump format.
        packet.original_length = 0;
        packet.time_ms = event.timestamp_us() / 1000;
        memcpy(packet.data, rtcp_packet.packet_data().data(), packet.length);
        rtp_writer->WritePacket(&packet);
        rtcp_counter++;
      } else {
        std::cout << "Skipping malformed event." << std::endl;
      }
    }
  }
  std::cout << "Wrote " << rtp_counter << (header_only ? " header-only" : "")
            << " RTP packets and " << rtcp_counter << " RTCP packets to the "
            << "output file." << std::endl;
  return 0;
}
