diff --git a/webrtc/logging/rtc_event_log/rtc_event_log2text.cc b/webrtc/logging/rtc_event_log/rtc_event_log2text.cc index 1dcc78b976..7467ae62ab 100644 --- a/webrtc/logging/rtc_event_log/rtc_event_log2text.cc +++ b/webrtc/logging/rtc_event_log/rtc_event_log2text.cc @@ -9,8 +9,10 @@ */ #include +#include #include #include +#include // pair #include "gflags/gflags.h" #include "webrtc/base/checks.h" @@ -439,14 +441,13 @@ int main(int argc, char* argv[]) { size_t total_length; uint8_t header[IP_PACKET_SIZE]; webrtc::PacketDirection direction; - - parsed_stream.GetRtpHeader(i, &direction, header, &header_length, - &total_length); + webrtc::RtpHeaderExtensionMap* extension_map = parsed_stream.GetRtpHeader( + i, &direction, header, &header_length, &total_length); // Parse header to get SSRC and RTP time. webrtc::RtpUtility::RtpHeaderParser rtp_parser(header, header_length); webrtc::RTPHeader parsed_header; - rtp_parser.Parse(&parsed_header); + rtp_parser.Parse(&parsed_header, extension_map); MediaType media_type = parsed_stream.GetMediaType(parsed_header.ssrc, direction); @@ -456,7 +457,31 @@ int main(int argc, char* argv[]) { std::cout << parsed_stream.GetTimestamp(i) << "\tRTP" << StreamInfo(direction, media_type) << "\tssrc=" << parsed_header.ssrc - << "\ttimestamp=" << parsed_header.timestamp << std::endl; + << "\ttimestamp=" << parsed_header.timestamp; + if (parsed_header.extension.hasAbsoluteSendTime) { + std::cout << "\tAbsSendTime=" + << parsed_header.extension.absoluteSendTime; + } + if (parsed_header.extension.hasVideoContentType) { + std::cout << "\tContentType=" + << static_cast(parsed_header.extension.videoContentType); + } + if (parsed_header.extension.hasVideoRotation) { + std::cout << "\tRotation=" + << static_cast(parsed_header.extension.videoRotation); + } + if (parsed_header.extension.hasTransportSequenceNumber) { + std::cout << "\tTransportSeq=" + << parsed_header.extension.transportSequenceNumber; + } + if (parsed_header.extension.hasTransmissionTimeOffset) { + std::cout << "\tTransmTimeOffset=" + << parsed_header.extension.transmissionTimeOffset; + } + if (parsed_header.extension.hasAudioLevel) { + std::cout << "\tAudioLevel=" << parsed_header.extension.audioLevel; + } + std::cout << std::endl; } if (!FLAGS_nortcp && parsed_stream.GetEventType(i) == diff --git a/webrtc/logging/rtc_event_log/rtc_event_log_parser.cc b/webrtc/logging/rtc_event_log/rtc_event_log_parser.cc index d2cdcd5b5d..78dd4fdce7 100644 --- a/webrtc/logging/rtc_event_log/rtc_event_log_parser.cc +++ b/webrtc/logging/rtc_event_log/rtc_event_log_parser.cc @@ -158,6 +158,12 @@ bool ParsedRtcEventLog::ParseStream(std::istream& stream) { // Check whether we have reached end of file. stream.peek(); if (stream.eof()) { + // Process all extensions maps for faster look-up later. + for (auto& event_stream : streams_) { + rtp_extensions_maps_[StreamId(event_stream.ssrc, + event_stream.direction)] = + &event_stream.rtp_extensions_map; + } return true; } @@ -204,34 +210,41 @@ bool ParsedRtcEventLog::ParseStream(std::istream& stream) { case VIDEO_RECEIVER_CONFIG_EVENT: { rtclog::StreamConfig config = GetVideoReceiveConfig(event); streams_.emplace_back(config.remote_ssrc, MediaType::VIDEO, - kIncomingPacket); + kIncomingPacket, + RtpHeaderExtensionMap(config.rtp_extensions)); streams_.emplace_back(config.local_ssrc, MediaType::VIDEO, - kOutgoingPacket); + kOutgoingPacket, + RtpHeaderExtensionMap(config.rtp_extensions)); break; } case VIDEO_SENDER_CONFIG_EVENT: { std::vector configs = GetVideoSendConfig(event); for (size_t i = 0; i < configs.size(); i++) { - streams_.emplace_back(configs[i].local_ssrc, MediaType::VIDEO, - kOutgoingPacket); + streams_.emplace_back( + configs[i].local_ssrc, MediaType::VIDEO, kOutgoingPacket, + RtpHeaderExtensionMap(configs[i].rtp_extensions)); - streams_.emplace_back(configs[i].rtx_ssrc, MediaType::VIDEO, - kOutgoingPacket); + streams_.emplace_back( + configs[i].rtx_ssrc, MediaType::VIDEO, kOutgoingPacket, + RtpHeaderExtensionMap(configs[i].rtp_extensions)); } break; } case AUDIO_RECEIVER_CONFIG_EVENT: { rtclog::StreamConfig config = GetAudioReceiveConfig(event); streams_.emplace_back(config.remote_ssrc, MediaType::AUDIO, - kIncomingPacket); + kIncomingPacket, + RtpHeaderExtensionMap(config.rtp_extensions)); streams_.emplace_back(config.local_ssrc, MediaType::AUDIO, - kOutgoingPacket); + kOutgoingPacket, + RtpHeaderExtensionMap(config.rtp_extensions)); break; } case AUDIO_SENDER_CONFIG_EVENT: { rtclog::StreamConfig config = GetAudioSendConfig(event); streams_.emplace_back(config.local_ssrc, MediaType::AUDIO, - kOutgoingPacket); + kOutgoingPacket, + RtpHeaderExtensionMap(config.rtp_extensions)); break; } default: @@ -262,11 +275,12 @@ ParsedRtcEventLog::EventType ParsedRtcEventLog::GetEventType( } // The header must have space for at least IP_PACKET_SIZE bytes. -void ParsedRtcEventLog::GetRtpHeader(size_t index, - PacketDirection* incoming, - uint8_t* header, - size_t* header_length, - size_t* total_length) const { +webrtc::RtpHeaderExtensionMap* ParsedRtcEventLog::GetRtpHeader( + size_t index, + PacketDirection* incoming, + uint8_t* header, + size_t* header_length, + size_t* total_length) const { RTC_CHECK_LT(index, GetNumberOfEvents()); const rtclog::Event& event = events_[index]; RTC_CHECK(event.has_type()); @@ -295,7 +309,15 @@ void ParsedRtcEventLog::GetRtpHeader(size_t index, RTC_CHECK_LE(rtp_packet.header().size(), static_cast(IP_PACKET_SIZE)); memcpy(header, rtp_packet.header().data(), rtp_packet.header().size()); + uint32_t ssrc = ByteReader::ReadBigEndian(header + 8); + StreamId stream_id( + ssrc, rtp_packet.incoming() ? kIncomingPacket : kOutgoingPacket); + auto it = rtp_extensions_maps_.find(stream_id); + if (it != rtp_extensions_maps_.end()) { + return it->second; + } } + return nullptr; } // The packet must have space for at least IP_PACKET_SIZE bytes. diff --git a/webrtc/logging/rtc_event_log/rtc_event_log_parser.h b/webrtc/logging/rtc_event_log/rtc_event_log_parser.h index 7a17f32d27..58e0dc2b3f 100644 --- a/webrtc/logging/rtc_event_log/rtc_event_log_parser.h +++ b/webrtc/logging/rtc_event_log/rtc_event_log_parser.h @@ -10,11 +10,15 @@ #ifndef WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_PARSER_H_ #define WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_PARSER_H_ +#include #include +#include // pair #include #include "webrtc/base/ignore_wundef.h" #include "webrtc/logging/rtc_event_log/rtc_event_log.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h" #include "webrtc/video_receive_stream.h" #include "webrtc/video_send_stream.h" @@ -99,11 +103,15 @@ class ParsedRtcEventLog { // parameters. Each output parameter can be set to nullptr if that value // isn't needed. // NB: The header must have space for at least IP_PACKET_SIZE bytes. - void GetRtpHeader(size_t index, - PacketDirection* incoming, - uint8_t* header, - size_t* header_length, - size_t* total_length) const; + // Returns: a pointer to a header extensions map acquired from parsing + // corresponding Audio/Video Sender/Receiver config events. + // Warning: if the same SSRC is reused by both video and audio streams during + // call, extensions maps may be incorrect (the last one would be returned). + webrtc::RtpHeaderExtensionMap* GetRtpHeader(size_t index, + PacketDirection* incoming, + uint8_t* header, + size_t* header_length, + size_t* total_length) const; // Reads packet, direction and packet length from the RTCP event at |index|, // and stores the values in the corresponding output parameters. @@ -178,15 +186,25 @@ class ParsedRtcEventLog { struct Stream { Stream(uint32_t ssrc, MediaType media_type, - webrtc::PacketDirection direction) - : ssrc(ssrc), media_type(media_type), direction(direction) {} + webrtc::PacketDirection direction, + webrtc::RtpHeaderExtensionMap map) + : ssrc(ssrc), + media_type(media_type), + direction(direction), + rtp_extensions_map(map) {} uint32_t ssrc; MediaType media_type; webrtc::PacketDirection direction; + webrtc::RtpHeaderExtensionMap rtp_extensions_map; }; // All configured streams found in the event log. std::vector streams_; + + // To find configured extensions map for given stream, what are needed to + // parse a header. + typedef std::pair StreamId; + std::map rtp_extensions_maps_; }; } // namespace webrtc diff --git a/webrtc/tools/event_log_visualizer/analyzer.cc b/webrtc/tools/event_log_visualizer/analyzer.cc index dcff92c9d2..c4f5c7b3bf 100644 --- a/webrtc/tools/event_log_visualizer/analyzer.cc +++ b/webrtc/tools/event_log_visualizer/analyzer.cc @@ -289,10 +289,6 @@ EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log) uint64_t first_timestamp = std::numeric_limits::max(); uint64_t last_timestamp = std::numeric_limits::min(); - // Maps a stream identifier consisting of ssrc and direction - // to the header extensions used by that stream, - std::map extension_maps; - PacketDirection direction; uint8_t header[IP_PACKET_SIZE]; size_t header_length; @@ -323,11 +319,8 @@ EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log) case ParsedRtcEventLog::VIDEO_RECEIVER_CONFIG_EVENT: { rtclog::StreamConfig config = parsed_log_.GetVideoReceiveConfig(i); StreamId stream(config.remote_ssrc, kIncomingPacket); - extension_maps[stream] = RtpHeaderExtensionMap(config.rtp_extensions); video_ssrcs_.insert(stream); StreamId rtx_stream(config.rtx_ssrc, kIncomingPacket); - extension_maps[rtx_stream] = - RtpHeaderExtensionMap(config.rtp_extensions); video_ssrcs_.insert(rtx_stream); rtx_ssrcs_.insert(rtx_stream); break; @@ -337,12 +330,8 @@ EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log) parsed_log_.GetVideoSendConfig(i); for (const auto& config : configs) { StreamId stream(config.local_ssrc, kOutgoingPacket); - extension_maps[stream] = - RtpHeaderExtensionMap(config.rtp_extensions); video_ssrcs_.insert(stream); StreamId rtx_stream(config.rtx_ssrc, kOutgoingPacket); - extension_maps[rtx_stream] = - RtpHeaderExtensionMap(config.rtp_extensions); video_ssrcs_.insert(rtx_stream); rtx_ssrcs_.insert(rtx_stream); } @@ -351,28 +340,21 @@ EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log) case ParsedRtcEventLog::AUDIO_RECEIVER_CONFIG_EVENT: { rtclog::StreamConfig config = parsed_log_.GetAudioReceiveConfig(i); StreamId stream(config.remote_ssrc, kIncomingPacket); - extension_maps[stream] = RtpHeaderExtensionMap(config.rtp_extensions); audio_ssrcs_.insert(stream); break; } case ParsedRtcEventLog::AUDIO_SENDER_CONFIG_EVENT: { rtclog::StreamConfig config = parsed_log_.GetAudioSendConfig(i); StreamId stream(config.local_ssrc, kOutgoingPacket); - extension_maps[stream] = RtpHeaderExtensionMap(config.rtp_extensions); audio_ssrcs_.insert(stream); break; } case ParsedRtcEventLog::RTP_EVENT: { - parsed_log_.GetRtpHeader(i, &direction, header, &header_length, - &total_length); - // Parse header to get SSRC. + RtpHeaderExtensionMap* extension_map = parsed_log_.GetRtpHeader( + i, &direction, header, &header_length, &total_length); RtpUtility::RtpHeaderParser rtp_parser(header, header_length); RTPHeader parsed_header; - rtp_parser.Parse(&parsed_header); - StreamId stream(parsed_header.ssrc, direction); - // Look up the extension_map and parse it again to get the extensions. - if (extension_maps.count(stream) == 1) { - RtpHeaderExtensionMap* extension_map = &extension_maps[stream]; + if (extension_map != nullptr) { rtp_parser.Parse(&parsed_header, extension_map); } else { // Use the default extension map. @@ -382,6 +364,7 @@ EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log) rtp_parser.Parse(&parsed_header, &default_extension_map); } uint64_t timestamp = parsed_log_.GetTimestamp(i); + StreamId stream(parsed_header.ssrc, direction); rtp_packets_[stream].push_back( LoggedRtpPacket(timestamp, parsed_header, total_length)); break;