OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 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 |
(...skipping 14 matching lines...) Expand all Loading... |
25 #include "webrtc/modules/audio_coding/acm2/acm_resampler.h" | 25 #include "webrtc/modules/audio_coding/acm2/acm_resampler.h" |
26 #include "webrtc/modules/audio_coding/acm2/call_statistics.h" | 26 #include "webrtc/modules/audio_coding/acm2/call_statistics.h" |
27 #include "webrtc/modules/audio_coding/neteq/include/neteq.h" | 27 #include "webrtc/modules/audio_coding/neteq/include/neteq.h" |
28 #include "webrtc/system_wrappers/include/clock.h" | 28 #include "webrtc/system_wrappers/include/clock.h" |
29 #include "webrtc/system_wrappers/include/trace.h" | 29 #include "webrtc/system_wrappers/include/trace.h" |
30 | 30 |
31 namespace webrtc { | 31 namespace webrtc { |
32 | 32 |
33 namespace acm2 { | 33 namespace acm2 { |
34 | 34 |
| 35 namespace { |
| 36 |
| 37 // Is the given codec a CNG codec? |
| 38 // TODO(kwiberg): Move to RentACodec. |
| 39 bool IsCng(int codec_id) { |
| 40 auto i = RentACodec::CodecIdFromIndex(codec_id); |
| 41 return (i && (*i == RentACodec::CodecId::kCNNB || |
| 42 *i == RentACodec::CodecId::kCNWB || |
| 43 *i == RentACodec::CodecId::kCNSWB || |
| 44 *i == RentACodec::CodecId::kCNFB)); |
| 45 } |
| 46 |
| 47 } // namespace |
| 48 |
35 AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config) | 49 AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config) |
36 : last_audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]), | 50 : last_audio_decoder_(nullptr), |
| 51 last_audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]), |
37 neteq_(NetEq::Create(config.neteq_config, config.decoder_factory)), | 52 neteq_(NetEq::Create(config.neteq_config, config.decoder_factory)), |
38 clock_(config.clock), | 53 clock_(config.clock), |
39 resampled_last_output_frame_(true) { | 54 resampled_last_output_frame_(true) { |
40 assert(clock_); | 55 assert(clock_); |
41 memset(last_audio_buffer_.get(), 0, AudioFrame::kMaxDataSizeSamples); | 56 memset(last_audio_buffer_.get(), 0, AudioFrame::kMaxDataSizeSamples); |
42 } | 57 } |
43 | 58 |
44 AcmReceiver::~AcmReceiver() { | 59 AcmReceiver::~AcmReceiver() { |
45 delete neteq_; | 60 delete neteq_; |
46 } | 61 } |
(...skipping 26 matching lines...) Expand all Loading... |
73 } | 88 } |
74 | 89 |
75 int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header, | 90 int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header, |
76 rtc::ArrayView<const uint8_t> incoming_payload) { | 91 rtc::ArrayView<const uint8_t> incoming_payload) { |
77 uint32_t receive_timestamp = 0; | 92 uint32_t receive_timestamp = 0; |
78 const RTPHeader* header = &rtp_header.header; // Just a shorthand. | 93 const RTPHeader* header = &rtp_header.header; // Just a shorthand. |
79 | 94 |
80 { | 95 { |
81 rtc::CritScope lock(&crit_sect_); | 96 rtc::CritScope lock(&crit_sect_); |
82 | 97 |
83 const rtc::Optional<CodecInst> ci = | 98 const Decoder* decoder = RtpHeaderToDecoder(*header, incoming_payload[0]); |
84 RtpHeaderToDecoder(*header, incoming_payload[0]); | 99 if (!decoder) { |
85 if (!ci) { | |
86 LOG_F(LS_ERROR) << "Payload-type " | 100 LOG_F(LS_ERROR) << "Payload-type " |
87 << static_cast<int>(header->payloadType) | 101 << static_cast<int>(header->payloadType) |
88 << " is not registered."; | 102 << " is not registered."; |
89 return -1; | 103 return -1; |
90 } | 104 } |
91 receive_timestamp = NowInTimestamp(ci->plfreq); | 105 const int sample_rate_hz = [&decoder] { |
| 106 const auto ci = RentACodec::CodecIdFromIndex(decoder->acm_codec_id); |
| 107 return ci ? RentACodec::CodecInstById(*ci)->plfreq : -1; |
| 108 }(); |
| 109 receive_timestamp = NowInTimestamp(sample_rate_hz); |
92 | 110 |
93 if (STR_CASE_CMP(ci->plname, "cn") == 0) { | 111 // If this is a CNG while the audio codec is not mono, skip pushing in |
94 if (last_audio_decoder_ && last_audio_decoder_->channels > 1) { | 112 // packets into NetEq. |
95 // This is a CNG and the audio codec is not mono, so skip pushing in | 113 if (IsCng(decoder->acm_codec_id) && last_audio_decoder_ && |
96 // packets into NetEq. | 114 last_audio_decoder_->channels > 1) |
97 return 0; | 115 return 0; |
98 } | 116 if (!IsCng(decoder->acm_codec_id) && |
99 } else { | 117 decoder->acm_codec_id != |
100 last_audio_decoder_ = ci; | 118 *RentACodec::CodecIndexFromId(RentACodec::CodecId::kAVT)) { |
101 last_packet_sample_rate_hz_ = rtc::Optional<int>(ci->plfreq); | 119 last_audio_decoder_ = decoder; |
| 120 last_packet_sample_rate_hz_ = rtc::Optional<int>(decoder->sample_rate_hz); |
102 } | 121 } |
103 | 122 |
104 } // |crit_sect_| is released. | 123 } // |crit_sect_| is released. |
105 | 124 |
106 if (neteq_->InsertPacket(rtp_header, incoming_payload, receive_timestamp) < | 125 if (neteq_->InsertPacket(rtp_header, incoming_payload, receive_timestamp) < |
107 0) { | 126 0) { |
108 LOG(LERROR) << "AcmReceiver::InsertPacket " | 127 LOG(LERROR) << "AcmReceiver::InsertPacket " |
109 << static_cast<int>(header->payloadType) | 128 << static_cast<int>(header->payloadType) |
110 << " Failed to insert packet"; | 129 << " Failed to insert packet"; |
111 return -1; | 130 return -1; |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 if (neteq_->RemovePayloadType(cur->second.payload_type) == 0) { | 275 if (neteq_->RemovePayloadType(cur->second.payload_type) == 0) { |
257 decoders_.erase(cur); | 276 decoders_.erase(cur); |
258 } else { | 277 } else { |
259 LOG_F(LS_ERROR) << "Cannot remove payload " | 278 LOG_F(LS_ERROR) << "Cannot remove payload " |
260 << static_cast<int>(cur->second.payload_type); | 279 << static_cast<int>(cur->second.payload_type); |
261 ret_val = -1; | 280 ret_val = -1; |
262 } | 281 } |
263 } | 282 } |
264 | 283 |
265 // No codec is registered, invalidate last audio decoder. | 284 // No codec is registered, invalidate last audio decoder. |
266 last_audio_decoder_ = rtc::Optional<CodecInst>(); | 285 last_audio_decoder_ = nullptr; |
267 last_packet_sample_rate_hz_ = rtc::Optional<int>(); | 286 last_packet_sample_rate_hz_ = rtc::Optional<int>(); |
268 return ret_val; | 287 return ret_val; |
269 } | 288 } |
270 | 289 |
271 int AcmReceiver::RemoveCodec(uint8_t payload_type) { | 290 int AcmReceiver::RemoveCodec(uint8_t payload_type) { |
272 rtc::CritScope lock(&crit_sect_); | 291 rtc::CritScope lock(&crit_sect_); |
273 auto it = decoders_.find(payload_type); | 292 auto it = decoders_.find(payload_type); |
274 if (it == decoders_.end()) { // Such a payload-type is not registered. | 293 if (it == decoders_.end()) { // Such a payload-type is not registered. |
275 return 0; | 294 return 0; |
276 } | 295 } |
277 if (neteq_->RemovePayloadType(payload_type) != NetEq::kOK) { | 296 if (neteq_->RemovePayloadType(payload_type) != NetEq::kOK) { |
278 LOG(LERROR) << "AcmReceiver::RemoveCodec" << static_cast<int>(payload_type); | 297 LOG(LERROR) << "AcmReceiver::RemoveCodec" << static_cast<int>(payload_type); |
279 return -1; | 298 return -1; |
280 } | 299 } |
281 if (last_audio_decoder_ && payload_type == last_audio_decoder_->pltype) { | 300 if (last_audio_decoder_ == &it->second) { |
282 last_audio_decoder_ = rtc::Optional<CodecInst>(); | 301 last_audio_decoder_ = nullptr; |
283 last_packet_sample_rate_hz_ = rtc::Optional<int>(); | 302 last_packet_sample_rate_hz_ = rtc::Optional<int>(); |
284 } | 303 } |
285 decoders_.erase(it); | 304 decoders_.erase(it); |
286 return 0; | 305 return 0; |
287 } | 306 } |
288 | 307 |
289 rtc::Optional<uint32_t> AcmReceiver::GetPlayoutTimestamp() { | 308 rtc::Optional<uint32_t> AcmReceiver::GetPlayoutTimestamp() { |
290 return neteq_->GetPlayoutTimestamp(); | 309 return neteq_->GetPlayoutTimestamp(); |
291 } | 310 } |
292 | 311 |
293 int AcmReceiver::FilteredCurrentDelayMs() const { | 312 int AcmReceiver::FilteredCurrentDelayMs() const { |
294 return neteq_->FilteredCurrentDelayMs(); | 313 return neteq_->FilteredCurrentDelayMs(); |
295 } | 314 } |
296 | 315 |
297 int AcmReceiver::LastAudioCodec(CodecInst* codec) const { | 316 int AcmReceiver::LastAudioCodec(CodecInst* codec) const { |
298 rtc::CritScope lock(&crit_sect_); | 317 rtc::CritScope lock(&crit_sect_); |
299 if (!last_audio_decoder_) { | 318 if (!last_audio_decoder_) { |
300 return -1; | 319 return -1; |
301 } | 320 } |
302 *codec = *last_audio_decoder_; | 321 *codec = *RentACodec::CodecInstById( |
| 322 *RentACodec::CodecIdFromIndex(last_audio_decoder_->acm_codec_id)); |
| 323 codec->pltype = last_audio_decoder_->payload_type; |
| 324 codec->channels = last_audio_decoder_->channels; |
| 325 codec->plfreq = last_audio_decoder_->sample_rate_hz; |
303 return 0; | 326 return 0; |
304 } | 327 } |
305 | 328 |
306 void AcmReceiver::GetNetworkStatistics(NetworkStatistics* acm_stat) { | 329 void AcmReceiver::GetNetworkStatistics(NetworkStatistics* acm_stat) { |
307 NetEqNetworkStatistics neteq_stat; | 330 NetEqNetworkStatistics neteq_stat; |
308 // NetEq function always returns zero, so we don't check the return value. | 331 // NetEq function always returns zero, so we don't check the return value. |
309 neteq_->NetworkStatistics(&neteq_stat); | 332 neteq_->NetworkStatistics(&neteq_stat); |
310 | 333 |
311 acm_stat->currentBufferSize = neteq_stat.current_buffer_size_ms; | 334 acm_stat->currentBufferSize = neteq_stat.current_buffer_size_ms; |
312 acm_stat->preferredBufferSize = neteq_stat.preferred_buffer_size_ms; | 335 acm_stat->preferredBufferSize = neteq_stat.preferred_buffer_size_ms; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 std::vector<uint16_t> AcmReceiver::GetNackList( | 379 std::vector<uint16_t> AcmReceiver::GetNackList( |
357 int64_t round_trip_time_ms) const { | 380 int64_t round_trip_time_ms) const { |
358 return neteq_->GetNackList(round_trip_time_ms); | 381 return neteq_->GetNackList(round_trip_time_ms); |
359 } | 382 } |
360 | 383 |
361 void AcmReceiver::ResetInitialDelay() { | 384 void AcmReceiver::ResetInitialDelay() { |
362 neteq_->SetMinimumDelay(0); | 385 neteq_->SetMinimumDelay(0); |
363 // TODO(turajs): Should NetEq Buffer be flushed? | 386 // TODO(turajs): Should NetEq Buffer be flushed? |
364 } | 387 } |
365 | 388 |
366 const rtc::Optional<CodecInst> AcmReceiver::RtpHeaderToDecoder( | 389 const AcmReceiver::Decoder* AcmReceiver::RtpHeaderToDecoder( |
367 const RTPHeader& rtp_header, | 390 const RTPHeader& rtp_header, |
368 uint8_t payload_type) const { | 391 uint8_t payload_type) const { |
369 const rtc::Optional<CodecInst> ci = | 392 auto it = decoders_.find(rtp_header.payloadType); |
370 neteq_->GetDecoder(rtp_header.payloadType); | 393 const auto red_index = |
371 if (ci && STR_CASE_CMP(ci->plname, "red") == 0) { | 394 RentACodec::CodecIndexFromId(RentACodec::CodecId::kRED); |
372 // This is a RED packet. Get the payload of the audio codec. | 395 if (red_index && // This ensures that RED is defined in WebRTC. |
373 return neteq_->GetDecoder(payload_type & 0x7f); | 396 it != decoders_.end() && it->second.acm_codec_id == *red_index) { |
374 } else { | 397 // This is a RED packet, get the payload of the audio codec. |
375 return ci; | 398 it = decoders_.find(payload_type & 0x7F); |
376 } | 399 } |
| 400 |
| 401 // Check if the payload is registered. |
| 402 return it != decoders_.end() ? &it->second : nullptr; |
377 } | 403 } |
378 | 404 |
379 uint32_t AcmReceiver::NowInTimestamp(int decoder_sampling_rate) const { | 405 uint32_t AcmReceiver::NowInTimestamp(int decoder_sampling_rate) const { |
380 // Down-cast the time to (32-6)-bit since we only care about | 406 // Down-cast the time to (32-6)-bit since we only care about |
381 // the least significant bits. (32-6) bits cover 2^(32-6) = 67108864 ms. | 407 // the least significant bits. (32-6) bits cover 2^(32-6) = 67108864 ms. |
382 // We masked 6 most significant bits of 32-bit so there is no overflow in | 408 // We masked 6 most significant bits of 32-bit so there is no overflow in |
383 // the conversion from milliseconds to timestamp. | 409 // the conversion from milliseconds to timestamp. |
384 const uint32_t now_in_ms = static_cast<uint32_t>( | 410 const uint32_t now_in_ms = static_cast<uint32_t>( |
385 clock_->TimeInMilliseconds() & 0x03ffffff); | 411 clock_->TimeInMilliseconds() & 0x03ffffff); |
386 return static_cast<uint32_t>( | 412 return static_cast<uint32_t>( |
387 (decoder_sampling_rate / 1000) * now_in_ms); | 413 (decoder_sampling_rate / 1000) * now_in_ms); |
388 } | 414 } |
389 | 415 |
390 void AcmReceiver::GetDecodingCallStatistics( | 416 void AcmReceiver::GetDecodingCallStatistics( |
391 AudioDecodingCallStats* stats) const { | 417 AudioDecodingCallStats* stats) const { |
392 rtc::CritScope lock(&crit_sect_); | 418 rtc::CritScope lock(&crit_sect_); |
393 *stats = call_stats_.GetDecodingStatistics(); | 419 *stats = call_stats_.GetDecodingStatistics(); |
394 } | 420 } |
395 | 421 |
396 } // namespace acm2 | 422 } // namespace acm2 |
397 | 423 |
398 } // namespace webrtc | 424 } // namespace webrtc |
OLD | NEW |