Visualize events related to probing in the total bitrate graph.

BUG=webrtc:6984
R=terelius@webrtc.org

Review-Url: https://codereview.webrtc.org/2782553005 .
Cr-Commit-Position: refs/heads/master@{#17449}
This commit is contained in:
philipel
2017-03-29 16:28:53 +02:00
parent 6104cb7656
commit e127e7a0ed
8 changed files with 117 additions and 1 deletions

View File

@ -534,4 +534,58 @@ void ParsedRtcEventLog::GetAudioNetworkAdaptation(
rtc::Optional<float>(ana_event.uplink_packet_loss_fraction()); rtc::Optional<float>(ana_event.uplink_packet_loss_fraction());
} }
ParsedRtcEventLog::BweProbeClusterCreatedEvent
ParsedRtcEventLog::GetBweProbeClusterCreated(size_t index) const {
RTC_CHECK_LT(index, GetNumberOfEvents());
const rtclog::Event& event = events_[index];
RTC_CHECK(event.has_type());
RTC_CHECK_EQ(event.type(), rtclog::Event::BWE_PROBE_CLUSTER_CREATED_EVENT);
RTC_CHECK(event.has_probe_cluster());
const rtclog::BweProbeCluster& pcc_event = event.probe_cluster();
BweProbeClusterCreatedEvent res;
res.timestamp = GetTimestamp(index);
RTC_CHECK(pcc_event.has_id());
res.id = pcc_event.id();
RTC_CHECK(pcc_event.has_bitrate_bps());
res.bitrate_bps = pcc_event.bitrate_bps();
RTC_CHECK(pcc_event.has_min_packets());
res.min_packets = pcc_event.min_packets();
RTC_CHECK(pcc_event.has_min_bytes());
res.min_bytes = pcc_event.min_bytes();
return res;
}
ParsedRtcEventLog::BweProbeResultEvent ParsedRtcEventLog::GetBweProbeResult(
size_t index) const {
RTC_CHECK_LT(index, GetNumberOfEvents());
const rtclog::Event& event = events_[index];
RTC_CHECK(event.has_type());
RTC_CHECK_EQ(event.type(), rtclog::Event::BWE_PROBE_RESULT_EVENT);
RTC_CHECK(event.has_probe_result());
const rtclog::BweProbeResult& pr_event = event.probe_result();
BweProbeResultEvent res;
res.timestamp = GetTimestamp(index);
RTC_CHECK(pr_event.has_id());
res.id = pr_event.id();
RTC_CHECK(pr_event.has_result());
if (pr_event.result() == rtclog::BweProbeResult::SUCCESS) {
RTC_CHECK(pr_event.has_bitrate_bps());
res.bitrate_bps = rtc::Optional<uint64_t>(pr_event.bitrate_bps());
} else if (pr_event.result() ==
rtclog::BweProbeResult::INVALID_SEND_RECEIVE_INTERVAL) {
res.failure_reason =
rtc::Optional<ProbeFailureReason>(kInvalidSendReceiveInterval);
} else if (pr_event.result() ==
rtclog::BweProbeResult::INVALID_SEND_RECEIVE_RATIO) {
res.failure_reason =
rtc::Optional<ProbeFailureReason>(kInvalidSendReceiveRatio);
} else if (pr_event.result() == rtclog::BweProbeResult::TIMEOUT) {
res.failure_reason = rtc::Optional<ProbeFailureReason>(kTimeout);
} else {
RTC_NOTREACHED();
}
return res;
}
} // namespace webrtc } // namespace webrtc

View File

@ -35,6 +35,21 @@ class ParsedRtcEventLog {
friend class RtcEventLogTestHelper; friend class RtcEventLogTestHelper;
public: public:
struct BweProbeClusterCreatedEvent {
uint64_t timestamp;
uint32_t id;
uint64_t bitrate_bps;
uint32_t min_packets;
uint32_t min_bytes;
};
struct BweProbeResultEvent {
uint64_t timestamp;
uint32_t id;
rtc::Optional<uint64_t> bitrate_bps;
rtc::Optional<ProbeFailureReason> failure_reason;
};
enum EventType { enum EventType {
UNKNOWN_EVENT = 0, UNKNOWN_EVENT = 0,
LOG_START = 1, LOG_START = 1,
@ -142,6 +157,11 @@ class ParsedRtcEventLog {
size_t index, size_t index,
AudioNetworkAdaptor::EncoderRuntimeConfig* config) const; AudioNetworkAdaptor::EncoderRuntimeConfig* config) const;
ParsedRtcEventLog::BweProbeClusterCreatedEvent GetBweProbeClusterCreated(
size_t index) const;
ParsedRtcEventLog::BweProbeResultEvent GetBweProbeResult(size_t index) const;
private: private:
std::vector<rtclog::Event> events_; std::vector<rtclog::Event> events_;
}; };

View File

