diff --git a/webrtc/modules/audio_coding/neteq/tools/rtp_analyze.cc b/webrtc/modules/audio_coding/neteq/tools/rtp_analyze.cc index d062b386f6..d6d1b6560a 100644 --- a/webrtc/modules/audio_coding/neteq/tools/rtp_analyze.cc +++ b/webrtc/modules/audio_coding/neteq/tools/rtp_analyze.cc @@ -38,6 +38,9 @@ static const bool red_dummy = DEFINE_int32(audio_level, 1, "Extension ID for audio level (RFC 6464)"); static const bool audio_level_dummy = google::RegisterFlagValidator(&FLAGS_audio_level, &ValidateExtensionId); +DEFINE_int32(abs_send_time, 3, "Extension ID for absolute sender time"); +static const bool abs_send_time_dummy = + google::RegisterFlagValidator(&FLAGS_abs_send_time, &ValidateExtensionId); int main(int argc, char* argv[]) { std::string program_name = argv[0]; @@ -63,13 +66,19 @@ int main(int argc, char* argv[]) { rtc::scoped_ptr file_source( webrtc::test::RtpFileSource::Create(argv[1])); assert(file_source.get()); - // Set RTP extension ID. + // Set RTP extension IDs. bool print_audio_level = false; if (!google::GetCommandLineFlagInfoOrDie("audio_level").is_default) { print_audio_level = true; file_source->RegisterRtpHeaderExtension(webrtc::kRtpExtensionAudioLevel, FLAGS_audio_level); } + bool print_abs_send_time = false; + if (!google::GetCommandLineFlagInfoOrDie("abs_send_time").is_default) { + print_abs_send_time = true; + file_source->RegisterRtpHeaderExtension( + webrtc::kRtpExtensionAbsoluteSendTime, FLAGS_abs_send_time); + } FILE* out_file; if (argc == 3) { @@ -88,8 +97,13 @@ int main(int argc, char* argv[]) { 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; rtc::scoped_ptr packet; while (true) { packet.reset(file_source->NextPacket()); @@ -97,13 +111,14 @@ int main(int argc, char* argv[]) { // End of file reached. break; } - // Write packet data to file. + // 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(packet->time_ms()), - static_cast(packet->packet_length_bytes()), + static_cast(packet->virtual_packet_length_bytes()), packet->header().payloadType, packet->header().markerBit, packet->header().ssrc); @@ -114,6 +129,35 @@ int main(int argc, char* argv[]) { packet->header().extension.audioLevel & 0x7F, (packet->header().extension.audioLevel & 0x80) == 0 ? 0 : 1); } + 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( + (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(packet->header().extension.absoluteSendTime) / + 262144 + + 64.0 * cycles; + fprintf(out_file, " %11f", send_time_seconds); + } fprintf(out_file, "\n"); if (packet->header().payloadType == FLAGS_red) {