| 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 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" | |
| 20 | 19 |
| 21 namespace webrtc { | 20 namespace webrtc { |
| 22 RTPReceiverStrategy* RTPReceiverStrategy::CreateAudioStrategy( | 21 RTPReceiverStrategy* RTPReceiverStrategy::CreateAudioStrategy( |
| 23 RtpData* data_callback) { | 22 RtpData* data_callback) { |
| 24 return new RTPReceiverAudio(data_callback); | 23 return new RTPReceiverAudio(data_callback); |
| 25 } | 24 } |
| 26 | 25 |
| 27 RTPReceiverAudio::RTPReceiverAudio(RtpData* data_callback) | 26 RTPReceiverAudio::RTPReceiverAudio(RtpData* data_callback) |
| 28 : RTPReceiverStrategy(data_callback), | 27 : RTPReceiverStrategy(data_callback), |
| 29 TelephoneEventHandler(), | 28 TelephoneEventHandler(), |
| 30 last_received_frequency_(8000), | 29 last_received_frequency_(8000), |
| 31 telephone_event_forward_to_decoder_(false), | 30 telephone_event_forward_to_decoder_(false), |
| 32 telephone_event_payload_type_(-1), | 31 telephone_event_payload_type_(-1), |
| 33 cng_nb_payload_type_(-1), | 32 cng_nb_payload_type_(-1), |
| 34 cng_wb_payload_type_(-1), | 33 cng_wb_payload_type_(-1), |
| 35 cng_swb_payload_type_(-1), | 34 cng_swb_payload_type_(-1), |
| 36 cng_fb_payload_type_(-1), | 35 cng_fb_payload_type_(-1), |
| 37 cng_payload_type_(-1), | 36 cng_payload_type_(-1), |
| 38 g722_payload_type_(-1), | 37 g722_payload_type_(-1), |
| 39 last_received_g722_(false), | 38 last_received_g722_(false), |
| 40 num_energy_(0), | 39 num_energy_(0), |
| 41 current_remote_energy_() { | 40 current_remote_energy_() { |
| 42 last_payload_.Audio.channels = 1; | 41 last_payload_.Audio.channels = 1; |
| 43 memset(current_remote_energy_, 0, sizeof(current_remote_energy_)); | 42 memset(current_remote_energy_, 0, sizeof(current_remote_energy_)); |
| 44 } | 43 } |
| 45 | 44 |
| 46 // Outband TelephoneEvent(DTMF) detection | 45 // Outband TelephoneEvent(DTMF) detection |
| 47 void RTPReceiverAudio::SetTelephoneEventForwardToDecoder( | 46 void RTPReceiverAudio::SetTelephoneEventForwardToDecoder( |
| 48 bool forward_to_decoder) { | 47 bool forward_to_decoder) { |
| 49 CriticalSectionScoped lock(crit_sect_.get()); | 48 rtc::CritScope lock(&crit_sect_); |
| 50 telephone_event_forward_to_decoder_ = forward_to_decoder; | 49 telephone_event_forward_to_decoder_ = forward_to_decoder; |
| 51 } | 50 } |
| 52 | 51 |
| 53 // Is forwarding of outband telephone events turned on/off? | 52 // Is forwarding of outband telephone events turned on/off? |
| 54 bool RTPReceiverAudio::TelephoneEventForwardToDecoder() const { | 53 bool RTPReceiverAudio::TelephoneEventForwardToDecoder() const { |
| 55 CriticalSectionScoped lock(crit_sect_.get()); | 54 rtc::CritScope lock(&crit_sect_); |
| 56 return telephone_event_forward_to_decoder_; | 55 return telephone_event_forward_to_decoder_; |
| 57 } | 56 } |
| 58 | 57 |
| 59 bool RTPReceiverAudio::TelephoneEventPayloadType( | 58 bool RTPReceiverAudio::TelephoneEventPayloadType( |
| 60 int8_t payload_type) const { | 59 int8_t payload_type) const { |
| 61 CriticalSectionScoped lock(crit_sect_.get()); | 60 rtc::CritScope lock(&crit_sect_); |
| 62 return telephone_event_payload_type_ == payload_type; | 61 return telephone_event_payload_type_ == payload_type; |
| 63 } | 62 } |
| 64 | 63 |
| 65 bool RTPReceiverAudio::CNGPayloadType(int8_t payload_type, | 64 bool RTPReceiverAudio::CNGPayloadType(int8_t payload_type, |
| 66 uint32_t* frequency, | 65 uint32_t* frequency, |
| 67 bool* cng_payload_type_has_changed) { | 66 bool* cng_payload_type_has_changed) { |
| 68 CriticalSectionScoped lock(crit_sect_.get()); | 67 rtc::CritScope lock(&crit_sect_); |
| 69 *cng_payload_type_has_changed = false; | 68 *cng_payload_type_has_changed = false; |
| 70 | 69 |
| 71 // We can have four CNG on 8000Hz, 16000Hz, 32000Hz and 48000Hz. | 70 // We can have four CNG on 8000Hz, 16000Hz, 32000Hz and 48000Hz. |
| 72 if (cng_nb_payload_type_ == payload_type) { | 71 if (cng_nb_payload_type_ == payload_type) { |
| 73 *frequency = 8000; | 72 *frequency = 8000; |
| 74 if (cng_payload_type_ != -1 && cng_payload_type_ != cng_nb_payload_type_) | 73 if (cng_payload_type_ != -1 && cng_payload_type_ != cng_nb_payload_type_) |
| 75 *cng_payload_type_has_changed = true; | 74 *cng_payload_type_has_changed = true; |
| 76 | 75 |
| 77 cng_payload_type_ = cng_nb_payload_type_; | 76 cng_payload_type_ = cng_nb_payload_type_; |
| 78 return true; | 77 return true; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 // - GSM frame N/A 8,000 20 20 | 144 // - GSM frame N/A 8,000 20 20 |
| 146 // - GSM-EFR frame N/A 8,000 20 20 | 145 // - GSM-EFR frame N/A 8,000 20 20 |
| 147 // - LPC frame N/A 8,000 20 20 | 146 // - LPC frame N/A 8,000 20 20 |
| 148 // - MPA frame N/A var. var. | 147 // - MPA frame N/A var. var. |
| 149 // - | 148 // - |
| 150 // - G7221 frame N/A | 149 // - G7221 frame N/A |
| 151 int32_t RTPReceiverAudio::OnNewPayloadTypeCreated( | 150 int32_t RTPReceiverAudio::OnNewPayloadTypeCreated( |
| 152 const char payload_name[RTP_PAYLOAD_NAME_SIZE], | 151 const char payload_name[RTP_PAYLOAD_NAME_SIZE], |
| 153 int8_t payload_type, | 152 int8_t payload_type, |
| 154 uint32_t frequency) { | 153 uint32_t frequency) { |
| 155 CriticalSectionScoped lock(crit_sect_.get()); | 154 rtc::CritScope lock(&crit_sect_); |
| 156 | 155 |
| 157 if (RtpUtility::StringCompare(payload_name, "telephone-event", 15)) { | 156 if (RtpUtility::StringCompare(payload_name, "telephone-event", 15)) { |
| 158 telephone_event_payload_type_ = payload_type; | 157 telephone_event_payload_type_ = payload_type; |
| 159 } | 158 } |
| 160 if (RtpUtility::StringCompare(payload_name, "cn", 2)) { | 159 if (RtpUtility::StringCompare(payload_name, "cn", 2)) { |
| 161 // we can have three CNG on 8000Hz, 16000Hz and 32000Hz | 160 // we can have three CNG on 8000Hz, 16000Hz and 32000Hz |
| 162 if (frequency == 8000) { | 161 if (frequency == 8000) { |
| 163 cng_nb_payload_type_ = payload_type; | 162 cng_nb_payload_type_ = payload_type; |
| 164 } else if (frequency == 16000) { | 163 } else if (frequency == 16000) { |
| 165 cng_wb_payload_type_ = payload_type; | 164 cng_wb_payload_type_ = payload_type; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 } | 198 } |
| 200 | 199 |
| 201 return ParseAudioCodecSpecific(rtp_header, | 200 return ParseAudioCodecSpecific(rtp_header, |
| 202 payload, | 201 payload, |
| 203 payload_length, | 202 payload_length, |
| 204 specific_payload.Audio, | 203 specific_payload.Audio, |
| 205 is_red); | 204 is_red); |
| 206 } | 205 } |
| 207 | 206 |
| 208 int RTPReceiverAudio::GetPayloadTypeFrequency() const { | 207 int RTPReceiverAudio::GetPayloadTypeFrequency() const { |
| 209 CriticalSectionScoped lock(crit_sect_.get()); | 208 rtc::CritScope lock(&crit_sect_); |
| 210 if (last_received_g722_) { | 209 if (last_received_g722_) { |
| 211 return 8000; | 210 return 8000; |
| 212 } | 211 } |
| 213 return last_received_frequency_; | 212 return last_received_frequency_; |
| 214 } | 213 } |
| 215 | 214 |
| 216 RTPAliveType RTPReceiverAudio::ProcessDeadOrAlive( | 215 RTPAliveType RTPReceiverAudio::ProcessDeadOrAlive( |
| 217 uint16_t last_payload_length) const { | 216 uint16_t last_payload_length) const { |
| 218 | 217 |
| 219 // Our CNG is 9 bytes; if it's a likely CNG the receiver needs to check | 218 // Our CNG is 9 bytes; if it's a likely CNG the receiver needs to check |
| (...skipping 22 matching lines...) Expand all Loading... |
| 242 &cng_payload_type_has_changed); | 241 &cng_payload_type_has_changed); |
| 243 | 242 |
| 244 if (is_cng_payload_type) { | 243 if (is_cng_payload_type) { |
| 245 // Don't do callbacks for DTMF packets. | 244 // Don't do callbacks for DTMF packets. |
| 246 *should_discard_changes = true; | 245 *should_discard_changes = true; |
| 247 return; | 246 return; |
| 248 } | 247 } |
| 249 } | 248 } |
| 250 | 249 |
| 251 int RTPReceiverAudio::Energy(uint8_t array_of_energy[kRtpCsrcSize]) const { | 250 int RTPReceiverAudio::Energy(uint8_t array_of_energy[kRtpCsrcSize]) const { |
| 252 CriticalSectionScoped cs(crit_sect_.get()); | 251 rtc::CritScope cs(&crit_sect_); |
| 253 | 252 |
| 254 assert(num_energy_ <= kRtpCsrcSize); | 253 assert(num_energy_ <= kRtpCsrcSize); |
| 255 | 254 |
| 256 if (num_energy_ > 0) { | 255 if (num_energy_ > 0) { |
| 257 memcpy(array_of_energy, current_remote_energy_, | 256 memcpy(array_of_energy, current_remote_energy_, |
| 258 sizeof(uint8_t) * num_energy_); | 257 sizeof(uint8_t) * num_energy_); |
| 259 } | 258 } |
| 260 return num_energy_; | 259 return num_energy_; |
| 261 } | 260 } |
| 262 | 261 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 284 const AudioPayload& audio_specific, | 283 const AudioPayload& audio_specific, |
| 285 bool is_red) { | 284 bool is_red) { |
| 286 | 285 |
| 287 if (payload_length == 0) { | 286 if (payload_length == 0) { |
| 288 return 0; | 287 return 0; |
| 289 } | 288 } |
| 290 | 289 |
| 291 bool telephone_event_packet = | 290 bool telephone_event_packet = |
| 292 TelephoneEventPayloadType(rtp_header->header.payloadType); | 291 TelephoneEventPayloadType(rtp_header->header.payloadType); |
| 293 if (telephone_event_packet) { | 292 if (telephone_event_packet) { |
| 294 CriticalSectionScoped lock(crit_sect_.get()); | 293 rtc::CritScope lock(&crit_sect_); |
| 295 | 294 |
| 296 // RFC 4733 2.3 | 295 // RFC 4733 2.3 |
| 297 // 0 1 2 3 | 296 // 0 1 2 3 |
| 298 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | 297 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| 299 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 298 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 300 // | event |E|R| volume | duration | | 299 // | event |E|R| volume | duration | |
| 301 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 300 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 302 // | 301 // |
| 303 if (payload_length % 4 != 0) { | 302 if (payload_length % 4 != 0) { |
| 304 return -1; | 303 return -1; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 329 } | 328 } |
| 330 } | 329 } |
| 331 | 330 |
| 332 // RFC 4733 2.5.1.3 & 2.5.2.3 Long-Duration Events | 331 // RFC 4733 2.5.1.3 & 2.5.2.3 Long-Duration Events |
| 333 // should not be a problem since we don't care about the duration | 332 // should not be a problem since we don't care about the duration |
| 334 | 333 |
| 335 // RFC 4733 See 2.5.1.5. & 2.5.2.4. Multiple Events in a Packet | 334 // RFC 4733 See 2.5.1.5. & 2.5.2.4. Multiple Events in a Packet |
| 336 } | 335 } |
| 337 | 336 |
| 338 { | 337 { |
| 339 CriticalSectionScoped lock(crit_sect_.get()); | 338 rtc::CritScope lock(&crit_sect_); |
| 340 | 339 |
| 341 if (!telephone_event_packet) { | 340 if (!telephone_event_packet) { |
| 342 last_received_frequency_ = audio_specific.frequency; | 341 last_received_frequency_ = audio_specific.frequency; |
| 343 } | 342 } |
| 344 | 343 |
| 345 // Check if this is a CNG packet, receiver might want to know | 344 // Check if this is a CNG packet, receiver might want to know |
| 346 uint32_t ignored; | 345 uint32_t ignored; |
| 347 bool also_ignored; | 346 bool also_ignored; |
| 348 if (CNGPayloadType(rtp_header->header.payloadType, | 347 if (CNGPayloadType(rtp_header->header.payloadType, |
| 349 &ignored, | 348 &ignored, |
| (...skipping 27 matching lines...) Expand all Loading... |
| 377 // only one frame in the RED strip the one byte to help NetEq | 376 // only one frame in the RED strip the one byte to help NetEq |
| 378 return data_callback_->OnReceivedPayloadData( | 377 return data_callback_->OnReceivedPayloadData( |
| 379 payload_data + 1, payload_length - 1, rtp_header); | 378 payload_data + 1, payload_length - 1, rtp_header); |
| 380 } | 379 } |
| 381 | 380 |
| 382 rtp_header->type.Audio.channel = audio_specific.channels; | 381 rtp_header->type.Audio.channel = audio_specific.channels; |
| 383 return data_callback_->OnReceivedPayloadData( | 382 return data_callback_->OnReceivedPayloadData( |
| 384 payload_data, payload_length, rtp_header); | 383 payload_data, payload_length, rtp_header); |
| 385 } | 384 } |
| 386 } // namespace webrtc | 385 } // namespace webrtc |
| OLD | NEW |