1 /* 2 * Copyright (c) 2012 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/video_engine/stream_synchronization.h" 12 13 #include <assert.h> 14 #include <math.h> 15 #include <stdlib.h> 16 17 #include <algorithm> 18 19 #include "webrtc/system_wrappers/interface/logging.h" 20 21 namespace webrtc { 22 23 static const int kMaxChangeMs = 80; 24 static const int kMaxDeltaDelayMs = 10000; 25 static const int kFilterLength = 4; 26 // Minimum difference between audio and video to warrant a change. 27 static const int kMinDeltaMs = 30; 28 29 struct ViESyncDelay { 30 ViESyncDelay() { 31 extra_video_delay_ms = 0; 32 last_video_delay_ms = 0; 33 extra_audio_delay_ms = 0; 34 last_audio_delay_ms = 0; 35 network_delay = 120; 36 } 37 38 int extra_video_delay_ms; 39 int last_video_delay_ms; 40 int extra_audio_delay_ms; 41 int last_audio_delay_ms; 42 int network_delay; 43 }; 44 45 StreamSynchronization::StreamSynchronization(int audio_channel_id, 46 int video_channel_id) 47 : channel_delay_(new ViESyncDelay), 48 audio_channel_id_(audio_channel_id), 49 video_channel_id_(video_channel_id), 50 base_target_delay_ms_(0), 51 avg_diff_ms_(0) {} 52 53 StreamSynchronization::~StreamSynchronization() { 54 delete channel_delay_; 55 } 56 57 bool StreamSynchronization::ComputeRelativeDelay( 58 const Measurements& audio_measurement, 59 const Measurements& video_measurement, 60 int* relative_delay_ms) { 61 assert(relative_delay_ms); 62 if (audio_measurement.rtcp.size() < 2 || video_measurement.rtcp.size() < 2) { 63 // We need two RTCP SR reports per stream to do synchronization. 64 return false; 65 } 66 int64_t audio_last_capture_time_ms; 67 if (!RtpToNtpMs(audio_measurement.latest_timestamp, 68 audio_measurement.rtcp, 69 &audio_last_capture_time_ms)) { 70 return false; 71 } 72 int64_t video_last_capture_time_ms; 73 if (!RtpToNtpMs(video_measurement.latest_timestamp, 74 video_measurement.rtcp, 75 &video_last_capture_time_ms)) { 76 return false; 77 } 78 if (video_last_capture_time_ms < 0) { 79 return false; 80 } 81 // Positive diff means that video_measurement is behind audio_measurement. 82 *relative_delay_ms = video_measurement.latest_receive_time_ms - 83 audio_measurement.latest_receive_time_ms - 84 (video_last_capture_time_ms - audio_last_capture_time_ms); 85 if (*relative_delay_ms > kMaxDeltaDelayMs || 86 *relative_delay_ms < -kMaxDeltaDelayMs) { 87 return false; 88 } 89 return true; 90 } 91 92 bool StreamSynchronization::ComputeDelays(int relative_delay_ms, 93 int current_audio_delay_ms, 94 int* total_audio_delay_target_ms, 95 int* total_video_delay_target_ms) { 96 assert(total_audio_delay_target_ms && total_video_delay_target_ms); 97 98 int current_video_delay_ms = *total_video_delay_target_ms; 99 LOG(LS_VERBOSE) << "Audio delay: " << current_audio_delay_ms 100 << ", network delay diff: " << channel_delay_->network_delay 101 << " current diff: " << relative_delay_ms 102 << " for channel " << audio_channel_id_; 103 // Calculate the difference between the lowest possible video delay and 104 // the current audio delay. 105 int current_diff_ms = current_video_delay_ms - current_audio_delay_ms + 106 relative_delay_ms; 107 108 avg_diff_ms_ = ((kFilterLength - 1) * avg_diff_ms_ + 109 current_diff_ms) / kFilterLength; 110 if (abs(avg_diff_ms_) < kMinDeltaMs) { 111 // Don't adjust if the diff is within our margin. 112 return false; 113 } 114 115 // Make sure we don't move too fast. 116 int diff_ms = avg_diff_ms_ / 2; 117 diff_ms = std::min(diff_ms, kMaxChangeMs); 118 diff_ms = std::max(diff_ms, -kMaxChangeMs); 119 120 // Reset the average after a move to prevent overshooting reaction. 121 avg_diff_ms_ = 0; 122 123 if (diff_ms > 0) { 124 // The minimum video delay is longer than the current audio delay. 125 // We need to decrease extra video delay, or add extra audio delay. 126 if (channel_delay_->extra_video_delay_ms > base_target_delay_ms_) { 127 // We have extra delay added to ViE. Reduce this delay before adding 128 // extra delay to VoE. 129 channel_delay_->extra_video_delay_ms -= diff_ms; 130 channel_delay_->extra_audio_delay_ms = base_target_delay_ms_; 131 } else { // channel_delay_->extra_video_delay_ms > 0 132 // We have no extra video delay to remove, increase the audio delay. 133 channel_delay_->extra_audio_delay_ms += diff_ms; 134 channel_delay_->extra_video_delay_ms = base_target_delay_ms_; 135 } 136 } else { // if (diff_ms > 0) 137 // The video delay is lower than the current audio delay. 138 // We need to decrease extra audio delay, or add extra video delay. 139 if (channel_delay_->extra_audio_delay_ms > base_target_delay_ms_) { 140 // We have extra delay in VoiceEngine. 141 // Start with decreasing the voice delay. 142 // Note: diff_ms is negative; add the negative difference. 143 channel_delay_->extra_audio_delay_ms += diff_ms; 144 channel_delay_->extra_video_delay_ms = base_target_delay_ms_; 145 } else { // channel_delay_->extra_audio_delay_ms > base_target_delay_ms_ 146 // We have no extra delay in VoiceEngine, increase the video delay. 147 // Note: diff_ms is negative; subtract the negative difference. 148 channel_delay_->extra_video_delay_ms -= diff_ms; // X - (-Y) = X + Y. 149 channel_delay_->extra_audio_delay_ms = base_target_delay_ms_; 150 } 151 } 152 153 // Make sure that video is never below our target. 154 channel_delay_->extra_video_delay_ms = std::max( 155 channel_delay_->extra_video_delay_ms, base_target_delay_ms_); 156 157 int new_video_delay_ms; 158 if (channel_delay_->extra_video_delay_ms > base_target_delay_ms_) { 159 new_video_delay_ms = channel_delay_->extra_video_delay_ms; 160 } else { 161 // No change to the extra video delay. We are changing audio and we only 162 // allow to change one at the time. 163 new_video_delay_ms = channel_delay_->last_video_delay_ms; 164 } 165 166 // Make sure that we don't go below the extra video delay. 167 new_video_delay_ms = std::max( 168 new_video_delay_ms, channel_delay_->extra_video_delay_ms); 169 170 // Verify we don't go above the maximum allowed video delay. 171 new_video_delay_ms = 172 std::min(new_video_delay_ms, base_target_delay_ms_ + kMaxDeltaDelayMs); 173 174 int new_audio_delay_ms; 175 if (channel_delay_->extra_audio_delay_ms > base_target_delay_ms_) { 176 new_audio_delay_ms = channel_delay_->extra_audio_delay_ms; 177 } else { 178 // No change to the audio delay. We are changing video and we only 179 // allow to change one at the time. 180 new_audio_delay_ms = channel_delay_->last_audio_delay_ms; 181 } 182 183 // Make sure that we don't go below the extra audio delay. 184 new_audio_delay_ms = std::max( 185 new_audio_delay_ms, channel_delay_->extra_audio_delay_ms); 186 187 // Verify we don't go above the maximum allowed audio delay. 188 new_audio_delay_ms = 189 std::min(new_audio_delay_ms, base_target_delay_ms_ + kMaxDeltaDelayMs); 190 191 // Remember our last audio and video delays. 192 channel_delay_->last_video_delay_ms = new_video_delay_ms; 193 channel_delay_->last_audio_delay_ms = new_audio_delay_ms; 194 195 LOG(LS_VERBOSE) << "Sync video delay " << new_video_delay_ms 196 << " and audio delay " << channel_delay_->extra_audio_delay_ms 197 << " for video channel " << video_channel_id_ 198 << " for audio channel " << audio_channel_id_; 199 200 // Return values. 201 *total_video_delay_target_ms = new_video_delay_ms; 202 *total_audio_delay_target_ms = new_audio_delay_ms; 203 return true; 204 } 205 206 void StreamSynchronization::SetTargetBufferingDelay(int target_delay_ms) { 207 // Initial extra delay for audio (accounting for existing extra delay). 208 channel_delay_->extra_audio_delay_ms += 209 target_delay_ms - base_target_delay_ms_; 210 channel_delay_->last_audio_delay_ms += 211 target_delay_ms - base_target_delay_ms_; 212 213 // The video delay is compared to the last value (and how much we can update 214 // is limited by that as well). 215 channel_delay_->last_video_delay_ms += 216 target_delay_ms - base_target_delay_ms_; 217 218 channel_delay_->extra_video_delay_ms += 219 target_delay_ms - base_target_delay_ms_; 220 221 // Video is already delayed by the desired amount. 222 base_target_delay_ms_ = target_delay_ms; 223 } 224 225 } // namespace webrtc 226