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/modules/audio_coding/neteq/timestamp_scaler.h"
12 
13 #include "webrtc/modules/audio_coding/neteq/decoder_database.h"
14 #include "webrtc/modules/audio_coding/neteq/defines.h"
15 #include "webrtc/system_wrappers/include/logging.h"
16 
17 namespace webrtc {
18 
Reset()19 void TimestampScaler::Reset() {
20   first_packet_received_ = false;
21 }
22 
ToInternal(Packet * packet)23 void TimestampScaler::ToInternal(Packet* packet) {
24   if (!packet) {
25     return;
26   }
27   packet->header.timestamp = ToInternal(packet->header.timestamp,
28                                         packet->header.payloadType);
29 }
30 
ToInternal(PacketList * packet_list)31 void TimestampScaler::ToInternal(PacketList* packet_list) {
32   PacketList::iterator it;
33   for (it = packet_list->begin(); it != packet_list->end(); ++it) {
34     ToInternal(*it);
35   }
36 }
37 
ToInternal(uint32_t external_timestamp,uint8_t rtp_payload_type)38 uint32_t TimestampScaler::ToInternal(uint32_t external_timestamp,
39                                      uint8_t rtp_payload_type) {
40   const DecoderDatabase::DecoderInfo* info =
41       decoder_database_.GetDecoderInfo(rtp_payload_type);
42   if (!info) {
43     // Payload type is unknown. Do not scale.
44     return external_timestamp;
45   }
46   switch (info->codec_type) {
47     case NetEqDecoder::kDecoderG722:
48     case NetEqDecoder::kDecoderG722_2ch: {
49       // Use timestamp scaling with factor 2 (two output samples per RTP
50       // timestamp).
51       numerator_ = 2;
52       denominator_ = 1;
53       break;
54     }
55     case NetEqDecoder::kDecoderAVT:
56     case NetEqDecoder::kDecoderCNGnb:
57     case NetEqDecoder::kDecoderCNGwb:
58     case NetEqDecoder::kDecoderCNGswb32kHz:
59     case NetEqDecoder::kDecoderCNGswb48kHz: {
60       // Do not change the timestamp scaling settings for DTMF or CNG.
61       break;
62     }
63     default: {
64       // Do not use timestamp scaling for any other codec.
65       numerator_ = 1;
66       denominator_ = 1;
67       break;
68     }
69   }
70 
71   if (!(numerator_ == 1 && denominator_ == 1)) {
72     // We have a scale factor != 1.
73     if (!first_packet_received_) {
74       external_ref_ = external_timestamp;
75       internal_ref_ = external_timestamp;
76       first_packet_received_ = true;
77     }
78     int32_t external_diff = external_timestamp - external_ref_;
79     assert(denominator_ > 0);  // Should not be possible.
80     external_ref_ = external_timestamp;
81     internal_ref_ += (external_diff * numerator_) / denominator_;
82     return internal_ref_;
83   } else {
84     // No scaling.
85     return external_timestamp;
86   }
87 }
88 
89 
ToExternal(uint32_t internal_timestamp) const90 uint32_t TimestampScaler::ToExternal(uint32_t internal_timestamp) const {
91   if (!first_packet_received_ || (numerator_ == 1 && denominator_ == 1)) {
92     // Not initialized, or scale factor is 1.
93     return internal_timestamp;
94   } else {
95     int32_t internal_diff = internal_timestamp - internal_ref_;
96     assert(numerator_ > 0);  // Should not be possible.
97     // Do not update references in this method.
98     // Switch |denominator_| and |numerator_| to convert the other way.
99     return external_ref_ + (internal_diff * denominator_) / numerator_;
100   }
101 }
102 
103 }  // namespace webrtc
104