/*
 *  Copyright (c) 2012 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 <algorithm>
#include <cstdint>
#include <cstdio>
#include <memory>
#include <string>
#include <vector>

#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "api/rtp_header_extension_id.h"
#include "api/rtp_headers.h"
#include "modules/audio_coding/neteq/tools/rtp_file_source.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "rtc_base/checks.h"

ABSL_FLAG(int, red, 117, "RTP payload type for RED");
ABSL_FLAG(int,
          audio_level,
          -1,
          "Extension ID for audio level (RFC 6464); "
          "-1 not to print audio level");
ABSL_FLAG(int,
          abs_send_time,
          -1,
          "Extension ID for absolute sender time; "
          "-1 not to print absolute send time");

namespace {

struct RedHeader {
  uint32_t rtp_timestamp;
  int payload_type;
};
std::vector<RedHeader> ExtractRedHeaders(const webrtc::RtpPacket& packet) {
  //
  //  0                   1                    2                   3
  //  0 1 2 3 4 5 6 7 8 9 0 1 2 3  4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  // |1|   block PT  |  timestamp offset         |   block length    |
  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  // |1|    ...                                                      |
  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  // |0|   block PT  |
  // +-+-+-+-+-+-+-+-+
  //
  const uint8_t* payload_ptr = packet.payload().data();
  const uint8_t* payload_end_ptr =
      packet.payload().data() + packet.payload().size();

  // Find all RED headers with the extension bit set to 1. That is, all headers
  // but the last one.
  std::vector<RedHeader> red_headers;
  while ((payload_ptr < payload_end_ptr) && (*payload_ptr & 0x80)) {
    RedHeader header;
    header.payload_type = payload_ptr[0] & 0x7F;
    uint32_t offset = (payload_ptr[1] << 6) + ((payload_ptr[2] & 0xFC) >> 2);
    header.rtp_timestamp = packet.Timestamp() - offset;
    red_headers.push_back(header);
    payload_ptr += 4;
  }
  // Last header.
  RTC_DCHECK_LT(payload_ptr, payload_end_ptr);
  if (payload_ptr >= payload_end_ptr) {
    return {};  // Payload too short.
  }
  RedHeader header;
  header.payload_type = payload_ptr[0] & 0x7F;
  header.rtp_timestamp = packet.Timestamp();
  red_headers.push_back(header);
  std::reverse(red_headers.begin(), red_headers.end());
  return red_headers;
}

}  // namespace

int main(int argc, char* argv[]) {
  std::vector<char*> args = absl::ParseCommandLine(argc, argv);
  std::string usage =
      "Tool for parsing an RTP dump file to text output.\n"
      "Example usage:\n"
      "./rtp_analyze input.rtp output.txt\n\n"
      "Output is sent to stdout if no output file is given. "
      "Note that this tool can read files with or without payloads.\n";
  if (args.size() != 2 && args.size() != 3) {
    printf("%s", usage.c_str());
    return 1;
  }

  RTC_CHECK(absl::GetFlag(FLAGS_red) >= 0 &&
            absl::GetFlag(FLAGS_red) <= 127);          // Payload type
  RTC_CHECK(absl::GetFlag(FLAGS_audio_level) == -1 ||  // Default
            (absl::GetFlag(FLAGS_audio_level) > 0 &&
             absl::GetFlag(FLAGS_audio_level) <= 255));  // Extension ID
  RTC_CHECK(absl::GetFlag(FLAGS_abs_send_time) == -1 ||  // Default
            (absl::GetFlag(FLAGS_abs_send_time) > 0 &&
             absl::GetFlag(FLAGS_abs_send_time) <= 255));  // Extension ID

  printf("Input file: %s\n", args[1]);
  std::unique_ptr<webrtc::test::RtpFileSource> file_source(
      webrtc::test::RtpFileSource::Create(args[1]));
  RTC_DCHECK(file_source.get());
  // Set RTP extension IDs.
  bool print_audio_level = false;
  if (absl::GetFlag(FLAGS_audio_level) != -1) {
    print_audio_level = true;
    file_source->RegisterRtpHeaderExtension(
        webrtc::kRtpExtensionAudioLevel,
        webrtc::RtpHeaderExtensionId(absl::GetFlag(FLAGS_audio_level)));
  }
  bool print_abs_send_time = false;
  if (absl::GetFlag(FLAGS_abs_send_time) != -1) {
    print_abs_send_time = true;
    file_source->RegisterRtpHeaderExtension(
        webrtc::kRtpExtensionAbsoluteSendTime,
        webrtc::RtpHeaderExtensionId(absl::GetFlag(FLAGS_abs_send_time)));
  }

  FILE* out_file;
  if (args.size() == 3) {
    out_file = fopen(args[2], "wt");
    if (!out_file) {
      printf("Cannot open output file %s\n", args[2]);
      return -1;
    }
    printf("Output file: %s\n\n", args[2]);
  } else {
    out_file = stdout;
  }

  // Print file header.
  fprintf(out_file, "SeqNo  TimeStamp   SendTime  Size    PT  M       SSRC");
  if (print_audio_level) {
    fprintf(out_file, " AuLvl (V)");
  }
  if (print_abs_send_time) {
    fprintf(out_file, " AbsSendTime");
  }
  fprintf(out_file, "\n");

  uint32_t max_abs_send_time = 0;
  int cycles = -1;
  std::unique_ptr<webrtc::RtpPacketReceived> packet;
  while (true) {
    packet = file_source->NextPacket();
    if (!packet) {
      // End of file reached.
      break;
    }
    // Write packet data to file. Use virtual_packet_length_bytes so that the
    // correct packet sizes are printed also for RTP header-only dumps.
    fprintf(out_file, "%5u %10u %10i %5zu %5i %2i %#08X",
            packet->SequenceNumber(), packet->Timestamp(),
            packet->arrival_time().ms<int>(), packet->size(),
            packet->PayloadType(), packet->Marker(), packet->Ssrc());
    webrtc::AudioLevel audio_level;
    if (print_audio_level &&
        packet->GetExtension<webrtc::AudioLevelExtension>(&audio_level)) {
      fprintf(out_file, " %5d (%1i)", audio_level.level(),
              audio_level.voice_activity());
    }
    uint32_t abs_sent_time;
    if (print_abs_send_time &&
        packet->GetExtension<webrtc::AbsoluteSendTime>(&abs_sent_time)) {
      if (cycles == -1) {
        // Initialize.
        max_abs_send_time = abs_sent_time;
        cycles = 0;
      }
      // Abs sender time is 24 bit 6.18 fixed point. Shift by 8 to normalize to
      // 32 bits (unsigned). Calculate the difference between this packet's
      // send time and the maximum observed. Cast to signed 32-bit to get the
      // desired wrap-around behavior.
      if (static_cast<int32_t>((abs_sent_time << 8) -
                               (max_abs_send_time << 8)) >= 0) {
        // The difference is non-negative, meaning that this packet is newer
        // than the previously observed maximum absolute send time.
        if (abs_sent_time < max_abs_send_time) {
          // Wrap detected.
          cycles++;
        }
        max_abs_send_time = abs_sent_time;
      }
      // Abs sender time is 24 bit 6.18 fixed point. Divide by 2^18 to convert
      // to floating point representation.
      double send_time_seconds =
          static_cast<double>(abs_sent_time) / 262144 + 64.0 * cycles;
      fprintf(out_file, " %11f", send_time_seconds);
    }
    fprintf(out_file, "\n");

    if (packet->PayloadType() == absl::GetFlag(FLAGS_red)) {
      for (const RedHeader& red : ExtractRedHeaders(*packet)) {
        fprintf(out_file, "* %5u %10u %10i %5i\n", packet->SequenceNumber(),
                red.rtp_timestamp, packet->arrival_time().ms<int>(),
                red.payload_type);
      }
    }
  }

  fclose(out_file);

  return 0;
}
