OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h" | 11 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h" |
12 | 12 |
13 #include <assert.h> // assert | 13 #include <assert.h> // assert |
14 #include <math.h> // pow() | 14 #include <math.h> // pow() |
15 #include <string.h> // memcpy() | 15 #include <string.h> // memcpy() |
16 | 16 |
17 #include "webrtc/base/logging.h" | 17 #include "webrtc/base/logging.h" |
18 #include "webrtc/base/trace_event.h" | 18 #include "webrtc/base/trace_event.h" |
19 | 19 |
20 namespace webrtc { | 20 namespace webrtc { |
21 RTPReceiverStrategy* RTPReceiverStrategy::CreateAudioStrategy( | 21 RTPReceiverStrategy* RTPReceiverStrategy::CreateAudioStrategy( |
22 RtpData* data_callback) { | 22 RtpData* data_callback) { |
23 return new RTPReceiverAudio(data_callback); | 23 return new RTPReceiverAudio(data_callback); |
24 } | 24 } |
25 | 25 |
26 RTPReceiverAudio::RTPReceiverAudio(RtpData* data_callback) | 26 RTPReceiverAudio::RTPReceiverAudio(RtpData* data_callback) |
27 : RTPReceiverStrategy(data_callback), | 27 : RTPReceiverStrategy(data_callback), |
28 TelephoneEventHandler(), | 28 TelephoneEventHandler(), |
29 last_received_frequency_(8000), | |
30 telephone_event_forward_to_decoder_(false), | 29 telephone_event_forward_to_decoder_(false), |
31 telephone_event_payload_type_(-1), | 30 telephone_event_payload_type_(-1), |
32 cng_nb_payload_type_(-1), | 31 cng_nb_payload_type_(-1), |
33 cng_wb_payload_type_(-1), | 32 cng_wb_payload_type_(-1), |
34 cng_swb_payload_type_(-1), | 33 cng_swb_payload_type_(-1), |
35 cng_fb_payload_type_(-1), | 34 cng_fb_payload_type_(-1), |
36 cng_payload_type_(-1), | |
37 g722_payload_type_(-1), | |
38 last_received_g722_(false), | |
39 num_energy_(0), | 35 num_energy_(0), |
40 current_remote_energy_() { | 36 current_remote_energy_() { |
41 last_payload_.Audio.channels = 1; | 37 last_payload_.Audio.channels = 1; |
42 memset(current_remote_energy_, 0, sizeof(current_remote_energy_)); | 38 memset(current_remote_energy_, 0, sizeof(current_remote_energy_)); |
43 } | 39 } |
44 | 40 |
45 // Outband TelephoneEvent(DTMF) detection | 41 // Outband TelephoneEvent(DTMF) detection |
46 void RTPReceiverAudio::SetTelephoneEventForwardToDecoder( | 42 void RTPReceiverAudio::SetTelephoneEventForwardToDecoder( |
47 bool forward_to_decoder) { | 43 bool forward_to_decoder) { |
48 rtc::CritScope lock(&crit_sect_); | 44 rtc::CritScope lock(&crit_sect_); |
49 telephone_event_forward_to_decoder_ = forward_to_decoder; | 45 telephone_event_forward_to_decoder_ = forward_to_decoder; |
50 } | 46 } |
51 | 47 |
52 // Is forwarding of outband telephone events turned on/off? | 48 // Is forwarding of outband telephone events turned on/off? |
53 bool RTPReceiverAudio::TelephoneEventForwardToDecoder() const { | 49 bool RTPReceiverAudio::TelephoneEventForwardToDecoder() const { |
54 rtc::CritScope lock(&crit_sect_); | 50 rtc::CritScope lock(&crit_sect_); |
55 return telephone_event_forward_to_decoder_; | 51 return telephone_event_forward_to_decoder_; |
56 } | 52 } |
57 | 53 |
58 bool RTPReceiverAudio::TelephoneEventPayloadType( | 54 bool RTPReceiverAudio::TelephoneEventPayloadType( |
59 int8_t payload_type) const { | 55 int8_t payload_type) const { |
60 rtc::CritScope lock(&crit_sect_); | 56 rtc::CritScope lock(&crit_sect_); |
61 return telephone_event_payload_type_ == payload_type; | 57 return telephone_event_payload_type_ == payload_type; |
62 } | 58 } |
63 | 59 |
64 bool RTPReceiverAudio::CNGPayloadType(int8_t payload_type, | 60 bool RTPReceiverAudio::CNGPayloadType(int8_t payload_type) { |
65 uint32_t* frequency, | |
66 bool* cng_payload_type_has_changed) { | |
67 rtc::CritScope lock(&crit_sect_); | 61 rtc::CritScope lock(&crit_sect_); |
68 *cng_payload_type_has_changed = false; | |
69 | |
70 // We can have four CNG on 8000Hz, 16000Hz, 32000Hz and 48000Hz. | 62 // We can have four CNG on 8000Hz, 16000Hz, 32000Hz and 48000Hz. |
hlundin-webrtc
2016/10/04 11:38:18
Wording is a bit choppy in this comment. Bonus poi
ossu
2016/10/04 12:40:24
I've reworded here and moved it down to where the
| |
71 if (cng_nb_payload_type_ == payload_type) { | 63 return payload_type == cng_nb_payload_type_ || |
72 *frequency = 8000; | 64 payload_type == cng_wb_payload_type_ || |
73 if (cng_payload_type_ != -1 && cng_payload_type_ != cng_nb_payload_type_) | 65 payload_type == cng_swb_payload_type_ || |
74 *cng_payload_type_has_changed = true; | 66 payload_type == cng_fb_payload_type_; |
75 | |
76 cng_payload_type_ = cng_nb_payload_type_; | |
77 return true; | |
78 } else if (cng_wb_payload_type_ == payload_type) { | |
79 // if last received codec is G.722 we must use frequency 8000 | |
80 if (last_received_g722_) { | |
81 *frequency = 8000; | |
82 } else { | |
83 *frequency = 16000; | |
84 } | |
85 if (cng_payload_type_ != -1 && cng_payload_type_ != cng_wb_payload_type_) | |
86 *cng_payload_type_has_changed = true; | |
87 cng_payload_type_ = cng_wb_payload_type_; | |
88 return true; | |
89 } else if (cng_swb_payload_type_ == payload_type) { | |
90 *frequency = 32000; | |
91 if ((cng_payload_type_ != -1) && | |
92 (cng_payload_type_ != cng_swb_payload_type_)) | |
93 *cng_payload_type_has_changed = true; | |
94 cng_payload_type_ = cng_swb_payload_type_; | |
95 return true; | |
96 } else if (cng_fb_payload_type_ == payload_type) { | |
97 *frequency = 48000; | |
98 if (cng_payload_type_ != -1 && cng_payload_type_ != cng_fb_payload_type_) | |
99 *cng_payload_type_has_changed = true; | |
100 cng_payload_type_ = cng_fb_payload_type_; | |
101 return true; | |
102 } else { | |
103 // not CNG | |
104 if (g722_payload_type_ == payload_type) { | |
105 last_received_g722_ = true; | |
106 } else { | |
107 last_received_g722_ = false; | |
108 } | |
109 } | |
110 return false; | |
111 } | 67 } |
112 | 68 |
113 bool RTPReceiverAudio::ShouldReportCsrcChanges(uint8_t payload_type) const { | 69 bool RTPReceiverAudio::ShouldReportCsrcChanges(uint8_t payload_type) const { |
114 // Don't do this for DTMF packets, otherwise it's fine. | 70 // Don't do this for DTMF packets, otherwise it's fine. |
115 return !TelephoneEventPayloadType(payload_type); | 71 return !TelephoneEventPayloadType(payload_type); |
116 } | 72 } |
117 | 73 |
118 // - Sample based or frame based codecs based on RFC 3551 | 74 // - Sample based or frame based codecs based on RFC 3551 |
119 // - | 75 // - |
120 // - NOTE! There is one error in the RFC, stating G.722 uses 8 bits/samples. | 76 // - NOTE! There is one error in the RFC, stating G.722 uses 8 bits/samples. |
(...skipping 29 matching lines...) Expand all Loading... | |
150 int32_t RTPReceiverAudio::OnNewPayloadTypeCreated( | 106 int32_t RTPReceiverAudio::OnNewPayloadTypeCreated( |
151 const char payload_name[RTP_PAYLOAD_NAME_SIZE], | 107 const char payload_name[RTP_PAYLOAD_NAME_SIZE], |
152 int8_t payload_type, | 108 int8_t payload_type, |
153 uint32_t frequency) { | 109 uint32_t frequency) { |
154 rtc::CritScope lock(&crit_sect_); | 110 rtc::CritScope lock(&crit_sect_); |
155 | 111 |
156 if (RtpUtility::StringCompare(payload_name, "telephone-event", 15)) { | 112 if (RtpUtility::StringCompare(payload_name, "telephone-event", 15)) { |
157 telephone_event_payload_type_ = payload_type; | 113 telephone_event_payload_type_ = payload_type; |
158 } | 114 } |
159 if (RtpUtility::StringCompare(payload_name, "cn", 2)) { | 115 if (RtpUtility::StringCompare(payload_name, "cn", 2)) { |
160 // we can have three CNG on 8000Hz, 16000Hz and 32000Hz | |
hlundin-webrtc
2016/10/04 11:38:18
lol
| |
161 if (frequency == 8000) { | 116 if (frequency == 8000) { |
162 cng_nb_payload_type_ = payload_type; | 117 cng_nb_payload_type_ = payload_type; |
163 } else if (frequency == 16000) { | 118 } else if (frequency == 16000) { |
164 cng_wb_payload_type_ = payload_type; | 119 cng_wb_payload_type_ = payload_type; |
165 } else if (frequency == 32000) { | 120 } else if (frequency == 32000) { |
166 cng_swb_payload_type_ = payload_type; | 121 cng_swb_payload_type_ = payload_type; |
167 } else if (frequency == 48000) { | 122 } else if (frequency == 48000) { |
168 cng_fb_payload_type_ = payload_type; | 123 cng_fb_payload_type_ = payload_type; |
169 } else { | 124 } else { |
170 assert(false); | 125 assert(false); |
(...skipping 26 matching lines...) Expand all Loading... | |
197 LOG(LS_INFO) << "Received first audio RTP packet"; | 152 LOG(LS_INFO) << "Received first audio RTP packet"; |
198 } | 153 } |
199 | 154 |
200 return ParseAudioCodecSpecific(rtp_header, | 155 return ParseAudioCodecSpecific(rtp_header, |
201 payload, | 156 payload, |
202 payload_length, | 157 payload_length, |
203 specific_payload.Audio, | 158 specific_payload.Audio, |
204 is_red); | 159 is_red); |
205 } | 160 } |
206 | 161 |
207 int RTPReceiverAudio::GetPayloadTypeFrequency() const { | |
208 rtc::CritScope lock(&crit_sect_); | |
209 if (last_received_g722_) { | |
210 return 8000; | |
211 } | |
212 return last_received_frequency_; | |
213 } | |
214 | |
215 RTPAliveType RTPReceiverAudio::ProcessDeadOrAlive( | 162 RTPAliveType RTPReceiverAudio::ProcessDeadOrAlive( |
216 uint16_t last_payload_length) const { | 163 uint16_t last_payload_length) const { |
217 | 164 |
218 // Our CNG is 9 bytes; if it's a likely CNG the receiver needs to check | 165 // Our CNG is 9 bytes; if it's a likely CNG the receiver needs to check |
219 // kRtpNoRtp against NetEq speech_type kOutputPLCtoCNG. | 166 // kRtpNoRtp against NetEq speech_type kOutputPLCtoCNG. |
220 if (last_payload_length < 10) { // our CNG is 9 bytes | 167 if (last_payload_length < 10) { // our CNG is 9 bytes |
221 return kRtpNoRtp; | 168 return kRtpNoRtp; |
222 } else { | 169 } else { |
223 return kRtpDead; | 170 return kRtpDead; |
224 } | 171 } |
225 } | 172 } |
226 | 173 |
227 void RTPReceiverAudio::CheckPayloadChanged(int8_t payload_type, | 174 void RTPReceiverAudio::CheckPayloadChanged(int8_t payload_type, |
danilchap
2016/10/03 14:29:38
may be pull string further and change signature of
hlundin-webrtc
2016/10/04 11:38:18
Would be nice, but I'm afraid that will lead into
| |
228 PayloadUnion* specific_payload, | 175 PayloadUnion* specific_payload, |
hlundin-webrtc
2016/10/04 11:38:18
/* specific_payload */
ossu
2016/10/04 12:40:24
Done.
| |
229 bool* should_discard_changes) { | 176 bool* should_discard_changes) { |
230 *should_discard_changes = false; | 177 *should_discard_changes = |
231 | 178 TelephoneEventPayloadType(payload_type) || CNGPayloadType(payload_type); |
232 if (TelephoneEventPayloadType(payload_type)) { | |
233 // Don't do callbacks for DTMF packets. | |
234 *should_discard_changes = true; | |
235 return; | |
236 } | |
237 // frequency is updated for CNG | |
238 bool cng_payload_type_has_changed = false; | |
239 bool is_cng_payload_type = CNGPayloadType(payload_type, | |
240 &specific_payload->Audio.frequency, | |
241 &cng_payload_type_has_changed); | |
242 | |
243 if (is_cng_payload_type) { | |
244 // Don't do callbacks for DTMF packets. | |
245 *should_discard_changes = true; | |
246 return; | |
247 } | |
248 } | 179 } |
249 | 180 |
250 int RTPReceiverAudio::Energy(uint8_t array_of_energy[kRtpCsrcSize]) const { | 181 int RTPReceiverAudio::Energy(uint8_t array_of_energy[kRtpCsrcSize]) const { |
251 rtc::CritScope cs(&crit_sect_); | 182 rtc::CritScope cs(&crit_sect_); |
252 | 183 |
253 assert(num_energy_ <= kRtpCsrcSize); | 184 assert(num_energy_ <= kRtpCsrcSize); |
254 | 185 |
255 if (num_energy_ > 0) { | 186 if (num_energy_ > 0) { |
256 memcpy(array_of_energy, current_remote_energy_, | 187 memcpy(array_of_energy, current_remote_energy_, |
257 sizeof(uint8_t) * num_energy_); | 188 sizeof(uint8_t) * num_energy_); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
330 | 261 |
331 // RFC 4733 2.5.1.3 & 2.5.2.3 Long-Duration Events | 262 // RFC 4733 2.5.1.3 & 2.5.2.3 Long-Duration Events |
332 // should not be a problem since we don't care about the duration | 263 // should not be a problem since we don't care about the duration |
333 | 264 |
334 // RFC 4733 See 2.5.1.5. & 2.5.2.4. Multiple Events in a Packet | 265 // RFC 4733 See 2.5.1.5. & 2.5.2.4. Multiple Events in a Packet |
335 } | 266 } |
336 | 267 |
337 { | 268 { |
338 rtc::CritScope lock(&crit_sect_); | 269 rtc::CritScope lock(&crit_sect_); |
339 | 270 |
340 if (!telephone_event_packet) { | |
341 last_received_frequency_ = audio_specific.frequency; | |
342 } | |
343 | |
344 // Check if this is a CNG packet, receiver might want to know | 271 // Check if this is a CNG packet, receiver might want to know |
345 uint32_t ignored; | 272 if (CNGPayloadType(rtp_header->header.payloadType)) { |
346 bool also_ignored; | |
347 if (CNGPayloadType(rtp_header->header.payloadType, | |
348 &ignored, | |
349 &also_ignored)) { | |
350 rtp_header->type.Audio.isCNG = true; | 273 rtp_header->type.Audio.isCNG = true; |
351 rtp_header->frameType = kAudioFrameCN; | 274 rtp_header->frameType = kAudioFrameCN; |
352 } else { | 275 } else { |
353 rtp_header->frameType = kAudioFrameSpeech; | 276 rtp_header->frameType = kAudioFrameSpeech; |
354 rtp_header->type.Audio.isCNG = false; | 277 rtp_header->type.Audio.isCNG = false; |
355 } | 278 } |
356 | 279 |
357 // check if it's a DTMF event, hence something we can playout | 280 // check if it's a DTMF event, hence something we can playout |
358 if (telephone_event_packet) { | 281 if (telephone_event_packet) { |
359 if (!telephone_event_forward_to_decoder_) { | 282 if (!telephone_event_forward_to_decoder_) { |
(...skipping 16 matching lines...) Expand all Loading... | |
376 // only one frame in the RED strip the one byte to help NetEq | 299 // only one frame in the RED strip the one byte to help NetEq |
377 return data_callback_->OnReceivedPayloadData( | 300 return data_callback_->OnReceivedPayloadData( |
378 payload_data + 1, payload_length - 1, rtp_header); | 301 payload_data + 1, payload_length - 1, rtp_header); |
379 } | 302 } |
380 | 303 |
381 rtp_header->type.Audio.channel = audio_specific.channels; | 304 rtp_header->type.Audio.channel = audio_specific.channels; |
382 return data_callback_->OnReceivedPayloadData( | 305 return data_callback_->OnReceivedPayloadData( |
383 payload_data, payload_length, rtp_header); | 306 payload_data, payload_length, rtp_header); |
384 } | 307 } |
385 } // namespace webrtc | 308 } // namespace webrtc |
OLD | NEW |