Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /* | |
| 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | |
| 3 * | |
| 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 | |
| 6 * tree. An additional intellectual property rights grant can be found | |
| 7 * in the file PATENTS. All contributing project authors may | |
| 8 * be found in the AUTHORS file in the root of the source tree. | |
| 9 */ | |
| 10 | |
| 11 #include "webrtc/modules/audio_coding/neteq/tools/neteq_delay_analyzer.h" | |
| 12 | |
| 13 #include <algorithm> | |
| 14 #include <limits> | |
| 15 #include <utility> | |
| 16 | |
| 17 namespace webrtc { | |
| 18 namespace test { | |
| 19 | |
| 20 void NetEqDelayAnalyzer::AfterInsertPacket( | |
| 21 const test::NetEqInput::PacketData& packet, | |
| 22 NetEq* neteq) { | |
| 23 data_.insert( | |
| 24 std::make_pair(packet.header.timestamp, | |
| 25 TimingData(packet.header.sequenceNumber, packet.time_ms))); | |
| 26 } | |
| 27 | |
| 28 void NetEqDelayAnalyzer::BeforeGetAudio(NetEq* neteq) { | |
| 29 last_sync_buffer_ms_ = neteq->SyncBufferSizeMs(); | |
| 30 } | |
| 31 | |
| 32 void NetEqDelayAnalyzer::AfterGetAudio(int64_t time_now_ms, | |
| 33 const AudioFrame& audio_frame, | |
| 34 bool muted, | |
|
ivoc
2017/05/16 13:25:50
Since this is not used you can comment out the nam
hlundin-webrtc
2017/05/30 14:56:06
Done.
| |
| 35 NetEq* neteq) { | |
| 36 get_audio_time_ms_.push_back(time_now_ms); | |
| 37 // Check what timestamps were decoded in the last GetAudio call. | |
| 38 std::vector<uint32_t> dec_ts = neteq->LastDecodedTimestamps(); | |
| 39 // Find those timestamps in data_, insert their decoding time and sync | |
| 40 // delay. | |
| 41 for (uint32_t ts : dec_ts) { | |
| 42 auto it = data_.find(ts); | |
| 43 if (it == data_.end()) { | |
| 44 // This is a packet that was split out from another packet. Skip it. | |
| 45 continue; | |
| 46 } | |
| 47 RTC_CHECK(!it->second.decode_get_audio_count) | |
|
ivoc
2017/05/16 13:25:50
I think this code block would be easier to read wi
hlundin-webrtc
2017/05/30 14:56:06
Done.
| |
| 48 << "Decode time already written"; | |
| 49 it->second.decode_get_audio_count = | |
| 50 rtc::Optional<int64_t>(get_audio_count_); | |
| 51 RTC_CHECK(!it->second.sync_delay_ms) << "Decode time already written"; | |
| 52 it->second.sync_delay_ms = rtc::Optional<int64_t>(last_sync_buffer_ms_); | |
| 53 it->second.target_delay_ms = rtc::Optional<int>(neteq->TargetDelayMs()); | |
| 54 it->second.current_delay_ms = | |
| 55 rtc::Optional<int>(neteq->FilteredCurrentDelayMs()); | |
| 56 } | |
| 57 last_sample_rate_hz_ = audio_frame.sample_rate_hz_; | |
| 58 ++get_audio_count_; | |
| 59 } | |
| 60 | |
| 61 void NetEqDelayAnalyzer::CreateGraphs( | |
|
ivoc
2017/05/16 13:25:50
This function is pretty long, so you can consider
hlundin-webrtc
2017/05/30 14:56:06
Done.
| |
| 62 std::vector<float>* send_time_s, | |
| 63 std::vector<float>* arrival_delay_ms, | |
| 64 std::vector<float>* corrected_arrival_delay_ms, | |
| 65 std::vector<rtc::Optional<float>>* playout_delay_ms, | |
| 66 std::vector<rtc::Optional<float>>* target_delay_ms) const { | |
| 67 // Create nominal_get_audio_time_ms, a vector starting at | |
| 68 // get_audio_time_ms_[0] and increasing by 10 for each element. | |
| 69 std::vector<int64_t> nominal_get_audio_time_ms(get_audio_time_ms_.size()); | |
| 70 nominal_get_audio_time_ms[0] = get_audio_time_ms_[0]; | |
| 71 std::transform( | |
| 72 nominal_get_audio_time_ms.begin(), nominal_get_audio_time_ms.end() - 1, | |
|
ivoc
2017/05/16 13:25:50
Will this crash if nominal_get_audio_time_ms is em
hlundin-webrtc
2017/05/30 14:56:06
Presumably, but we already set the first element o
ivoc
2017/05/30 16:29:45
Acknowledged.
| |
| 73 nominal_get_audio_time_ms.begin() + 1, [](int64_t& x) { return x + 10; }); | |
| 74 RTC_DCHECK( | |
| 75 std::is_sorted(get_audio_time_ms_.begin(), get_audio_time_ms_.end())); | |
| 76 | |
| 77 std::vector<double> rtp_timestamps_ms; | |
| 78 std::vector<double> arrival_time_ms; | |
| 79 std::vector<double> corrected_arrival_time_ms; | |
| 80 std::vector<int64_t> decode_get_audio_count; | |
| 81 std::vector<int64_t> sync_delay_ms; | |
| 82 std::vector<int> raw_target_delay_ms; | |
| 83 std::vector<int> filtered_delay_ms; | |
| 84 double offset = std::numeric_limits<double>::max(); | |
| 85 | |
| 86 TimestampUnwrapper unwrapper; | |
| 87 for (auto& d : data_) { | |
|
ivoc
2017/05/16 13:25:50
Please add a comment to explain what this loop doe
hlundin-webrtc
2017/05/30 14:56:06
Done.
| |
| 88 rtp_timestamps_ms.push_back(unwrapper.Unwrap(d.first) / | |
| 89 (last_sample_rate_hz_ / 1000.f)); | |
| 90 arrival_time_ms.push_back(d.second.arrival_time_ms); | |
|
ivoc
2017/05/16 13:25:50
Also here I would suggest to introduce an intermed
hlundin-webrtc
2017/05/30 14:56:06
Done.
| |
| 91 offset = | |
| 92 std::min(offset, arrival_time_ms.back() - rtp_timestamps_ms.back()); | |
| 93 // Interpolate arrival times. | |
| 94 double x = d.second.arrival_time_ms; | |
| 95 // Find first element which is larger than x. | |
| 96 auto it = std::find_if(get_audio_time_ms_.begin(), get_audio_time_ms_.end(), | |
| 97 [x](int64_t v) -> bool { return v > x; }); | |
| 98 if (it == get_audio_time_ms_.end()) { | |
| 99 --it; | |
| 100 } | |
| 101 const size_t upper_ix = it - get_audio_time_ms_.begin(); | |
| 102 | |
| 103 size_t lower_ix; | |
| 104 if (upper_ix == 0 || get_audio_time_ms_[upper_ix] <= x) { | |
| 105 lower_ix = upper_ix; | |
| 106 } else { | |
| 107 lower_ix = upper_ix - 1; | |
| 108 } | |
| 109 double y; | |
|
ivoc
2017/05/16 13:25:50
The variable names are a bit cryptic in this funct
hlundin-webrtc
2017/05/30 14:56:06
I broke this part out to a generalized interpolati
| |
| 110 if (lower_ix == upper_ix) { | |
| 111 y = nominal_get_audio_time_ms[lower_ix]; | |
| 112 } else { | |
| 113 RTC_DCHECK_NE(get_audio_time_ms_[lower_ix], get_audio_time_ms_[upper_ix]); | |
| 114 y = (x - get_audio_time_ms_[lower_ix]) * | |
| 115 (nominal_get_audio_time_ms[upper_ix] - | |
| 116 nominal_get_audio_time_ms[lower_ix]) / | |
| 117 (get_audio_time_ms_[upper_ix] - get_audio_time_ms_[lower_ix]) + | |
| 118 nominal_get_audio_time_ms[lower_ix]; | |
| 119 } | |
| 120 corrected_arrival_time_ms.push_back(y); | |
| 121 | |
| 122 decode_get_audio_count.push_back( | |
| 123 d.second.decode_get_audio_count.value_or(-1)); | |
| 124 sync_delay_ms.push_back(d.second.sync_delay_ms.value_or(-1)); | |
| 125 raw_target_delay_ms.push_back(d.second.target_delay_ms.value_or(-1)); | |
| 126 filtered_delay_ms.push_back(d.second.current_delay_ms.value_or(-1)); | |
| 127 } | |
| 128 send_time_s->resize(rtp_timestamps_ms.size()); | |
| 129 std::transform(rtp_timestamps_ms.begin(), rtp_timestamps_ms.end(), | |
| 130 send_time_s->begin(), [rtp_timestamps_ms](double x) { | |
| 131 return (x - rtp_timestamps_ms[0]) / 1000.f; | |
| 132 }); | |
| 133 | |
| 134 RTC_DCHECK_EQ(send_time_s->size(), corrected_arrival_time_ms.size()); | |
| 135 RTC_DCHECK_EQ(send_time_s->size(), rtp_timestamps_ms.size()); | |
| 136 RTC_DCHECK_EQ(send_time_s->size(), decode_get_audio_count.size()); | |
| 137 for (size_t i = 0; i < send_time_s->size(); ++i) { | |
|
ivoc
2017/05/16 13:25:50
Please add a comment to explain what this for loop
hlundin-webrtc
2017/05/30 14:56:06
Done.
| |
| 138 const double y = | |
| 139 corrected_arrival_time_ms[i] - (rtp_timestamps_ms[i] + offset); | |
| 140 corrected_arrival_delay_ms->emplace_back(y); | |
|
ivoc
2017/05/16 13:25:50
This is exactly the same as push_back for a vector
hlundin-webrtc
2017/05/30 14:56:06
You are right. This is over-kill. I changed them a
| |
| 141 const double z = arrival_time_ms[i] - (rtp_timestamps_ms[i] + offset); | |
| 142 arrival_delay_ms->emplace_back(z); | |
| 143 | |
| 144 if (decode_get_audio_count[i] > -1) { | |
| 145 RTC_DCHECK_NE(sync_delay_ms[i], -1); | |
| 146 const float playout_ms = decode_get_audio_count[i] * 10 + | |
| 147 get_audio_time_ms_[0] + sync_delay_ms[i] - | |
| 148 (rtp_timestamps_ms[i] + offset); | |
| 149 playout_delay_ms->emplace_back(rtc::Optional<float>(playout_ms)); | |
| 150 RTC_DCHECK_GT(raw_target_delay_ms[i], -1); | |
| 151 RTC_DCHECK_GT(filtered_delay_ms[i], -1); | |
| 152 const float target = | |
| 153 playout_ms - filtered_delay_ms[i] + raw_target_delay_ms[i]; | |
| 154 target_delay_ms->emplace_back(rtc::Optional<float>(target)); | |
| 155 } else { | |
| 156 playout_delay_ms->emplace_back(rtc::Optional<float>()); | |
| 157 target_delay_ms->emplace_back(rtc::Optional<float>()); | |
| 158 } | |
| 159 } | |
| 160 RTC_DCHECK_EQ(send_time_s->size(), corrected_arrival_delay_ms->size()); | |
| 161 RTC_DCHECK_EQ(send_time_s->size(), playout_delay_ms->size()); | |
| 162 RTC_DCHECK_EQ(send_time_s->size(), target_delay_ms->size()); | |
| 163 } | |
| 164 | |
| 165 } // namespace test | |
| 166 } // namespace webrtc | |
| OLD | NEW |