Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: webrtc/modules/audio_coding/acm2/acm_receiver.cc

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

Powered by Google App Engine
This is Rietveld 408576698