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:
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user