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}
This commit is contained in:
ossu
2016-07-06 09:34:22 -07:00
committed by Commit bot
parent 1d4fefbbaf
commit 63fb95a68d
4 changed files with 23 additions and 6 deletions

View File

@ -220,7 +220,8 @@ class FatalMessage {
// remainder is zero. // remainder is zero.
template <typename T> template <typename T>
inline T CheckedDivExact(T a, T b) { 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; return a / b;
} }

View File

@ -472,6 +472,11 @@ int32_t AudioCodingModuleImpl::Encode(const InputData& input_data) {
if (!HaveValidEncoder("Process")) if (!HaveValidEncoder("Process"))
return -1; 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. // Scale the timestamp to the codec's RTP timestamp rate.
uint32_t rtp_timestamp = uint32_t rtp_timestamp =
first_frame_ ? input_data.input_timestamp first_frame_ ? input_data.input_timestamp
@ -752,7 +757,8 @@ int AudioCodingModuleImpl::PreprocessToAddData(const AudioFrame& in_frame,
expected_codec_ts_ = in_frame.timestamp_; expected_codec_ts_ = in_frame.timestamp_;
first_10ms_data_ = true; first_10ms_data_ = true;
} else if (in_frame.timestamp_ != expected_in_ts_) { } 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_ += expected_codec_ts_ +=
(in_frame.timestamp_ - expected_in_ts_) * (in_frame.timestamp_ - expected_in_ts_) *
static_cast<uint32_t>( static_cast<uint32_t>(
@ -764,9 +770,19 @@ int AudioCodingModuleImpl::PreprocessToAddData(const AudioFrame& in_frame,
if (!down_mix && !resample) { if (!down_mix && !resample) {
// No pre-processing is required. // 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_in_ts_ += static_cast<uint32_t>(in_frame.samples_per_channel_);
expected_codec_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; return 0;
} }

View File

@ -101,12 +101,11 @@ void TestVadDtx::Run(std::string in_filename, int frequency, int channels,
} }
uint16_t frame_size_samples = in_file.PayloadLength10Ms(); uint16_t frame_size_samples = in_file.PayloadLength10Ms();
uint32_t time_stamp = 0x12345678;
AudioFrame audio_frame; AudioFrame audio_frame;
while (!in_file.EndOfFile()) { while (!in_file.EndOfFile()) {
in_file.Read10MsData(audio_frame); in_file.Read10MsData(audio_frame);
audio_frame.timestamp_ = time_stamp; audio_frame.timestamp_ = time_stamp_;
time_stamp += frame_size_samples; time_stamp_ += frame_size_samples;
EXPECT_GE(acm_send_->Add10MsData(audio_frame), 0); EXPECT_GE(acm_send_->Add10MsData(audio_frame), 0);
bool muted; bool muted;
acm_receive_->PlayoutData10Ms(kOutputFreqHz, &audio_frame, &muted); acm_receive_->PlayoutData10Ms(kOutputFreqHz, &audio_frame, &muted);

View File

@ -72,6 +72,7 @@ class TestVadDtx : public ACMTest {
std::unique_ptr<AudioCodingModule> acm_receive_; std::unique_ptr<AudioCodingModule> acm_receive_;
std::unique_ptr<Channel> channel_; std::unique_ptr<Channel> channel_;
std::unique_ptr<ActivityMonitor> monitor_; std::unique_ptr<ActivityMonitor> monitor_;
uint32_t time_stamp_ = 0x12345678;
}; };
// TestWebRtcVadDtx is to verify that the WebRTC VAD/DTX perform as they should. // TestWebRtcVadDtx is to verify that the WebRTC VAD/DTX perform as they should.