blob: e71aee0202dfef194d0f13fc1ba2187305cfb045 [file] [log] [blame]
henrik.lundin@webrtc.org184b9132014-04-02 20:56:17 +00001/*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include <assert.h>
12#include <stdio.h>
kwiberg2d0c3322016-02-14 09:28:33 -080013
14#include <memory>
henrik.lundin@webrtc.org184b9132014-04-02 20:56:17 +000015#include <vector>
16
Mirko Bonadei14be7992019-06-27 15:59:09 +020017#include "absl/flags/flag.h"
18#include "absl/flags/parse.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "modules/audio_coding/neteq/tools/packet.h"
20#include "modules/audio_coding/neteq/tools/rtp_file_source.h"
21#include "rtc_base/flags.h"
henrik.lundin@webrtc.org184b9132014-04-02 20:56:17 +000022
Mirko Bonadei14be7992019-06-27 15:59:09 +020023ABSL_FLAG(int, red, 117, "RTP payload type for RED");
24ABSL_FLAG(int,
25 audio_level,
26 -1,
27 "Extension ID for audio level (RFC 6464); "
28 "-1 not to print audio level");
29ABSL_FLAG(int,
30 abs_send_time,
31 -1,
32 "Extension ID for absolute sender time; "
33 "-1 not to print absolute send time");
henrik.lundin@webrtc.org184b9132014-04-02 20:56:17 +000034
35int main(int argc, char* argv[]) {
Mirko Bonadei14be7992019-06-27 15:59:09 +020036 std::vector<char*> args = absl::ParseCommandLine(argc, argv);
henrik.lundin@webrtc.org184b9132014-04-02 20:56:17 +000037 std::string usage =
38 "Tool for parsing an RTP dump file to text output.\n"
Mirko Bonadei14be7992019-06-27 15:59:09 +020039 "Example usage:\n"
40 "./rtp_analyze input.rtp output.txt\n\n"
41 "Output is sent to stdout if no output file is given. "
oprypin6e09d872017-08-31 03:21:39 -070042 "Note that this tool can read files with or without payloads.\n";
Mirko Bonadei14be7992019-06-27 15:59:09 +020043 if (args.size() != 2 && args.size() != 3) {
oprypin6e09d872017-08-31 03:21:39 -070044 printf("%s", usage.c_str());
oprypin6e09d872017-08-31 03:21:39 -070045 return 1;
henrik.lundin@webrtc.org184b9132014-04-02 20:56:17 +000046 }
47
Mirko Bonadei14be7992019-06-27 15:59:09 +020048 RTC_CHECK(absl::GetFlag(FLAGS_red) >= 0 &&
49 absl::GetFlag(FLAGS_red) <= 127); // Payload type
50 RTC_CHECK(absl::GetFlag(FLAGS_audio_level) == -1 || // Default
51 (absl::GetFlag(FLAGS_audio_level) > 0 &&
52 absl::GetFlag(FLAGS_audio_level) <= 255)); // Extension ID
53 RTC_CHECK(absl::GetFlag(FLAGS_abs_send_time) == -1 || // Default
54 (absl::GetFlag(FLAGS_abs_send_time) > 0 &&
55 absl::GetFlag(FLAGS_abs_send_time) <= 255)); // Extension ID
oprypin6e09d872017-08-31 03:21:39 -070056
Mirko Bonadei14be7992019-06-27 15:59:09 +020057 printf("Input file: %s\n", args[1]);
kwiberg2d0c3322016-02-14 09:28:33 -080058 std::unique_ptr<webrtc::test::RtpFileSource> file_source(
Mirko Bonadei14be7992019-06-27 15:59:09 +020059 webrtc::test::RtpFileSource::Create(args[1]));
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000060 assert(file_source.get());
Henrik Lundinb0b54252015-04-17 11:47:07 +020061 // Set RTP extension IDs.
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000062 bool print_audio_level = false;
Mirko Bonadei14be7992019-06-27 15:59:09 +020063 if (absl::GetFlag(FLAGS_audio_level) != -1) {
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000064 print_audio_level = true;
65 file_source->RegisterRtpHeaderExtension(webrtc::kRtpExtensionAudioLevel,
Mirko Bonadei14be7992019-06-27 15:59:09 +020066 absl::GetFlag(FLAGS_audio_level));
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000067 }
Henrik Lundinb0b54252015-04-17 11:47:07 +020068 bool print_abs_send_time = false;
Mirko Bonadei14be7992019-06-27 15:59:09 +020069 if (absl::GetFlag(FLAGS_abs_send_time) != -1) {
Henrik Lundinb0b54252015-04-17 11:47:07 +020070 print_abs_send_time = true;
71 file_source->RegisterRtpHeaderExtension(
Mirko Bonadei14be7992019-06-27 15:59:09 +020072 webrtc::kRtpExtensionAbsoluteSendTime,
73 absl::GetFlag(FLAGS_abs_send_time));
Henrik Lundinb0b54252015-04-17 11:47:07 +020074 }
henrik.lundin@webrtc.org184b9132014-04-02 20:56:17 +000075
76 FILE* out_file;
Mirko Bonadei14be7992019-06-27 15:59:09 +020077 if (args.size() == 3) {
78 out_file = fopen(args[2], "wt");
henrik.lundin@webrtc.org184b9132014-04-02 20:56:17 +000079 if (!out_file) {
Mirko Bonadei14be7992019-06-27 15:59:09 +020080 printf("Cannot open output file %s\n", args[2]);
henrik.lundin@webrtc.org184b9132014-04-02 20:56:17 +000081 return -1;
82 }
Mirko Bonadei14be7992019-06-27 15:59:09 +020083 printf("Output file: %s\n\n", args[2]);
henrik.lundin@webrtc.org184b9132014-04-02 20:56:17 +000084 } else {
85 out_file = stdout;
86 }
87
88 // Print file header.
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000089 fprintf(out_file, "SeqNo TimeStamp SendTime Size PT M SSRC");
90 if (print_audio_level) {
91 fprintf(out_file, " AuLvl (V)");
92 }
Henrik Lundinb0b54252015-04-17 11:47:07 +020093 if (print_abs_send_time) {
94 fprintf(out_file, " AbsSendTime");
95 }
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +000096 fprintf(out_file, "\n");
henrik.lundin@webrtc.org184b9132014-04-02 20:56:17 +000097
Henrik Lundinb0b54252015-04-17 11:47:07 +020098 uint32_t max_abs_send_time = 0;
99 int cycles = -1;
kwiberg2d0c3322016-02-14 09:28:33 -0800100 std::unique_ptr<webrtc::test::Packet> packet;
henrik.lundin@webrtc.org4b133da2014-10-02 08:19:38 +0000101 while (true) {
henrik.lundin46ba49c2016-05-24 22:50:47 -0700102 packet = file_source->NextPacket();
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000103 if (!packet.get()) {
henrik.lundin@webrtc.org4b133da2014-10-02 08:19:38 +0000104 // End of file reached.
105 break;
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000106 }
Henrik Lundinb0b54252015-04-17 11:47:07 +0200107 // Write packet data to file. Use virtual_packet_length_bytes so that the
108 // correct packet sizes are printed also for RTP header-only dumps.
Yves Gerey665174f2018-06-19 15:03:05 +0200109 fprintf(out_file, "%5u %10u %10u %5i %5i %2i %#08X",
110 packet->header().sequenceNumber, packet->header().timestamp,
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000111 static_cast<unsigned int>(packet->time_ms()),
Henrik Lundinb0b54252015-04-17 11:47:07 +0200112 static_cast<int>(packet->virtual_packet_length_bytes()),
Yves Gerey665174f2018-06-19 15:03:05 +0200113 packet->header().payloadType, packet->header().markerBit,
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000114 packet->header().ssrc);
115 if (print_audio_level && packet->header().extension.hasAudioLevel) {
Yves Gerey665174f2018-06-19 15:03:05 +0200116 fprintf(out_file, " %5u (%1i)", packet->header().extension.audioLevel,
Minyue4cee4192015-08-10 15:08:36 +0200117 packet->header().extension.voiceActivity);
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000118 }
Henrik Lundinb0b54252015-04-17 11:47:07 +0200119 if (print_abs_send_time && packet->header().extension.hasAbsoluteSendTime) {
120 if (cycles == -1) {
121 // Initialize.
122 max_abs_send_time = packet->header().extension.absoluteSendTime;
123 cycles = 0;
124 }
125 // Abs sender time is 24 bit 6.18 fixed point. Shift by 8 to normalize to
126 // 32 bits (unsigned). Calculate the difference between this packet's
127 // send time and the maximum observed. Cast to signed 32-bit to get the
128 // desired wrap-around behavior.
129 if (static_cast<int32_t>(
130 (packet->header().extension.absoluteSendTime << 8) -
131 (max_abs_send_time << 8)) >= 0) {
132 // The difference is non-negative, meaning that this packet is newer
133 // than the previously observed maximum absolute send time.
134 if (packet->header().extension.absoluteSendTime < max_abs_send_time) {
135 // Wrap detected.
136 cycles++;
137 }
138 max_abs_send_time = packet->header().extension.absoluteSendTime;
139 }
140 // Abs sender time is 24 bit 6.18 fixed point. Divide by 2^18 to convert
141 // to floating point representation.
142 double send_time_seconds =
143 static_cast<double>(packet->header().extension.absoluteSendTime) /
144 262144 +
145 64.0 * cycles;
146 fprintf(out_file, " %11f", send_time_seconds);
147 }
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000148 fprintf(out_file, "\n");
149
Mirko Bonadei14be7992019-06-27 15:59:09 +0200150 if (packet->header().payloadType == absl::GetFlag(FLAGS_red)) {
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000151 std::list<webrtc::RTPHeader*> red_headers;
152 packet->ExtractRedHeaders(&red_headers);
153 while (!red_headers.empty()) {
154 webrtc::RTPHeader* red = red_headers.front();
155 assert(red);
Yves Gerey665174f2018-06-19 15:03:05 +0200156 fprintf(out_file, "* %5u %10u %10u %5i\n", red->sequenceNumber,
157 red->timestamp, static_cast<unsigned int>(packet->time_ms()),
henrik.lundin@webrtc.org810acbc2014-04-14 18:42:23 +0000158 red->payloadType);
159 red_headers.pop_front();
160 delete red;
henrik.lundin@webrtc.org184b9132014-04-02 20:56:17 +0000161 }
henrik.lundin@webrtc.org184b9132014-04-02 20:56:17 +0000162 }
163 }
164
henrik.lundin@webrtc.org184b9132014-04-02 20:56:17 +0000165 fclose(out_file);
166
167 return 0;
168}