Make rtc_event_log2text output header extensions

BUG=webrtc:none

Review-Url: https://codereview.webrtc.org/2918103002
Cr-Commit-Position: refs/heads/master@{#18530}
This commit is contained in:
ilnik
2017-06-12 01:02:46 -07:00
committed by Commit Bot
parent 3fae628094
commit a8e781aedf
4 changed files with 95 additions and 47 deletions

View File

@ -9,8 +9,10 @@
*/ */
#include <iostream> #include <iostream>
#include <map>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <utility> // pair
#include "gflags/gflags.h" #include "gflags/gflags.h"
#include "webrtc/base/checks.h" #include "webrtc/base/checks.h"
@ -439,14 +441,13 @@ int main(int argc, char* argv[]) {
size_t total_length; size_t total_length;
uint8_t header[IP_PACKET_SIZE]; uint8_t header[IP_PACKET_SIZE];
webrtc::PacketDirection direction; webrtc::PacketDirection direction;
webrtc::RtpHeaderExtensionMap* extension_map = parsed_stream.GetRtpHeader(
parsed_stream.GetRtpHeader(i, &direction, header, &header_length, i, &direction, header, &header_length, &total_length);
&total_length);
// Parse header to get SSRC and RTP time. // Parse header to get SSRC and RTP time.
webrtc::RtpUtility::RtpHeaderParser rtp_parser(header, header_length); webrtc::RtpUtility::RtpHeaderParser rtp_parser(header, header_length);
webrtc::RTPHeader parsed_header; webrtc::RTPHeader parsed_header;
rtp_parser.Parse(&parsed_header); rtp_parser.Parse(&parsed_header, extension_map);
MediaType media_type = MediaType media_type =
parsed_stream.GetMediaType(parsed_header.ssrc, direction); parsed_stream.GetMediaType(parsed_header.ssrc, direction);
@ -456,7 +457,31 @@ int main(int argc, char* argv[]) {
std::cout << parsed_stream.GetTimestamp(i) << "\tRTP" std::cout << parsed_stream.GetTimestamp(i) << "\tRTP"
<< StreamInfo(direction, media_type) << StreamInfo(direction, media_type)
<< "\tssrc=" << parsed_header.ssrc << "\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<int>(parsed_header.extension.videoContentType);
}
if (parsed_header.extension.hasVideoRotation) {
std::cout << "\tRotation="
<< static_cast<int>(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 && if (!FLAGS_nortcp &&
parsed_stream.GetEventType(i) == parsed_stream.GetEventType(i) ==

View File

@ -158,6 +158,12 @@ bool ParsedRtcEventLog::ParseStream(std::istream& stream) {
// Check whether we have reached end of file. // Check whether we have reached end of file.
stream.peek(); stream.peek();
if (stream.eof()) { 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; return true;
} }
@ -204,34 +210,41 @@ bool ParsedRtcEventLog::ParseStream(std::istream& stream) {
case VIDEO_RECEIVER_CONFIG_EVENT: { case VIDEO_RECEIVER_CONFIG_EVENT: {
rtclog::StreamConfig config = GetVideoReceiveConfig(event); rtclog::StreamConfig config = GetVideoReceiveConfig(event);
streams_.emplace_back(config.remote_ssrc, MediaType::VIDEO, streams_.emplace_back(config.remote_ssrc, MediaType::VIDEO,
kIncomingPacket); kIncomingPacket,
RtpHeaderExtensionMap(config.rtp_extensions));
streams_.emplace_back(config.local_ssrc, MediaType::VIDEO, streams_.emplace_back(config.local_ssrc, MediaType::VIDEO,
kOutgoingPacket); kOutgoingPacket,
RtpHeaderExtensionMap(config.rtp_extensions));
break; break;
} }
case VIDEO_SENDER_CONFIG_EVENT: { case VIDEO_SENDER_CONFIG_EVENT: {
std::vector<rtclog::StreamConfig> configs = GetVideoSendConfig(event); std::vector<rtclog::StreamConfig> configs = GetVideoSendConfig(event);
for (size_t i = 0; i < configs.size(); i++) { for (size_t i = 0; i < configs.size(); i++) {
streams_.emplace_back(configs[i].local_ssrc, MediaType::VIDEO, streams_.emplace_back(
kOutgoingPacket); configs[i].local_ssrc, MediaType::VIDEO, kOutgoingPacket,
RtpHeaderExtensionMap(configs[i].rtp_extensions));
streams_.emplace_back(configs[i].rtx_ssrc, MediaType::VIDEO, streams_.emplace_back(
kOutgoingPacket); configs[i].rtx_ssrc, MediaType::VIDEO, kOutgoingPacket,
RtpHeaderExtensionMap(configs[i].rtp_extensions));
} }
break; break;
} }
case AUDIO_RECEIVER_CONFIG_EVENT: { case AUDIO_RECEIVER_CONFIG_EVENT: {
rtclog::StreamConfig config = GetAudioReceiveConfig(event); rtclog::StreamConfig config = GetAudioReceiveConfig(event);
streams_.emplace_back(config.remote_ssrc, MediaType::AUDIO, streams_.emplace_back(config.remote_ssrc, MediaType::AUDIO,
kIncomingPacket); kIncomingPacket,
RtpHeaderExtensionMap(config.rtp_extensions));
streams_.emplace_back(config.local_ssrc, MediaType::AUDIO, streams_.emplace_back(config.local_ssrc, MediaType::AUDIO,
kOutgoingPacket); kOutgoingPacket,
RtpHeaderExtensionMap(config.rtp_extensions));
break; break;
} }
case AUDIO_SENDER_CONFIG_EVENT: { case AUDIO_SENDER_CONFIG_EVENT: {
rtclog::StreamConfig config = GetAudioSendConfig(event); rtclog::StreamConfig config = GetAudioSendConfig(event);
streams_.emplace_back(config.local_ssrc, MediaType::AUDIO, streams_.emplace_back(config.local_ssrc, MediaType::AUDIO,
kOutgoingPacket); kOutgoingPacket,
RtpHeaderExtensionMap(config.rtp_extensions));
break; break;
} }
default: default:
@ -262,11 +275,12 @@ ParsedRtcEventLog::EventType ParsedRtcEventLog::GetEventType(
} }
// The header must have space for at least IP_PACKET_SIZE bytes. // The header must have space for at least IP_PACKET_SIZE bytes.
void ParsedRtcEventLog::GetRtpHeader(size_t index, webrtc::RtpHeaderExtensionMap* ParsedRtcEventLog::GetRtpHeader(
PacketDirection* incoming, size_t index,
uint8_t* header, PacketDirection* incoming,
size_t* header_length, uint8_t* header,
size_t* total_length) const { size_t* header_length,
size_t* total_length) const {
RTC_CHECK_LT(index, GetNumberOfEvents()); RTC_CHECK_LT(index, GetNumberOfEvents());
const rtclog::Event& event = events_[index]; const rtclog::Event& event = events_[index];
RTC_CHECK(event.has_type()); RTC_CHECK(event.has_type());
@ -295,7 +309,15 @@ void ParsedRtcEventLog::GetRtpHeader(size_t index,
RTC_CHECK_LE(rtp_packet.header().size(), RTC_CHECK_LE(rtp_packet.header().size(),
static_cast<size_t>(IP_PACKET_SIZE)); static_cast<size_t>(IP_PACKET_SIZE));
memcpy(header, rtp_packet.header().data(), rtp_packet.header().size()); memcpy(header, rtp_packet.header().data(), rtp_packet.header().size());
uint32_t ssrc = ByteReader<uint32_t>::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. // The packet must have space for at least IP_PACKET_SIZE bytes.

View File

@ -10,11 +10,15 @@
#ifndef WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_PARSER_H_ #ifndef WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_PARSER_H_
#define WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_PARSER_H_ #define WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_PARSER_H_
#include <map>
#include <string> #include <string>
#include <utility> // pair
#include <vector> #include <vector>
#include "webrtc/base/ignore_wundef.h" #include "webrtc/base/ignore_wundef.h"
#include "webrtc/logging/rtc_event_log/rtc_event_log.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_receive_stream.h"
#include "webrtc/video_send_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 // parameters. Each output parameter can be set to nullptr if that value
// isn't needed. // isn't needed.
// NB: The header must have space for at least IP_PACKET_SIZE bytes. // NB: The header must have space for at least IP_PACKET_SIZE bytes.
void GetRtpHeader(size_t index, // Returns: a pointer to a header extensions map acquired from parsing
PacketDirection* incoming, // corresponding Audio/Video Sender/Receiver config events.
uint8_t* header, // Warning: if the same SSRC is reused by both video and audio streams during
size_t* header_length, // call, extensions maps may be incorrect (the last one would be returned).
size_t* total_length) const; 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|, // Reads packet, direction and packet length from the RTCP event at |index|,
// and stores the values in the corresponding output parameters. // and stores the values in the corresponding output parameters.
@ -178,15 +186,25 @@ class ParsedRtcEventLog {
struct Stream { struct Stream {
Stream(uint32_t ssrc, Stream(uint32_t ssrc,
MediaType media_type, MediaType media_type,
webrtc::PacketDirection direction) webrtc::PacketDirection direction,
: ssrc(ssrc), media_type(media_type), direction(direction) {} webrtc::RtpHeaderExtensionMap map)
: ssrc(ssrc),
media_type(media_type),
direction(direction),
rtp_extensions_map(map) {}
uint32_t ssrc; uint32_t ssrc;
MediaType media_type; MediaType media_type;
webrtc::PacketDirection direction; webrtc::PacketDirection direction;
webrtc::RtpHeaderExtensionMap rtp_extensions_map;
}; };
// All configured streams found in the event log. // All configured streams found in the event log.
std::vector<Stream> streams_; std::vector<Stream> streams_;
// To find configured extensions map for given stream, what are needed to
// parse a header.
typedef std::pair<uint32_t, webrtc::PacketDirection> StreamId;
std::map<StreamId, webrtc::RtpHeaderExtensionMap*> rtp_extensions_maps_;
}; };
} // namespace webrtc } // namespace webrtc

View File

@ -289,10 +289,6 @@ EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log)
uint64_t first_timestamp = std::numeric_limits<uint64_t>::max(); uint64_t first_timestamp = std::numeric_limits<uint64_t>::max();
uint64_t last_timestamp = std::numeric_limits<uint64_t>::min(); uint64_t last_timestamp = std::numeric_limits<uint64_t>::min();
// Maps a stream identifier consisting of ssrc and direction
// to the header extensions used by that stream,
std::map<StreamId, RtpHeaderExtensionMap> extension_maps;
PacketDirection direction; PacketDirection direction;
uint8_t header[IP_PACKET_SIZE]; uint8_t header[IP_PACKET_SIZE];
size_t header_length; size_t header_length;
@ -323,11 +319,8 @@ EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log)
case ParsedRtcEventLog::VIDEO_RECEIVER_CONFIG_EVENT: { case ParsedRtcEventLog::VIDEO_RECEIVER_CONFIG_EVENT: {
rtclog::StreamConfig config = parsed_log_.GetVideoReceiveConfig(i); rtclog::StreamConfig config = parsed_log_.GetVideoReceiveConfig(i);
StreamId stream(config.remote_ssrc, kIncomingPacket); StreamId stream(config.remote_ssrc, kIncomingPacket);
extension_maps[stream] = RtpHeaderExtensionMap(config.rtp_extensions);
video_ssrcs_.insert(stream); video_ssrcs_.insert(stream);
StreamId rtx_stream(config.rtx_ssrc, kIncomingPacket); StreamId rtx_stream(config.rtx_ssrc, kIncomingPacket);
extension_maps[rtx_stream] =
RtpHeaderExtensionMap(config.rtp_extensions);
video_ssrcs_.insert(rtx_stream); video_ssrcs_.insert(rtx_stream);
rtx_ssrcs_.insert(rtx_stream); rtx_ssrcs_.insert(rtx_stream);
break; break;
@ -337,12 +330,8 @@ EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log)
parsed_log_.GetVideoSendConfig(i); parsed_log_.GetVideoSendConfig(i);
for (const auto& config : configs) { for (const auto& config : configs) {
StreamId stream(config.local_ssrc, kOutgoingPacket); StreamId stream(config.local_ssrc, kOutgoingPacket);
extension_maps[stream] =
RtpHeaderExtensionMap(config.rtp_extensions);
video_ssrcs_.insert(stream); video_ssrcs_.insert(stream);
StreamId rtx_stream(config.rtx_ssrc, kOutgoingPacket); StreamId rtx_stream(config.rtx_ssrc, kOutgoingPacket);
extension_maps[rtx_stream] =
RtpHeaderExtensionMap(config.rtp_extensions);
video_ssrcs_.insert(rtx_stream); video_ssrcs_.insert(rtx_stream);
rtx_ssrcs_.insert(rtx_stream); rtx_ssrcs_.insert(rtx_stream);
} }
@ -351,28 +340,21 @@ EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log)
case ParsedRtcEventLog::AUDIO_RECEIVER_CONFIG_EVENT: { case ParsedRtcEventLog::AUDIO_RECEIVER_CONFIG_EVENT: {
rtclog::StreamConfig config = parsed_log_.GetAudioReceiveConfig(i); rtclog::StreamConfig config = parsed_log_.GetAudioReceiveConfig(i);
StreamId stream(config.remote_ssrc, kIncomingPacket); StreamId stream(config.remote_ssrc, kIncomingPacket);
extension_maps[stream] = RtpHeaderExtensionMap(config.rtp_extensions);
audio_ssrcs_.insert(stream); audio_ssrcs_.insert(stream);
break; break;
} }
case ParsedRtcEventLog::AUDIO_SENDER_CONFIG_EVENT: { case ParsedRtcEventLog::AUDIO_SENDER_CONFIG_EVENT: {
rtclog::StreamConfig config = parsed_log_.GetAudioSendConfig(i); rtclog::StreamConfig config = parsed_log_.GetAudioSendConfig(i);
StreamId stream(config.local_ssrc, kOutgoingPacket); StreamId stream(config.local_ssrc, kOutgoingPacket);
extension_maps[stream] = RtpHeaderExtensionMap(config.rtp_extensions);
audio_ssrcs_.insert(stream); audio_ssrcs_.insert(stream);
break; break;
} }
case ParsedRtcEventLog::RTP_EVENT: { case ParsedRtcEventLog::RTP_EVENT: {
parsed_log_.GetRtpHeader(i, &direction, header, &header_length, RtpHeaderExtensionMap* extension_map = parsed_log_.GetRtpHeader(
&total_length); i, &direction, header, &header_length, &total_length);
// Parse header to get SSRC.
RtpUtility::RtpHeaderParser rtp_parser(header, header_length); RtpUtility::RtpHeaderParser rtp_parser(header, header_length);
RTPHeader parsed_header; RTPHeader parsed_header;
rtp_parser.Parse(&parsed_header); if (extension_map != nullptr) {
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];
rtp_parser.Parse(&parsed_header, extension_map); rtp_parser.Parse(&parsed_header, extension_map);
} else { } else {
// Use the default extension map. // Use the default extension map.
@ -382,6 +364,7 @@ EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log)
rtp_parser.Parse(&parsed_header, &default_extension_map); rtp_parser.Parse(&parsed_header, &default_extension_map);
} }
uint64_t timestamp = parsed_log_.GetTimestamp(i); uint64_t timestamp = parsed_log_.GetTimestamp(i);
StreamId stream(parsed_header.ssrc, direction);
rtp_packets_[stream].push_back( rtp_packets_[stream].push_back(
LoggedRtpPacket(timestamp, parsed_header, total_length)); LoggedRtpPacket(timestamp, parsed_header, total_length));
break; break;