OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 Plot* plot) { | 565 Plot* plot) { |
566 for (auto& kv : rtp_packets_) { | 566 for (auto& kv : rtp_packets_) { |
567 StreamId stream_id = kv.first; | 567 StreamId stream_id = kv.first; |
568 const std::vector<LoggedRtpPacket>& packet_stream = kv.second; | 568 const std::vector<LoggedRtpPacket>& packet_stream = kv.second; |
569 // Filter on direction and SSRC. | 569 // Filter on direction and SSRC. |
570 if (stream_id.GetDirection() != desired_direction || | 570 if (stream_id.GetDirection() != desired_direction || |
571 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) { | 571 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) { |
572 continue; | 572 continue; |
573 } | 573 } |
574 | 574 |
575 TimeSeries time_series; | 575 TimeSeries time_series(GetStreamName(stream_id), BAR_GRAPH); |
576 time_series.label = GetStreamName(stream_id); | |
577 time_series.style = BAR_GRAPH; | |
578 ProcessPoints<LoggedRtpPacket>( | 576 ProcessPoints<LoggedRtpPacket>( |
579 [](const LoggedRtpPacket& packet) -> rtc::Optional<float> { | 577 [](const LoggedRtpPacket& packet) -> rtc::Optional<float> { |
580 return rtc::Optional<float>(packet.total_length); | 578 return rtc::Optional<float>(packet.total_length); |
581 }, | 579 }, |
582 packet_stream, begin_time_, &time_series); | 580 packet_stream, begin_time_, &time_series); |
583 plot->series_list_.push_back(std::move(time_series)); | 581 plot->series_list_.push_back(std::move(time_series)); |
584 } | 582 } |
585 | 583 |
586 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); | 584 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
587 plot->SetSuggestedYAxis(0, 1, "Packet size (bytes)", kBottomMargin, | 585 plot->SetSuggestedYAxis(0, 1, "Packet size (bytes)", kBottomMargin, |
(...skipping 13 matching lines...) Expand all Loading... |
601 const std::string& label_prefix) { | 599 const std::string& label_prefix) { |
602 for (auto& kv : packets) { | 600 for (auto& kv : packets) { |
603 StreamId stream_id = kv.first; | 601 StreamId stream_id = kv.first; |
604 const std::vector<T>& packet_stream = kv.second; | 602 const std::vector<T>& packet_stream = kv.second; |
605 // Filter on direction and SSRC. | 603 // Filter on direction and SSRC. |
606 if (stream_id.GetDirection() != desired_direction || | 604 if (stream_id.GetDirection() != desired_direction || |
607 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) { | 605 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) { |
608 continue; | 606 continue; |
609 } | 607 } |
610 | 608 |
611 TimeSeries time_series; | 609 std::string label = label_prefix + " " + GetStreamName(stream_id); |
612 time_series.label = label_prefix + " " + GetStreamName(stream_id); | 610 TimeSeries time_series(label, LINE_STEP_GRAPH); |
613 time_series.style = LINE_STEP_GRAPH; | |
614 | |
615 for (size_t i = 0; i < packet_stream.size(); i++) { | 611 for (size_t i = 0; i < packet_stream.size(); i++) { |
616 float x = static_cast<float>(packet_stream[i].timestamp - begin_time_) / | 612 float x = static_cast<float>(packet_stream[i].timestamp - begin_time_) / |
617 1000000; | 613 1000000; |
618 time_series.points.emplace_back(x, i + 1); | 614 time_series.points.emplace_back(x, i + 1); |
619 } | 615 } |
620 | 616 |
621 plot->series_list_.push_back(std::move(time_series)); | 617 plot->series_list_.push_back(std::move(time_series)); |
622 } | 618 } |
623 } | 619 } |
624 | 620 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 void EventLogAnalyzer::CreateSequenceNumberGraph(Plot* plot) { | 711 void EventLogAnalyzer::CreateSequenceNumberGraph(Plot* plot) { |
716 for (auto& kv : rtp_packets_) { | 712 for (auto& kv : rtp_packets_) { |
717 StreamId stream_id = kv.first; | 713 StreamId stream_id = kv.first; |
718 const std::vector<LoggedRtpPacket>& packet_stream = kv.second; | 714 const std::vector<LoggedRtpPacket>& packet_stream = kv.second; |
719 // Filter on direction and SSRC. | 715 // Filter on direction and SSRC. |
720 if (stream_id.GetDirection() != kIncomingPacket || | 716 if (stream_id.GetDirection() != kIncomingPacket || |
721 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) { | 717 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) { |
722 continue; | 718 continue; |
723 } | 719 } |
724 | 720 |
725 TimeSeries time_series; | 721 TimeSeries time_series(GetStreamName(stream_id), BAR_GRAPH); |
726 time_series.label = GetStreamName(stream_id); | |
727 time_series.style = BAR_GRAPH; | |
728 ProcessPairs<LoggedRtpPacket, float>( | 722 ProcessPairs<LoggedRtpPacket, float>( |
729 [](const LoggedRtpPacket& old_packet, | 723 [](const LoggedRtpPacket& old_packet, |
730 const LoggedRtpPacket& new_packet) { | 724 const LoggedRtpPacket& new_packet) { |
731 int64_t diff = | 725 int64_t diff = |
732 WrappingDifference(new_packet.header.sequenceNumber, | 726 WrappingDifference(new_packet.header.sequenceNumber, |
733 old_packet.header.sequenceNumber, 1ul << 16); | 727 old_packet.header.sequenceNumber, 1ul << 16); |
734 return rtc::Optional<float>(diff); | 728 return rtc::Optional<float>(diff); |
735 }, | 729 }, |
736 packet_stream, begin_time_, &time_series); | 730 packet_stream, begin_time_, &time_series); |
737 plot->series_list_.push_back(std::move(time_series)); | 731 plot->series_list_.push_back(std::move(time_series)); |
738 } | 732 } |
739 | 733 |
740 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); | 734 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
741 plot->SetSuggestedYAxis(0, 1, "Difference since last packet", kBottomMargin, | 735 plot->SetSuggestedYAxis(0, 1, "Difference since last packet", kBottomMargin, |
742 kTopMargin); | 736 kTopMargin); |
743 plot->SetTitle("Sequence number"); | 737 plot->SetTitle("Sequence number"); |
744 } | 738 } |
745 | 739 |
746 void EventLogAnalyzer::CreateIncomingPacketLossGraph(Plot* plot) { | 740 void EventLogAnalyzer::CreateIncomingPacketLossGraph(Plot* plot) { |
747 for (auto& kv : rtp_packets_) { | 741 for (auto& kv : rtp_packets_) { |
748 StreamId stream_id = kv.first; | 742 StreamId stream_id = kv.first; |
749 const std::vector<LoggedRtpPacket>& packet_stream = kv.second; | 743 const std::vector<LoggedRtpPacket>& packet_stream = kv.second; |
750 // Filter on direction and SSRC. | 744 // Filter on direction and SSRC. |
751 if (stream_id.GetDirection() != kIncomingPacket || | 745 if (stream_id.GetDirection() != kIncomingPacket || |
752 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_) || | 746 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_) || |
753 packet_stream.size() == 0) { | 747 packet_stream.size() == 0) { |
754 continue; | 748 continue; |
755 } | 749 } |
756 | 750 |
757 TimeSeries time_series; | 751 TimeSeries time_series(GetStreamName(stream_id), LINE_DOT_GRAPH); |
758 time_series.label = GetStreamName(stream_id); | |
759 time_series.style = LINE_DOT_GRAPH; | |
760 const uint64_t kWindowUs = 1000000; | 752 const uint64_t kWindowUs = 1000000; |
761 const uint64_t kStep = 1000000; | 753 const uint64_t kStep = 1000000; |
762 SequenceNumberUnwrapper unwrapper_; | 754 SequenceNumberUnwrapper unwrapper_; |
763 SequenceNumberUnwrapper prior_unwrapper_; | 755 SequenceNumberUnwrapper prior_unwrapper_; |
764 size_t window_index_begin = 0; | 756 size_t window_index_begin = 0; |
765 size_t window_index_end = 0; | 757 size_t window_index_end = 0; |
766 int64_t highest_seq_number = | 758 int64_t highest_seq_number = |
767 unwrapper_.Unwrap(packet_stream[0].header.sequenceNumber) - 1; | 759 unwrapper_.Unwrap(packet_stream[0].header.sequenceNumber) - 1; |
768 int64_t highest_prior_seq_number = | 760 int64_t highest_prior_seq_number = |
769 prior_unwrapper_.Unwrap(packet_stream[0].header.sequenceNumber) - 1; | 761 prior_unwrapper_.Unwrap(packet_stream[0].header.sequenceNumber) - 1; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
807 StreamId stream_id = kv.first; | 799 StreamId stream_id = kv.first; |
808 const std::vector<LoggedRtpPacket>& packet_stream = kv.second; | 800 const std::vector<LoggedRtpPacket>& packet_stream = kv.second; |
809 // Filter on direction and SSRC. | 801 // Filter on direction and SSRC. |
810 if (stream_id.GetDirection() != kIncomingPacket || | 802 if (stream_id.GetDirection() != kIncomingPacket || |
811 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_) || | 803 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_) || |
812 IsAudioSsrc(stream_id) || !IsVideoSsrc(stream_id) || | 804 IsAudioSsrc(stream_id) || !IsVideoSsrc(stream_id) || |
813 IsRtxSsrc(stream_id)) { | 805 IsRtxSsrc(stream_id)) { |
814 continue; | 806 continue; |
815 } | 807 } |
816 | 808 |
817 TimeSeries capture_time_data; | 809 TimeSeries capture_time_data(GetStreamName(stream_id) + " capture-time", |
818 capture_time_data.label = GetStreamName(stream_id) + " capture-time"; | 810 BAR_GRAPH); |
819 capture_time_data.style = BAR_GRAPH; | |
820 ProcessPairs<LoggedRtpPacket, double>(NetworkDelayDiff_CaptureTime, | 811 ProcessPairs<LoggedRtpPacket, double>(NetworkDelayDiff_CaptureTime, |
821 packet_stream, begin_time_, | 812 packet_stream, begin_time_, |
822 &capture_time_data); | 813 &capture_time_data); |
823 plot->series_list_.push_back(std::move(capture_time_data)); | 814 plot->series_list_.push_back(std::move(capture_time_data)); |
824 | 815 |
825 TimeSeries send_time_data; | 816 TimeSeries send_time_data(GetStreamName(stream_id) + " abs-send-time", |
826 send_time_data.label = GetStreamName(stream_id) + " abs-send-time"; | 817 BAR_GRAPH); |
827 send_time_data.style = BAR_GRAPH; | |
828 ProcessPairs<LoggedRtpPacket, double>(NetworkDelayDiff_AbsSendTime, | 818 ProcessPairs<LoggedRtpPacket, double>(NetworkDelayDiff_AbsSendTime, |
829 packet_stream, begin_time_, | 819 packet_stream, begin_time_, |
830 &send_time_data); | 820 &send_time_data); |
831 plot->series_list_.push_back(std::move(send_time_data)); | 821 plot->series_list_.push_back(std::move(send_time_data)); |
832 } | 822 } |
833 | 823 |
834 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); | 824 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
835 plot->SetSuggestedYAxis(0, 1, "Latency change (ms)", kBottomMargin, | 825 plot->SetSuggestedYAxis(0, 1, "Latency change (ms)", kBottomMargin, |
836 kTopMargin); | 826 kTopMargin); |
837 plot->SetTitle("Network latency change between consecutive packets"); | 827 plot->SetTitle("Network latency change between consecutive packets"); |
838 } | 828 } |
839 | 829 |
840 void EventLogAnalyzer::CreateAccumulatedDelayChangeGraph(Plot* plot) { | 830 void EventLogAnalyzer::CreateAccumulatedDelayChangeGraph(Plot* plot) { |
841 for (auto& kv : rtp_packets_) { | 831 for (auto& kv : rtp_packets_) { |
842 StreamId stream_id = kv.first; | 832 StreamId stream_id = kv.first; |
843 const std::vector<LoggedRtpPacket>& packet_stream = kv.second; | 833 const std::vector<LoggedRtpPacket>& packet_stream = kv.second; |
844 // Filter on direction and SSRC. | 834 // Filter on direction and SSRC. |
845 if (stream_id.GetDirection() != kIncomingPacket || | 835 if (stream_id.GetDirection() != kIncomingPacket || |
846 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_) || | 836 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_) || |
847 IsAudioSsrc(stream_id) || !IsVideoSsrc(stream_id) || | 837 IsAudioSsrc(stream_id) || !IsVideoSsrc(stream_id) || |
848 IsRtxSsrc(stream_id)) { | 838 IsRtxSsrc(stream_id)) { |
849 continue; | 839 continue; |
850 } | 840 } |
851 | 841 |
852 TimeSeries capture_time_data; | 842 TimeSeries capture_time_data(GetStreamName(stream_id) + " capture-time", |
853 capture_time_data.label = GetStreamName(stream_id) + " capture-time"; | 843 LINE_GRAPH); |
854 capture_time_data.style = LINE_GRAPH; | |
855 AccumulatePairs<LoggedRtpPacket, double>(NetworkDelayDiff_CaptureTime, | 844 AccumulatePairs<LoggedRtpPacket, double>(NetworkDelayDiff_CaptureTime, |
856 packet_stream, begin_time_, | 845 packet_stream, begin_time_, |
857 &capture_time_data); | 846 &capture_time_data); |
858 plot->series_list_.push_back(std::move(capture_time_data)); | 847 plot->series_list_.push_back(std::move(capture_time_data)); |
859 | 848 |
860 TimeSeries send_time_data; | 849 TimeSeries send_time_data(GetStreamName(stream_id) + " abs-send-time", |
861 send_time_data.label = GetStreamName(stream_id) + " abs-send-time"; | 850 LINE_GRAPH); |
862 send_time_data.style = LINE_GRAPH; | |
863 AccumulatePairs<LoggedRtpPacket, double>(NetworkDelayDiff_AbsSendTime, | 851 AccumulatePairs<LoggedRtpPacket, double>(NetworkDelayDiff_AbsSendTime, |
864 packet_stream, begin_time_, | 852 packet_stream, begin_time_, |
865 &send_time_data); | 853 &send_time_data); |
866 plot->series_list_.push_back(std::move(send_time_data)); | 854 plot->series_list_.push_back(std::move(send_time_data)); |
867 } | 855 } |
868 | 856 |
869 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); | 857 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
870 plot->SetSuggestedYAxis(0, 1, "Latency change (ms)", kBottomMargin, | 858 plot->SetSuggestedYAxis(0, 1, "Latency change (ms)", kBottomMargin, |
871 kTopMargin); | 859 kTopMargin); |
872 plot->SetTitle("Accumulated network latency change"); | 860 plot->SetTitle("Accumulated network latency change"); |
873 } | 861 } |
874 | 862 |
875 // Plot the fraction of packets lost (as perceived by the loss-based BWE). | 863 // Plot the fraction of packets lost (as perceived by the loss-based BWE). |
876 void EventLogAnalyzer::CreateFractionLossGraph(Plot* plot) { | 864 void EventLogAnalyzer::CreateFractionLossGraph(Plot* plot) { |
877 plot->series_list_.push_back(TimeSeries()); | 865 TimeSeries* time_series = |
| 866 plot->AddTimeSeries("Fraction lost", LINE_DOT_GRAPH); |
878 for (auto& bwe_update : bwe_loss_updates_) { | 867 for (auto& bwe_update : bwe_loss_updates_) { |
879 float x = static_cast<float>(bwe_update.timestamp - begin_time_) / 1000000; | 868 float x = static_cast<float>(bwe_update.timestamp - begin_time_) / 1000000; |
880 float y = static_cast<float>(bwe_update.fraction_loss) / 255 * 100; | 869 float y = static_cast<float>(bwe_update.fraction_loss) / 255 * 100; |
881 plot->series_list_.back().points.emplace_back(x, y); | 870 time_series->points.emplace_back(x, y); |
882 } | 871 } |
883 plot->series_list_.back().label = "Fraction lost"; | |
884 plot->series_list_.back().style = LINE_DOT_GRAPH; | |
885 | 872 |
886 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); | 873 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
887 plot->SetSuggestedYAxis(0, 10, "Percent lost packets", kBottomMargin, | 874 plot->SetSuggestedYAxis(0, 10, "Percent lost packets", kBottomMargin, |
888 kTopMargin); | 875 kTopMargin); |
889 plot->SetTitle("Reported packet loss"); | 876 plot->SetTitle("Reported packet loss"); |
890 } | 877 } |
891 | 878 |
892 // Plot the total bandwidth used by all RTP streams. | 879 // Plot the total bandwidth used by all RTP streams. |
893 void EventLogAnalyzer::CreateTotalBitrateGraph( | 880 void EventLogAnalyzer::CreateTotalBitrateGraph( |
894 PacketDirection desired_direction, | 881 PacketDirection desired_direction, |
(...skipping 19 matching lines...) Expand all Loading... |
914 packets.push_back(TimestampSize(timestamp, total_length)); | 901 packets.push_back(TimestampSize(timestamp, total_length)); |
915 } | 902 } |
916 } | 903 } |
917 } | 904 } |
918 | 905 |
919 size_t window_index_begin = 0; | 906 size_t window_index_begin = 0; |
920 size_t window_index_end = 0; | 907 size_t window_index_end = 0; |
921 size_t bytes_in_window = 0; | 908 size_t bytes_in_window = 0; |
922 | 909 |
923 // Calculate a moving average of the bitrate and store in a TimeSeries. | 910 // Calculate a moving average of the bitrate and store in a TimeSeries. |
924 plot->series_list_.push_back(TimeSeries()); | 911 TimeSeries* time_series = plot->AddTimeSeries("Bitrate", LINE_GRAPH); |
925 for (uint64_t time = begin_time_; time < end_time_ + step_; time += step_) { | 912 for (uint64_t time = begin_time_; time < end_time_ + step_; time += step_) { |
926 while (window_index_end < packets.size() && | 913 while (window_index_end < packets.size() && |
927 packets[window_index_end].timestamp < time) { | 914 packets[window_index_end].timestamp < time) { |
928 bytes_in_window += packets[window_index_end].size; | 915 bytes_in_window += packets[window_index_end].size; |
929 ++window_index_end; | 916 ++window_index_end; |
930 } | 917 } |
931 while (window_index_begin < packets.size() && | 918 while (window_index_begin < packets.size() && |
932 packets[window_index_begin].timestamp < time - window_duration_) { | 919 packets[window_index_begin].timestamp < time - window_duration_) { |
933 RTC_DCHECK_LE(packets[window_index_begin].size, bytes_in_window); | 920 RTC_DCHECK_LE(packets[window_index_begin].size, bytes_in_window); |
934 bytes_in_window -= packets[window_index_begin].size; | 921 bytes_in_window -= packets[window_index_begin].size; |
935 ++window_index_begin; | 922 ++window_index_begin; |
936 } | 923 } |
937 float window_duration_in_seconds = | 924 float window_duration_in_seconds = |
938 static_cast<float>(window_duration_) / 1000000; | 925 static_cast<float>(window_duration_) / 1000000; |
939 float x = static_cast<float>(time - begin_time_) / 1000000; | 926 float x = static_cast<float>(time - begin_time_) / 1000000; |
940 float y = bytes_in_window * 8 / window_duration_in_seconds / 1000; | 927 float y = bytes_in_window * 8 / window_duration_in_seconds / 1000; |
941 plot->series_list_.back().points.push_back(TimeSeriesPoint(x, y)); | 928 time_series->points.emplace_back(x, y); |
942 } | 929 } |
943 | 930 |
944 // Set labels. | |
945 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { | |
946 plot->series_list_.back().label = "Incoming bitrate"; | |
947 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) { | |
948 plot->series_list_.back().label = "Outgoing bitrate"; | |
949 } | |
950 plot->series_list_.back().style = LINE_GRAPH; | |
951 | |
952 // Overlay the send-side bandwidth estimate over the outgoing bitrate. | 931 // Overlay the send-side bandwidth estimate over the outgoing bitrate. |
953 if (desired_direction == kOutgoingPacket) { | 932 if (desired_direction == kOutgoingPacket) { |
954 plot->series_list_.push_back(TimeSeries()); | 933 TimeSeries* time_series = |
| 934 plot->AddTimeSeries("Loss-based estimate", LINE_STEP_GRAPH); |
955 for (auto& bwe_update : bwe_loss_updates_) { | 935 for (auto& bwe_update : bwe_loss_updates_) { |
956 float x = | 936 float x = |
957 static_cast<float>(bwe_update.timestamp - begin_time_) / 1000000; | 937 static_cast<float>(bwe_update.timestamp - begin_time_) / 1000000; |
958 float y = static_cast<float>(bwe_update.new_bitrate) / 1000; | 938 float y = static_cast<float>(bwe_update.new_bitrate) / 1000; |
959 plot->series_list_.back().points.emplace_back(x, y); | 939 time_series->points.emplace_back(x, y); |
960 } | 940 } |
961 plot->series_list_.back().label = "Loss-based estimate"; | |
962 plot->series_list_.back().style = LINE_STEP_GRAPH; | |
963 } | 941 } |
964 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); | 942 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
965 plot->SetSuggestedYAxis(0, 1, "Bitrate (kbps)", kBottomMargin, kTopMargin); | 943 plot->SetSuggestedYAxis(0, 1, "Bitrate (kbps)", kBottomMargin, kTopMargin); |
966 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { | 944 if (desired_direction == webrtc::PacketDirection::kIncomingPacket) { |
967 plot->SetTitle("Incoming RTP bitrate"); | 945 plot->SetTitle("Incoming RTP bitrate"); |
968 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) { | 946 } else if (desired_direction == webrtc::PacketDirection::kOutgoingPacket) { |
969 plot->SetTitle("Outgoing RTP bitrate"); | 947 plot->SetTitle("Outgoing RTP bitrate"); |
970 } | 948 } |
971 } | 949 } |
972 | 950 |
973 // For each SSRC, plot the bandwidth used by that stream. | 951 // For each SSRC, plot the bandwidth used by that stream. |
974 void EventLogAnalyzer::CreateStreamBitrateGraph( | 952 void EventLogAnalyzer::CreateStreamBitrateGraph( |
975 PacketDirection desired_direction, | 953 PacketDirection desired_direction, |
976 Plot* plot) { | 954 Plot* plot) { |
977 for (auto& kv : rtp_packets_) { | 955 for (auto& kv : rtp_packets_) { |
978 StreamId stream_id = kv.first; | 956 StreamId stream_id = kv.first; |
979 const std::vector<LoggedRtpPacket>& packet_stream = kv.second; | 957 const std::vector<LoggedRtpPacket>& packet_stream = kv.second; |
980 // Filter on direction and SSRC. | 958 // Filter on direction and SSRC. |
981 if (stream_id.GetDirection() != desired_direction || | 959 if (stream_id.GetDirection() != desired_direction || |
982 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) { | 960 !MatchingSsrc(stream_id.GetSsrc(), desired_ssrc_)) { |
983 continue; | 961 continue; |
984 } | 962 } |
985 | 963 |
986 TimeSeries time_series; | 964 TimeSeries time_series(GetStreamName(stream_id), LINE_GRAPH); |
987 time_series.label = GetStreamName(stream_id); | |
988 time_series.style = LINE_GRAPH; | |
989 MovingAverage<LoggedRtpPacket, double>( | 965 MovingAverage<LoggedRtpPacket, double>( |
990 [](const LoggedRtpPacket& packet) { | 966 [](const LoggedRtpPacket& packet) { |
991 return rtc::Optional<double>(packet.total_length * 8.0 / 1000.0); | 967 return rtc::Optional<double>(packet.total_length * 8.0 / 1000.0); |
992 }, | 968 }, |
993 packet_stream, begin_time_, end_time_, window_duration_, step_, | 969 packet_stream, begin_time_, end_time_, window_duration_, step_, |
994 &time_series); | 970 &time_series); |
995 plot->series_list_.push_back(std::move(time_series)); | 971 plot->series_list_.push_back(std::move(time_series)); |
996 } | 972 } |
997 | 973 |
998 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); | 974 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
(...skipping 27 matching lines...) Expand all Loading... |
1026 SimulatedClock clock(0); | 1002 SimulatedClock clock(0); |
1027 BitrateObserver observer; | 1003 BitrateObserver observer; |
1028 RtcEventLogNullImpl null_event_log; | 1004 RtcEventLogNullImpl null_event_log; |
1029 PacketRouter packet_router; | 1005 PacketRouter packet_router; |
1030 CongestionController cc(&clock, &observer, &observer, &null_event_log, | 1006 CongestionController cc(&clock, &observer, &observer, &null_event_log, |
1031 &packet_router); | 1007 &packet_router); |
1032 // TODO(holmer): Log the call config and use that here instead. | 1008 // TODO(holmer): Log the call config and use that here instead. |
1033 static const uint32_t kDefaultStartBitrateBps = 300000; | 1009 static const uint32_t kDefaultStartBitrateBps = 300000; |
1034 cc.SetBweBitrates(0, kDefaultStartBitrateBps, -1); | 1010 cc.SetBweBitrates(0, kDefaultStartBitrateBps, -1); |
1035 | 1011 |
1036 TimeSeries time_series; | 1012 TimeSeries time_series("Delay-based estimate", LINE_DOT_GRAPH); |
1037 time_series.label = "Delay-based estimate"; | 1013 TimeSeries acked_time_series("Acked bitrate", LINE_DOT_GRAPH); |
1038 time_series.style = LINE_DOT_GRAPH; | |
1039 TimeSeries acked_time_series; | |
1040 acked_time_series.label = "Acked bitrate"; | |
1041 acked_time_series.style = LINE_DOT_GRAPH; | |
1042 | 1014 |
1043 auto rtp_iterator = outgoing_rtp.begin(); | 1015 auto rtp_iterator = outgoing_rtp.begin(); |
1044 auto rtcp_iterator = incoming_rtcp.begin(); | 1016 auto rtcp_iterator = incoming_rtcp.begin(); |
1045 | 1017 |
1046 auto NextRtpTime = [&]() { | 1018 auto NextRtpTime = [&]() { |
1047 if (rtp_iterator != outgoing_rtp.end()) | 1019 if (rtp_iterator != outgoing_rtp.end()) |
1048 return static_cast<int64_t>(rtp_iterator->first); | 1020 return static_cast<int64_t>(rtp_iterator->first); |
1049 return std::numeric_limits<int64_t>::max(); | 1021 return std::numeric_limits<int64_t>::max(); |
1050 }; | 1022 }; |
1051 | 1023 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1144 if (kv.first.GetDirection() == PacketDirection::kIncomingPacket) { | 1116 if (kv.first.GetDirection() == PacketDirection::kIncomingPacket) { |
1145 for (const LoggedRtcpPacket& rtcp_packet : kv.second) | 1117 for (const LoggedRtcpPacket& rtcp_packet : kv.second) |
1146 incoming_rtcp.insert( | 1118 incoming_rtcp.insert( |
1147 std::make_pair(rtcp_packet.timestamp, &rtcp_packet)); | 1119 std::make_pair(rtcp_packet.timestamp, &rtcp_packet)); |
1148 } | 1120 } |
1149 } | 1121 } |
1150 | 1122 |
1151 SimulatedClock clock(0); | 1123 SimulatedClock clock(0); |
1152 TransportFeedbackAdapter feedback_adapter(&clock); | 1124 TransportFeedbackAdapter feedback_adapter(&clock); |
1153 | 1125 |
1154 TimeSeries time_series; | 1126 TimeSeries time_series("Network Delay Change", LINE_DOT_GRAPH); |
1155 time_series.label = "Network Delay Change"; | |
1156 time_series.style = LINE_DOT_GRAPH; | |
1157 int64_t estimated_base_delay_ms = std::numeric_limits<int64_t>::max(); | 1127 int64_t estimated_base_delay_ms = std::numeric_limits<int64_t>::max(); |
1158 | 1128 |
1159 auto rtp_iterator = outgoing_rtp.begin(); | 1129 auto rtp_iterator = outgoing_rtp.begin(); |
1160 auto rtcp_iterator = incoming_rtcp.begin(); | 1130 auto rtcp_iterator = incoming_rtcp.begin(); |
1161 | 1131 |
1162 auto NextRtpTime = [&]() { | 1132 auto NextRtpTime = [&]() { |
1163 if (rtp_iterator != outgoing_rtp.end()) | 1133 if (rtp_iterator != outgoing_rtp.end()) |
1164 return static_cast<int64_t>(rtp_iterator->first); | 1134 return static_cast<int64_t>(rtp_iterator->first); |
1165 return std::numeric_limits<int64_t>::max(); | 1135 return std::numeric_limits<int64_t>::max(); |
1166 }; | 1136 }; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1247 } | 1217 } |
1248 return timestamps; | 1218 return timestamps; |
1249 } | 1219 } |
1250 | 1220 |
1251 void EventLogAnalyzer::CreateTimestampGraph(Plot* plot) { | 1221 void EventLogAnalyzer::CreateTimestampGraph(Plot* plot) { |
1252 for (const auto& kv : rtp_packets_) { | 1222 for (const auto& kv : rtp_packets_) { |
1253 const std::vector<LoggedRtpPacket>& rtp_packets = kv.second; | 1223 const std::vector<LoggedRtpPacket>& rtp_packets = kv.second; |
1254 StreamId stream_id = kv.first; | 1224 StreamId stream_id = kv.first; |
1255 | 1225 |
1256 { | 1226 { |
1257 TimeSeries timestamp_data; | 1227 TimeSeries timestamp_data(GetStreamName(stream_id) + " capture-time", |
1258 timestamp_data.label = GetStreamName(stream_id) + " capture-time"; | 1228 LINE_DOT_GRAPH); |
1259 timestamp_data.style = LINE_DOT_GRAPH; | |
1260 for (LoggedRtpPacket packet : rtp_packets) { | 1229 for (LoggedRtpPacket packet : rtp_packets) { |
1261 float x = static_cast<float>(packet.timestamp - begin_time_) / 1000000; | 1230 float x = static_cast<float>(packet.timestamp - begin_time_) / 1000000; |
1262 float y = packet.header.timestamp; | 1231 float y = packet.header.timestamp; |
1263 timestamp_data.points.emplace_back(x, y); | 1232 timestamp_data.points.emplace_back(x, y); |
1264 } | 1233 } |
1265 plot->series_list_.push_back(std::move(timestamp_data)); | 1234 plot->series_list_.push_back(std::move(timestamp_data)); |
1266 } | 1235 } |
1267 | 1236 |
1268 { | 1237 { |
1269 auto kv = rtcp_packets_.find(stream_id); | 1238 auto kv = rtcp_packets_.find(stream_id); |
1270 if (kv != rtcp_packets_.end()) { | 1239 if (kv != rtcp_packets_.end()) { |
1271 const auto& packets = kv->second; | 1240 const auto& packets = kv->second; |
1272 TimeSeries timestamp_data; | 1241 TimeSeries timestamp_data( |
1273 timestamp_data.label = GetStreamName(stream_id) + " rtcp capture-time"; | 1242 GetStreamName(stream_id) + " rtcp capture-time", LINE_DOT_GRAPH); |
1274 timestamp_data.style = LINE_DOT_GRAPH; | |
1275 for (const LoggedRtcpPacket& rtcp : packets) { | 1243 for (const LoggedRtcpPacket& rtcp : packets) { |
1276 if (rtcp.type != kRtcpSr) | 1244 if (rtcp.type != kRtcpSr) |
1277 continue; | 1245 continue; |
1278 rtcp::SenderReport* sr; | 1246 rtcp::SenderReport* sr; |
1279 sr = static_cast<rtcp::SenderReport*>(rtcp.packet.get()); | 1247 sr = static_cast<rtcp::SenderReport*>(rtcp.packet.get()); |
1280 float x = static_cast<float>(rtcp.timestamp - begin_time_) / 1000000; | 1248 float x = static_cast<float>(rtcp.timestamp - begin_time_) / 1000000; |
1281 float y = sr->rtp_timestamp(); | 1249 float y = sr->rtp_timestamp(); |
1282 timestamp_data.points.emplace_back(x, y); | 1250 timestamp_data.points.emplace_back(x, y); |
1283 } | 1251 } |
1284 plot->series_list_.push_back(std::move(timestamp_data)); | 1252 plot->series_list_.push_back(std::move(timestamp_data)); |
1285 } | 1253 } |
1286 } | 1254 } |
1287 } | 1255 } |
1288 | 1256 |
1289 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); | 1257 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
1290 plot->SetSuggestedYAxis(0, 1, "Timestamp (90khz)", kBottomMargin, kTopMargin); | 1258 plot->SetSuggestedYAxis(0, 1, "Timestamp (90khz)", kBottomMargin, kTopMargin); |
1291 plot->SetTitle("Timestamps"); | 1259 plot->SetTitle("Timestamps"); |
1292 } | 1260 } |
1293 | 1261 |
1294 void EventLogAnalyzer::CreateAudioEncoderTargetBitrateGraph(Plot* plot) { | 1262 void EventLogAnalyzer::CreateAudioEncoderTargetBitrateGraph(Plot* plot) { |
1295 plot->series_list_.push_back(TimeSeries()); | 1263 TimeSeries* time_series = |
1296 plot->series_list_.back().style = LINE_DOT_GRAPH; | 1264 plot->AddTimeSeries("Audio encoder target bitrate", LINE_DOT_GRAPH); |
1297 plot->series_list_.back().label = "Audio encoder target bitrate"; | |
1298 ProcessPoints<AudioNetworkAdaptationEvent>( | 1265 ProcessPoints<AudioNetworkAdaptationEvent>( |
1299 [](const AudioNetworkAdaptationEvent& ana_event) -> rtc::Optional<float> { | 1266 [](const AudioNetworkAdaptationEvent& ana_event) -> rtc::Optional<float> { |
1300 if (ana_event.config.bitrate_bps) | 1267 if (ana_event.config.bitrate_bps) |
1301 return rtc::Optional<float>( | 1268 return rtc::Optional<float>( |
1302 static_cast<float>(*ana_event.config.bitrate_bps)); | 1269 static_cast<float>(*ana_event.config.bitrate_bps)); |
1303 return rtc::Optional<float>(); | 1270 return rtc::Optional<float>(); |
1304 }, | 1271 }, |
1305 audio_network_adaptation_events_, begin_time_, | 1272 audio_network_adaptation_events_, begin_time_, time_series); |
1306 &plot->series_list_.back()); | |
1307 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); | 1273 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
1308 plot->SetSuggestedYAxis(0, 1, "Bitrate (bps)", kBottomMargin, kTopMargin); | 1274 plot->SetSuggestedYAxis(0, 1, "Bitrate (bps)", kBottomMargin, kTopMargin); |
1309 plot->SetTitle("Reported audio encoder target bitrate"); | 1275 plot->SetTitle("Reported audio encoder target bitrate"); |
1310 } | 1276 } |
1311 | 1277 |
1312 void EventLogAnalyzer::CreateAudioEncoderFrameLengthGraph(Plot* plot) { | 1278 void EventLogAnalyzer::CreateAudioEncoderFrameLengthGraph(Plot* plot) { |
1313 plot->series_list_.push_back(TimeSeries()); | 1279 TimeSeries* time_series = |
1314 plot->series_list_.back().style = LINE_DOT_GRAPH; | 1280 plot->AddTimeSeries("Audio encoder frame length", LINE_DOT_GRAPH); |
1315 plot->series_list_.back().label = "Audio encoder frame length"; | |
1316 ProcessPoints<AudioNetworkAdaptationEvent>( | 1281 ProcessPoints<AudioNetworkAdaptationEvent>( |
1317 [](const AudioNetworkAdaptationEvent& ana_event) { | 1282 [](const AudioNetworkAdaptationEvent& ana_event) { |
1318 if (ana_event.config.frame_length_ms) | 1283 if (ana_event.config.frame_length_ms) |
1319 return rtc::Optional<float>( | 1284 return rtc::Optional<float>( |
1320 static_cast<float>(*ana_event.config.frame_length_ms)); | 1285 static_cast<float>(*ana_event.config.frame_length_ms)); |
1321 return rtc::Optional<float>(); | 1286 return rtc::Optional<float>(); |
1322 }, | 1287 }, |
1323 audio_network_adaptation_events_, begin_time_, | 1288 audio_network_adaptation_events_, begin_time_, time_series); |
1324 &plot->series_list_.back()); | |
1325 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); | 1289 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
1326 plot->SetSuggestedYAxis(0, 1, "Frame length (ms)", kBottomMargin, kTopMargin); | 1290 plot->SetSuggestedYAxis(0, 1, "Frame length (ms)", kBottomMargin, kTopMargin); |
1327 plot->SetTitle("Reported audio encoder frame length"); | 1291 plot->SetTitle("Reported audio encoder frame length"); |
1328 } | 1292 } |
1329 | 1293 |
1330 void EventLogAnalyzer::CreateAudioEncoderUplinkPacketLossFractionGraph( | 1294 void EventLogAnalyzer::CreateAudioEncoderUplinkPacketLossFractionGraph( |
1331 Plot* plot) { | 1295 Plot* plot) { |
1332 plot->series_list_.push_back(TimeSeries()); | 1296 TimeSeries* time_series = plot->AddTimeSeries( |
1333 plot->series_list_.back().style = LINE_DOT_GRAPH; | 1297 "Audio encoder uplink packet loss fraction", LINE_DOT_GRAPH); |
1334 plot->series_list_.back().label = "Audio encoder uplink packet loss fraction"; | |
1335 ProcessPoints<AudioNetworkAdaptationEvent>( | 1298 ProcessPoints<AudioNetworkAdaptationEvent>( |
1336 [](const AudioNetworkAdaptationEvent& ana_event) { | 1299 [](const AudioNetworkAdaptationEvent& ana_event) { |
1337 if (ana_event.config.uplink_packet_loss_fraction) | 1300 if (ana_event.config.uplink_packet_loss_fraction) |
1338 return rtc::Optional<float>(static_cast<float>( | 1301 return rtc::Optional<float>(static_cast<float>( |
1339 *ana_event.config.uplink_packet_loss_fraction)); | 1302 *ana_event.config.uplink_packet_loss_fraction)); |
1340 return rtc::Optional<float>(); | 1303 return rtc::Optional<float>(); |
1341 }, | 1304 }, |
1342 audio_network_adaptation_events_, begin_time_, | 1305 audio_network_adaptation_events_, begin_time_, time_series); |
1343 &plot->series_list_.back()); | |
1344 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); | 1306 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
1345 plot->SetSuggestedYAxis(0, 10, "Percent lost packets", kBottomMargin, | 1307 plot->SetSuggestedYAxis(0, 10, "Percent lost packets", kBottomMargin, |
1346 kTopMargin); | 1308 kTopMargin); |
1347 plot->SetTitle("Reported audio encoder lost packets"); | 1309 plot->SetTitle("Reported audio encoder lost packets"); |
1348 } | 1310 } |
1349 | 1311 |
1350 void EventLogAnalyzer::CreateAudioEncoderEnableFecGraph(Plot* plot) { | 1312 void EventLogAnalyzer::CreateAudioEncoderEnableFecGraph(Plot* plot) { |
1351 plot->series_list_.push_back(TimeSeries()); | 1313 TimeSeries* time_series = |
1352 plot->series_list_.back().style = LINE_DOT_GRAPH; | 1314 plot->AddTimeSeries("Audio encoder FEC", LINE_DOT_GRAPH); |
1353 plot->series_list_.back().label = "Audio encoder FEC"; | |
1354 ProcessPoints<AudioNetworkAdaptationEvent>( | 1315 ProcessPoints<AudioNetworkAdaptationEvent>( |
1355 [](const AudioNetworkAdaptationEvent& ana_event) { | 1316 [](const AudioNetworkAdaptationEvent& ana_event) { |
1356 if (ana_event.config.enable_fec) | 1317 if (ana_event.config.enable_fec) |
1357 return rtc::Optional<float>( | 1318 return rtc::Optional<float>( |
1358 static_cast<float>(*ana_event.config.enable_fec)); | 1319 static_cast<float>(*ana_event.config.enable_fec)); |
1359 return rtc::Optional<float>(); | 1320 return rtc::Optional<float>(); |
1360 }, | 1321 }, |
1361 audio_network_adaptation_events_, begin_time_, | 1322 audio_network_adaptation_events_, begin_time_, time_series); |
1362 &plot->series_list_.back()); | |
1363 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); | 1323 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
1364 plot->SetSuggestedYAxis(0, 1, "FEC (false/true)", kBottomMargin, kTopMargin); | 1324 plot->SetSuggestedYAxis(0, 1, "FEC (false/true)", kBottomMargin, kTopMargin); |
1365 plot->SetTitle("Reported audio encoder FEC"); | 1325 plot->SetTitle("Reported audio encoder FEC"); |
1366 } | 1326 } |
1367 | 1327 |
1368 void EventLogAnalyzer::CreateAudioEncoderEnableDtxGraph(Plot* plot) { | 1328 void EventLogAnalyzer::CreateAudioEncoderEnableDtxGraph(Plot* plot) { |
1369 plot->series_list_.push_back(TimeSeries()); | 1329 TimeSeries* time_series = |
1370 plot->series_list_.back().style = LINE_DOT_GRAPH; | 1330 plot->AddTimeSeries("Audio encoder DTX", LINE_DOT_GRAPH); |
1371 plot->series_list_.back().label = "Audio encoder DTX"; | |
1372 ProcessPoints<AudioNetworkAdaptationEvent>( | 1331 ProcessPoints<AudioNetworkAdaptationEvent>( |
1373 [](const AudioNetworkAdaptationEvent& ana_event) { | 1332 [](const AudioNetworkAdaptationEvent& ana_event) { |
1374 if (ana_event.config.enable_dtx) | 1333 if (ana_event.config.enable_dtx) |
1375 return rtc::Optional<float>( | 1334 return rtc::Optional<float>( |
1376 static_cast<float>(*ana_event.config.enable_dtx)); | 1335 static_cast<float>(*ana_event.config.enable_dtx)); |
1377 return rtc::Optional<float>(); | 1336 return rtc::Optional<float>(); |
1378 }, | 1337 }, |
1379 audio_network_adaptation_events_, begin_time_, | 1338 audio_network_adaptation_events_, begin_time_, time_series); |
1380 &plot->series_list_.back()); | |
1381 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); | 1339 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
1382 plot->SetSuggestedYAxis(0, 1, "DTX (false/true)", kBottomMargin, kTopMargin); | 1340 plot->SetSuggestedYAxis(0, 1, "DTX (false/true)", kBottomMargin, kTopMargin); |
1383 plot->SetTitle("Reported audio encoder DTX"); | 1341 plot->SetTitle("Reported audio encoder DTX"); |
1384 } | 1342 } |
1385 | 1343 |
1386 void EventLogAnalyzer::CreateAudioEncoderNumChannelsGraph(Plot* plot) { | 1344 void EventLogAnalyzer::CreateAudioEncoderNumChannelsGraph(Plot* plot) { |
1387 plot->series_list_.push_back(TimeSeries()); | 1345 TimeSeries* time_series = |
1388 plot->series_list_.back().style = LINE_DOT_GRAPH; | 1346 plot->AddTimeSeries("Audio encoder number of channels", LINE_DOT_GRAPH); |
1389 plot->series_list_.back().label = "Audio encoder number of channels"; | |
1390 ProcessPoints<AudioNetworkAdaptationEvent>( | 1347 ProcessPoints<AudioNetworkAdaptationEvent>( |
1391 [](const AudioNetworkAdaptationEvent& ana_event) { | 1348 [](const AudioNetworkAdaptationEvent& ana_event) { |
1392 if (ana_event.config.num_channels) | 1349 if (ana_event.config.num_channels) |
1393 return rtc::Optional<float>( | 1350 return rtc::Optional<float>( |
1394 static_cast<float>(*ana_event.config.num_channels)); | 1351 static_cast<float>(*ana_event.config.num_channels)); |
1395 return rtc::Optional<float>(); | 1352 return rtc::Optional<float>(); |
1396 }, | 1353 }, |
1397 audio_network_adaptation_events_, begin_time_, | 1354 audio_network_adaptation_events_, begin_time_, time_series); |
1398 &plot->series_list_.back()); | |
1399 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); | 1355 plot->SetXAxis(0, call_duration_s_, "Time (s)", kLeftMargin, kRightMargin); |
1400 plot->SetSuggestedYAxis(0, 1, "Number of channels (1 (mono)/2 (stereo))", | 1356 plot->SetSuggestedYAxis(0, 1, "Number of channels (1 (mono)/2 (stereo))", |
1401 kBottomMargin, kTopMargin); | 1357 kBottomMargin, kTopMargin); |
1402 plot->SetTitle("Reported audio encoder number of channels"); | 1358 plot->SetTitle("Reported audio encoder number of channels"); |
1403 } | 1359 } |
1404 } // namespace plotting | 1360 } // namespace plotting |
1405 } // namespace webrtc | 1361 } // namespace webrtc |
OLD | NEW |