/*
 *  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_legacy/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;
}