@ -477,9 +477,12 @@ EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log)
break; break;
} }
case ParsedRtcEventLog::BWE_PROBE_CLUSTER_CREATED_EVENT: { case ParsedRtcEventLog::BWE_PROBE_CLUSTER_CREATED_EVENT: {
bwe_probe_cluster_created_events_.push_back(
parsed_log_.GetBweProbeClusterCreated(i));
break; break;
} }
case ParsedRtcEventLog::BWE_PROBE_RESULT_EVENT: { case ParsedRtcEventLog::BWE_PROBE_RESULT_EVENT: {
bwe_probe_result_events_.push_back(parsed_log_.GetBweProbeResult(i));
break; break;
} }
case ParsedRtcEventLog::UNKNOWN_EVENT: { case ParsedRtcEventLog::UNKNOWN_EVENT: {
@ -938,7 +941,26 @@ void EventLogAnalyzer::CreateTotalBitrateGraph(
float y = static_cast<float>(bwe_update.new_bitrate) / 1000; float y = static_cast<float>(bwe_update.new_bitrate) / 1000;
time_series->points.emplace_back(x, y); time_series->points.emplace_back(x, y);
} }
TimeSeries* created_series =
plot->AddTimeSeries("Probe cluster created.", DOT_GRAPH);
for (auto& cluster : bwe_probe_cluster_created_events_) {
float x = static_cast<float>(cluster.timestamp - begin_time_) / 1000000;
float y = static_cast<float>(cluster.bitrate_bps) / 1000;
created_series->points.emplace_back(x, y);
}
TimeSeries* result_series =
plot->AddTimeSeries("Probing results.", DOT_GRAPH);
for (auto& result : bwe_probe_result_events_) {
if (result.bitrate_bps) {
float x = static_cast<float>(result.timestamp - begin_time_) / 1000000;
float y = static_cast<float>(*result.bitrate_bps) / 1000;
result_series->points.emplace_back(x, y);
}
}
} }
plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin);
plot->SetSuggestedYAxis(0, 1, "Bitrate (kbps)", kBottomMargin, kTopMargin); plot->SetSuggestedYAxis(0, 1, "Bitrate (kbps)", kBottomMargin, kTopMargin);
if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { if (desired_direction == webrtc::PacketDirection::kIncomingPacket) {

View File

@ -167,6 +167,11 @@ class EventLogAnalyzer {
std::vector<AudioNetworkAdaptationEvent> audio_network_adaptation_events_; std::vector<AudioNetworkAdaptationEvent> audio_network_adaptation_events_;
std::vector<ParsedRtcEventLog::BweProbeClusterCreatedEvent>
bwe_probe_cluster_created_events_;
std::vector<ParsedRtcEventLog::BweProbeResultEvent> bwe_probe_result_events_;
// Window and step size used for calculating moving averages, e.g. bitrate. // Window and step size used for calculating moving averages, e.g. bitrate.
// The generated data points will be |step_| microseconds apart. // The generated data points will be |step_| microseconds apart.
// Only events occuring at most |window_duration_| microseconds before the // Only events occuring at most |window_duration_| microseconds before the

View File

@ -10,6 +10,7 @@ message ChartStyle {
LINE_CHART = 1; LINE_CHART = 1;
BAR_CHART = 2; BAR_CHART = 2;
LINE_STEP_CHART = 3; LINE_STEP_CHART = 3;
SCATTER_CHART = 4;
} }
} }

View File

@ -18,7 +18,13 @@
namespace webrtc { namespace webrtc {
namespace plotting { namespace plotting {
enum PlotStyle { LINE_GRAPH, LINE_DOT_GRAPH, BAR_GRAPH, LINE_STEP_GRAPH }; enum PlotStyle {
LINE_GRAPH,
LINE_DOT_GRAPH,
BAR_GRAPH,
LINE_STEP_GRAPH,
DOT_GRAPH
};
struct TimeSeriesPoint { struct TimeSeriesPoint {
TimeSeriesPoint(float x, float y) : x(x), y(y) {} TimeSeriesPoint(float x, float y) : x(x), y(y) {}

View File

@ -40,6 +40,9 @@ void ProtobufPlot::ExportProtobuf(webrtc::analytics::Chart* chart) {
data_set->set_highlight_points(true); data_set->set_highlight_points(true);
} else if (series_list_[i].style == LINE_STEP_GRAPH) { } else if (series_list_[i].style == LINE_STEP_GRAPH) {
data_set->set_style(webrtc::analytics::ChartStyle::LINE_STEP_CHART); data_set->set_style(webrtc::analytics::ChartStyle::LINE_STEP_CHART);
} else if (series_list_[i].style == DOT_GRAPH) {
data_set->set_style(webrtc::analytics::ChartStyle::SCATTER_CHART);
data_set->set_highlight_points(true);
} else { } else {
data_set->set_style(webrtc::analytics::ChartStyle::UNDEFINED); data_set->set_style(webrtc::analytics::ChartStyle::UNDEFINED);
} }

View File

@ -75,6 +75,11 @@ void PythonPlot::Draw() {
"plt.plot(x%zu[1:], y%zu[:-1], color=rgb_colors[%zu], " "plt.plot(x%zu[1:], y%zu[:-1], color=rgb_colors[%zu], "
"label=\'%s\')\n", "label=\'%s\')\n",
i, i, i, series_list_[i].label.c_str()); i, i, i, series_list_[i].label.c_str());
} else if (series_list_[i].style == DOT_GRAPH) {
printf(
"plt.plot(x%zu, y%zu, color=rgb_colors[%zu], label=\'%s\', "
"marker='.', ls=' ')\n",
i, i, i, series_list_[i].label.c_str());
} else { } else {
printf("raise Exception(\"Unknown graph type\")\n"); printf("raise Exception(\"Unknown graph type\")\n");
} }