/*
 *  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 <stdio.h>

#include <cstdint>
#include <list>
#include <memory>
#include <string>
#include <vector>

#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "api/rtp_headers.h"
#include "modules/audio_coding/neteq/tools/packet.h"
#include "modules/audio_coding/neteq/tools/rtp_file_source.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.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");

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,
                                            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,
        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::test::Packet> packet;
  while (true) {
    packet = file_source->NextPacket();
    if (!packet.get()) {
      // 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 %10u %5i %5i %2i %#08X",
            packet->header().sequenceNumber, packet->header().timestamp,
            static_cast<unsigned int>(packet->time_ms()),
            static_cast<int>(packet->virtual_packet_length_bytes()),
            packet->header().payloadType, packet->header().markerBit,
            packet->header().ssrc);
    if (print_audio_level && packet->header().extension.audio_level()) {
      fprintf(out_file, " %5d (%1i)",
              packet->header().extension.audio_level()->level(),
              packet->header().extension.audio_level()->voice_activity());
    }
    if (print_abs_send_time && packet->header().extension.hasAbsoluteSendTime) {
      if (cycles == -1) {
        // Initialize.
        max_abs_send_time = packet->header().extension.absoluteSendTime;
        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>(
              (packet->header().extension.absoluteSendTime << 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 (packet->header().extension.absoluteSendTime < max_abs_send_time) {
          // Wrap detected.
          cycles++;
        }
        max_abs_send_time = packet->header().extension.absoluteSendTime;
      }
      // 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>(packet->header().extension.absoluteSendTime) /
              262144 +
          64.0 * cycles;
      fprintf(out_file, " %11f", send_time_seconds);
    }
    fprintf(out_file, "\n");

    if (packet->header().payloadType == absl::GetFlag(FLAGS_red)) {
      std::list<webrtc::RTPHeader*> red_headers;
      packet->ExtractRedHeaders(&red_headers);
      while (!red_headers.empty()) {
        webrtc::RTPHeader* red = red_headers.front();
        RTC_DCHECK(red);
        fprintf(out_file, "* %5u %10u %10u %5i\n", red->sequenceNumber,
                red->timestamp, static_cast<unsigned int>(packet->time_ms()),
                red->payloadType);
        red_headers.pop_front();
        delete red;
      }
    }
  }

  fclose(out_file);

  return 0;
}
