Fixed time moving backwards in the AudioCodingModule.
There was a fast path in PreprocessToAddData that would just use the
input timestamps if the input format was equal to the required format of
the encoder. This works well as long as the codec never changes. If we
are first doing resampling (specifically upsampling) and then change to
a codec that does not require resampling, we'll need to stick to
whatever input timestamp we left off at, rather than silently accepting
whatever we're sent.
BUG=622435
Review-Url: https://codereview.webrtc.org/2119393002
Cr-Commit-Position: refs/heads/master@{#13398}
diff --git a/webrtc/base/checks.h b/webrtc/base/checks.h
index 681361a..e66c061 100644
--- a/webrtc/base/checks.h
+++ b/webrtc/base/checks.h
@@ -220,7 +220,8 @@
// remainder is zero.
template <typename T>
inline T CheckedDivExact(T a, T b) {
- RTC_CHECK_EQ(a % b, static_cast<T>(0));
+ RTC_CHECK_EQ(a % b, static_cast<T>(0)) << a << " is not evenly divisible by "
+ << b;
return a / b;
}
diff --git a/webrtc/modules/audio_coding/acm2/audio_coding_module.cc b/webrtc/modules/audio_coding/acm2/audio_coding_module.cc
index 6170d18..b394c59 100644
--- a/webrtc/modules/audio_coding/acm2/audio_coding_module.cc
+++ b/webrtc/modules/audio_coding/acm2/audio_coding_module.cc
@@ -472,6 +472,11 @@
if (!HaveValidEncoder("Process"))
return -1;
+ if(!first_frame_) {
+ RTC_DCHECK_GT(input_data.input_timestamp, last_timestamp_)
+ << "Time should not move backwards";
+ }
+
// Scale the timestamp to the codec's RTP timestamp rate.
uint32_t rtp_timestamp =
first_frame_ ? input_data.input_timestamp
@@ -752,7 +757,8 @@
expected_codec_ts_ = in_frame.timestamp_;
first_10ms_data_ = true;
} else if (in_frame.timestamp_ != expected_in_ts_) {
- // TODO(turajs): Do we need a warning here.
+ LOG(LS_WARNING) << "Unexpected input timestamp: " << in_frame.timestamp_
+ << ", expected: " << expected_in_ts_;
expected_codec_ts_ +=
(in_frame.timestamp_ - expected_in_ts_) *
static_cast<uint32_t>(
@@ -764,9 +770,19 @@
if (!down_mix && !resample) {
// No pre-processing is required.
+ if (expected_in_ts_ == expected_codec_ts_) {
+ // If we've never resampled, we can use the input frame as-is
+ *ptr_out = &in_frame;
+ } else {
+ // Otherwise we'll need to alter the timestamp. Since in_frame is const,
+ // we'll have to make a copy of it.
+ preprocess_frame_.CopyFrom(in_frame);
+ preprocess_frame_.timestamp_ = expected_codec_ts_;
+ *ptr_out = &preprocess_frame_;
+ }
+
expected_in_ts_ += static_cast<uint32_t>(in_frame.samples_per_channel_);
expected_codec_ts_ += static_cast<uint32_t>(in_frame.samples_per_channel_);
- *ptr_out = &in_frame;
return 0;
}
diff --git a/webrtc/modules/audio_coding/test/TestVADDTX.cc b/webrtc/modules/audio_coding/test/TestVADDTX.cc
index 4f53e47c..541dfc3 100644
--- a/webrtc/modules/audio_coding/test/TestVADDTX.cc
+++ b/webrtc/modules/audio_coding/test/TestVADDTX.cc
@@ -101,12 +101,11 @@
}
uint16_t frame_size_samples = in_file.PayloadLength10Ms();
- uint32_t time_stamp = 0x12345678;
AudioFrame audio_frame;
while (!in_file.EndOfFile()) {
in_file.Read10MsData(audio_frame);
- audio_frame.timestamp_ = time_stamp;
- time_stamp += frame_size_samples;
+ audio_frame.timestamp_ = time_stamp_;
+ time_stamp_ += frame_size_samples;
EXPECT_GE(acm_send_->Add10MsData(audio_frame), 0);
bool muted;
acm_receive_->PlayoutData10Ms(kOutputFreqHz, &audio_frame, &muted);
diff --git a/webrtc/modules/audio_coding/test/TestVADDTX.h b/webrtc/modules/audio_coding/test/TestVADDTX.h
index 893babc..b7e9871 100644
--- a/webrtc/modules/audio_coding/test/TestVADDTX.h
+++ b/webrtc/modules/audio_coding/test/TestVADDTX.h
@@ -72,6 +72,7 @@
std::unique_ptr<AudioCodingModule> acm_receive_;
std::unique_ptr<Channel> channel_;
std::unique_ptr<ActivityMonitor> monitor_;
+ uint32_t time_stamp_ = 0x12345678;
};
// TestWebRtcVadDtx is to verify that the WebRTC VAD/DTX perform as they should.