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:
@ -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) ==
|
||||||
|
|||||||
@ -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.
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user