This is still a tiny lie, since it checks for kCodecArbitrary to avoid scaling a codec with an external decoder, because of missing information in that case. The main point is still true, though. Once the next CL is in, removing NetEqDecoder usage completely in DecoderDatabase, another workaround will be in place for external decoders until we can fully deprecate them. BUG=webrtc:5805 Review-Url: https://codereview.webrtc.org/2270063006 Cr-Commit-Position: refs/heads/master@{#13952}
89 lines
3.0 KiB
C++
89 lines
3.0 KiB
C++
/*
|
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "webrtc/modules/audio_coding/neteq/timestamp_scaler.h"
|
|
|
|
#include "webrtc/modules/audio_coding/neteq/decoder_database.h"
|
|
#include "webrtc/system_wrappers/include/logging.h"
|
|
|
|
namespace webrtc {
|
|
|
|
void TimestampScaler::Reset() {
|
|
first_packet_received_ = false;
|
|
}
|
|
|
|
void TimestampScaler::ToInternal(Packet* packet) {
|
|
if (!packet) {
|
|
return;
|
|
}
|
|
packet->header.timestamp = ToInternal(packet->header.timestamp,
|
|
packet->header.payloadType);
|
|
}
|
|
|
|
void TimestampScaler::ToInternal(PacketList* packet_list) {
|
|
PacketList::iterator it;
|
|
for (it = packet_list->begin(); it != packet_list->end(); ++it) {
|
|
ToInternal(*it);
|
|
}
|
|
}
|
|
|
|
uint32_t TimestampScaler::ToInternal(uint32_t external_timestamp,
|
|
uint8_t rtp_payload_type) {
|
|
const DecoderDatabase::DecoderInfo* info =
|
|
decoder_database_.GetDecoderInfo(rtp_payload_type);
|
|
if (!info) {
|
|
// Payload type is unknown. Do not scale.
|
|
return external_timestamp;
|
|
}
|
|
if (!(info->IsComfortNoise() || info->IsDtmf())) {
|
|
// Do not change the timestamp scaling settings for DTMF or CNG.
|
|
numerator_ = info->SampleRateHz();
|
|
if (info->codec_type == NetEqDecoder::kDecoderArbitrary) {
|
|
// We have no format mapping for "arbitrary" external codecs, so we cannot
|
|
// support timestamp scaling of them.
|
|
denominator_ = numerator_;
|
|
} else {
|
|
denominator_ = info->GetFormat().clockrate_hz;
|
|
}
|
|
}
|
|
if (numerator_ != denominator_) {
|
|
// We have a scale factor != 1.
|
|
if (!first_packet_received_) {
|
|
external_ref_ = external_timestamp;
|
|
internal_ref_ = external_timestamp;
|
|
first_packet_received_ = true;
|
|
}
|
|
const int64_t external_diff = int64_t{external_timestamp} - external_ref_;
|
|
assert(denominator_ > 0); // Should not be possible.
|
|
external_ref_ = external_timestamp;
|
|
internal_ref_ += (external_diff * numerator_) / denominator_;
|
|
return internal_ref_;
|
|
} else {
|
|
// No scaling.
|
|
return external_timestamp;
|
|
}
|
|
}
|
|
|
|
|
|
uint32_t TimestampScaler::ToExternal(uint32_t internal_timestamp) const {
|
|
if (!first_packet_received_ || (numerator_ == denominator_)) {
|
|
// Not initialized, or scale factor is 1.
|
|
return internal_timestamp;
|
|
} else {
|
|
const int64_t internal_diff = int64_t{internal_timestamp} - internal_ref_;
|
|
assert(numerator_ > 0); // Should not be possible.
|
|
// Do not update references in this method.
|
|
// Switch |denominator_| and |numerator_| to convert the other way.
|
|
return external_ref_ + (internal_diff * denominator_) / numerator_;
|
|
}
|
|
}
|
|
|
|
} // namespace webrtc
|