LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/audio_coding/acm2 - acm_receiver.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 214 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 28 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2013 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/acm2/acm_receiver.h"
      12             : 
      13             : #include <stdlib.h>  // malloc
      14             : 
      15             : #include <algorithm>  // sort
      16             : #include <vector>
      17             : 
      18             : #include "webrtc/base/checks.h"
      19             : #include "webrtc/base/format_macros.h"
      20             : #include "webrtc/base/logging.h"
      21             : #include "webrtc/base/safe_conversions.h"
      22             : #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
      23             : #include "webrtc/common_types.h"
      24             : #include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
      25             : #include "webrtc/modules/audio_coding/acm2/acm_resampler.h"
      26             : #include "webrtc/modules/audio_coding/acm2/call_statistics.h"
      27             : #include "webrtc/modules/audio_coding/neteq/include/neteq.h"
      28             : #include "webrtc/system_wrappers/include/clock.h"
      29             : #include "webrtc/system_wrappers/include/trace.h"
      30             : 
      31             : namespace webrtc {
      32             : 
      33             : namespace acm2 {
      34             : 
      35           0 : AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config)
      36           0 :     : last_audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]),
      37           0 :       neteq_(NetEq::Create(config.neteq_config, config.decoder_factory)),
      38           0 :       clock_(config.clock),
      39           0 :       resampled_last_output_frame_(true) {
      40           0 :   assert(clock_);
      41           0 :   memset(last_audio_buffer_.get(), 0, AudioFrame::kMaxDataSizeSamples);
      42           0 : }
      43             : 
      44           0 : AcmReceiver::~AcmReceiver() {
      45           0 :   delete neteq_;
      46           0 : }
      47             : 
      48           0 : int AcmReceiver::SetMinimumDelay(int delay_ms) {
      49           0 :   if (neteq_->SetMinimumDelay(delay_ms))
      50           0 :     return 0;
      51           0 :   LOG(LERROR) << "AcmReceiver::SetExtraDelay " << delay_ms;
      52           0 :   return -1;
      53             : }
      54             : 
      55           0 : int AcmReceiver::SetMaximumDelay(int delay_ms) {
      56           0 :   if (neteq_->SetMaximumDelay(delay_ms))
      57           0 :     return 0;
      58           0 :   LOG(LERROR) << "AcmReceiver::SetExtraDelay " << delay_ms;
      59           0 :   return -1;
      60             : }
      61             : 
      62           0 : int AcmReceiver::LeastRequiredDelayMs() const {
      63           0 :   return neteq_->LeastRequiredDelayMs();
      64             : }
      65             : 
      66           0 : rtc::Optional<int> AcmReceiver::last_packet_sample_rate_hz() const {
      67           0 :   rtc::CritScope lock(&crit_sect_);
      68           0 :   return last_packet_sample_rate_hz_;
      69             : }
      70             : 
      71           0 : int AcmReceiver::last_output_sample_rate_hz() const {
      72           0 :   return neteq_->last_output_sample_rate_hz();
      73             : }
      74             : 
      75           0 : int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header,
      76             :                               rtc::ArrayView<const uint8_t> incoming_payload) {
      77           0 :   uint32_t receive_timestamp = 0;
      78           0 :   const RTPHeader* header = &rtp_header.header;  // Just a shorthand.
      79             : 
      80             :   {
      81           0 :     rtc::CritScope lock(&crit_sect_);
      82             : 
      83             :     const rtc::Optional<CodecInst> ci =
      84           0 :         RtpHeaderToDecoder(*header, incoming_payload[0]);
      85           0 :     if (!ci) {
      86           0 :       LOG_F(LS_ERROR) << "Payload-type "
      87           0 :                       << static_cast<int>(header->payloadType)
      88           0 :                       << " is not registered.";
      89           0 :       return -1;
      90             :     }
      91           0 :     receive_timestamp = NowInTimestamp(ci->plfreq);
      92             : 
      93           0 :     if (STR_CASE_CMP(ci->plname, "cn") == 0) {
      94           0 :       if (last_audio_decoder_ && last_audio_decoder_->channels > 1) {
      95             :         // This is a CNG and the audio codec is not mono, so skip pushing in
      96             :         // packets into NetEq.
      97           0 :         return 0;
      98             :       }
      99             :     } else {
     100           0 :       last_audio_decoder_ = ci;
     101           0 :       last_audio_format_ = neteq_->GetDecoderFormat(ci->pltype);
     102           0 :       RTC_DCHECK(last_audio_format_);
     103           0 :       last_packet_sample_rate_hz_ = rtc::Optional<int>(ci->plfreq);
     104             :     }
     105             :   }  // |crit_sect_| is released.
     106             : 
     107           0 :   if (neteq_->InsertPacket(rtp_header, incoming_payload, receive_timestamp) <
     108             :       0) {
     109           0 :     LOG(LERROR) << "AcmReceiver::InsertPacket "
     110           0 :                 << static_cast<int>(header->payloadType)
     111           0 :                 << " Failed to insert packet";
     112           0 :     return -1;
     113             :   }
     114           0 :   return 0;
     115             : }
     116             : 
     117           0 : int AcmReceiver::GetAudio(int desired_freq_hz,
     118             :                           AudioFrame* audio_frame,
     119             :                           bool* muted) {
     120           0 :   RTC_DCHECK(muted);
     121             :   // Accessing members, take the lock.
     122           0 :   rtc::CritScope lock(&crit_sect_);
     123             : 
     124           0 :   if (neteq_->GetAudio(audio_frame, muted) != NetEq::kOK) {
     125           0 :     LOG(LERROR) << "AcmReceiver::GetAudio - NetEq Failed.";
     126           0 :     return -1;
     127             :   }
     128             : 
     129           0 :   const int current_sample_rate_hz = neteq_->last_output_sample_rate_hz();
     130             : 
     131             :   // Update if resampling is required.
     132             :   const bool need_resampling =
     133           0 :       (desired_freq_hz != -1) && (current_sample_rate_hz != desired_freq_hz);
     134             : 
     135           0 :   if (need_resampling && !resampled_last_output_frame_) {
     136             :     // Prime the resampler with the last frame.
     137             :     int16_t temp_output[AudioFrame::kMaxDataSizeSamples];
     138           0 :     int samples_per_channel_int = resampler_.Resample10Msec(
     139           0 :         last_audio_buffer_.get(), current_sample_rate_hz, desired_freq_hz,
     140             :         audio_frame->num_channels_, AudioFrame::kMaxDataSizeSamples,
     141           0 :         temp_output);
     142           0 :     if (samples_per_channel_int < 0) {
     143           0 :       LOG(LERROR) << "AcmReceiver::GetAudio - "
     144           0 :                      "Resampling last_audio_buffer_ failed.";
     145           0 :       return -1;
     146             :     }
     147             :   }
     148             : 
     149             :   // TODO(henrik.lundin) Glitches in the output may appear if the output rate
     150             :   // from NetEq changes. See WebRTC issue 3923.
     151           0 :   if (need_resampling) {
     152           0 :     int samples_per_channel_int = resampler_.Resample10Msec(
     153             :         audio_frame->data_, current_sample_rate_hz, desired_freq_hz,
     154             :         audio_frame->num_channels_, AudioFrame::kMaxDataSizeSamples,
     155           0 :         audio_frame->data_);
     156           0 :     if (samples_per_channel_int < 0) {
     157           0 :       LOG(LERROR) << "AcmReceiver::GetAudio - Resampling audio_buffer_ failed.";
     158           0 :       return -1;
     159             :     }
     160           0 :     audio_frame->samples_per_channel_ =
     161           0 :         static_cast<size_t>(samples_per_channel_int);
     162           0 :     audio_frame->sample_rate_hz_ = desired_freq_hz;
     163           0 :     RTC_DCHECK_EQ(
     164             :         audio_frame->sample_rate_hz_,
     165           0 :         rtc::checked_cast<int>(audio_frame->samples_per_channel_ * 100));
     166           0 :     resampled_last_output_frame_ = true;
     167             :   } else {
     168           0 :     resampled_last_output_frame_ = false;
     169             :     // We might end up here ONLY if codec is changed.
     170             :   }
     171             : 
     172             :   // Store current audio in |last_audio_buffer_| for next time.
     173           0 :   memcpy(last_audio_buffer_.get(), audio_frame->data_,
     174           0 :          sizeof(int16_t) * audio_frame->samples_per_channel_ *
     175           0 :              audio_frame->num_channels_);
     176             : 
     177           0 :   call_stats_.DecodedByNetEq(audio_frame->speech_type_, *muted);
     178           0 :   return 0;
     179             : }
     180             : 
     181           0 : int32_t AcmReceiver::AddCodec(int acm_codec_id,
     182             :                               uint8_t payload_type,
     183             :                               size_t channels,
     184             :                               int /*sample_rate_hz*/,
     185             :                               AudioDecoder* audio_decoder,
     186             :                               const std::string& name) {
     187             :   // TODO(kwiberg): This function has been ignoring the |sample_rate_hz|
     188             :   // argument for a long time. Arguably, it should simply be removed.
     189             : 
     190           0 :   const auto neteq_decoder = [acm_codec_id, channels]() -> NetEqDecoder {
     191           0 :     if (acm_codec_id == -1)
     192           0 :       return NetEqDecoder::kDecoderArbitrary;  // External decoder.
     193             :     const rtc::Optional<RentACodec::CodecId> cid =
     194           0 :         RentACodec::CodecIdFromIndex(acm_codec_id);
     195           0 :     RTC_DCHECK(cid) << "Invalid codec index: " << acm_codec_id;
     196             :     const rtc::Optional<NetEqDecoder> ned =
     197           0 :         RentACodec::NetEqDecoderFromCodecId(*cid, channels);
     198           0 :     RTC_DCHECK(ned) << "Invalid codec ID: " << static_cast<int>(*cid);
     199           0 :     return *ned;
     200           0 :   }();
     201             :   const rtc::Optional<SdpAudioFormat> new_format =
     202           0 :       RentACodec::NetEqDecoderToSdpAudioFormat(neteq_decoder);
     203             : 
     204           0 :   rtc::CritScope lock(&crit_sect_);
     205             : 
     206           0 :   const auto old_format = neteq_->GetDecoderFormat(payload_type);
     207           0 :   if (old_format && new_format && *old_format == *new_format) {
     208             :     // Re-registering the same codec. Do nothing and return.
     209           0 :     return 0;
     210             :   }
     211             : 
     212           0 :   if (neteq_->RemovePayloadType(payload_type) != NetEq::kOK &&
     213           0 :       neteq_->LastError() != NetEq::kDecoderNotFound) {
     214           0 :     LOG(LERROR) << "Cannot remove payload " << static_cast<int>(payload_type);
     215           0 :     return -1;
     216             :   }
     217             : 
     218             :   int ret_val;
     219           0 :   if (!audio_decoder) {
     220           0 :     ret_val = neteq_->RegisterPayloadType(neteq_decoder, name, payload_type);
     221             :   } else {
     222           0 :     ret_val = neteq_->RegisterExternalDecoder(
     223           0 :         audio_decoder, neteq_decoder, name, payload_type);
     224             :   }
     225           0 :   if (ret_val != NetEq::kOK) {
     226           0 :     LOG(LERROR) << "AcmReceiver::AddCodec " << acm_codec_id
     227             :                 << static_cast<int>(payload_type)
     228           0 :                 << " channels: " << channels;
     229           0 :     return -1;
     230             :   }
     231           0 :   return 0;
     232             : }
     233             : 
     234           0 : bool AcmReceiver::AddCodec(int rtp_payload_type,
     235             :                            const SdpAudioFormat& audio_format) {
     236           0 :   const auto old_format = neteq_->GetDecoderFormat(rtp_payload_type);
     237           0 :   if (old_format && *old_format == audio_format) {
     238             :     // Re-registering the same codec. Do nothing and return.
     239           0 :     return true;
     240             :   }
     241             : 
     242           0 :   if (neteq_->RemovePayloadType(rtp_payload_type) != NetEq::kOK &&
     243           0 :       neteq_->LastError() != NetEq::kDecoderNotFound) {
     244           0 :     LOG(LERROR) << "AcmReceiver::AddCodec: Could not remove existing decoder"
     245           0 :                    " for payload type "
     246           0 :                 << rtp_payload_type;
     247           0 :     return false;
     248             :   }
     249             : 
     250             :   const bool success =
     251           0 :       neteq_->RegisterPayloadType(rtp_payload_type, audio_format);
     252           0 :   if (!success) {
     253           0 :     LOG(LERROR) << "AcmReceiver::AddCodec failed for payload type "
     254           0 :                 << rtp_payload_type << ", decoder format " << audio_format;
     255             :   }
     256           0 :   return success;
     257             : }
     258             : 
     259           0 : void AcmReceiver::FlushBuffers() {
     260           0 :   neteq_->FlushBuffers();
     261           0 : }
     262             : 
     263           0 : void AcmReceiver::RemoveAllCodecs() {
     264           0 :   rtc::CritScope lock(&crit_sect_);
     265           0 :   neteq_->RemoveAllPayloadTypes();
     266           0 :   last_audio_decoder_ = rtc::Optional<CodecInst>();
     267           0 :   last_audio_format_ = rtc::Optional<SdpAudioFormat>();
     268           0 :   last_packet_sample_rate_hz_ = rtc::Optional<int>();
     269           0 : }
     270             : 
     271           0 : int AcmReceiver::RemoveCodec(uint8_t payload_type) {
     272           0 :   rtc::CritScope lock(&crit_sect_);
     273           0 :   if (neteq_->RemovePayloadType(payload_type) != NetEq::kOK &&
     274           0 :       neteq_->LastError() != NetEq::kDecoderNotFound) {
     275           0 :     LOG(LERROR) << "AcmReceiver::RemoveCodec" << static_cast<int>(payload_type);
     276           0 :     return -1;
     277             :   }
     278           0 :   if (last_audio_decoder_ && payload_type == last_audio_decoder_->pltype) {
     279           0 :     last_audio_decoder_ = rtc::Optional<CodecInst>();
     280           0 :     last_audio_format_ = rtc::Optional<SdpAudioFormat>();
     281           0 :     last_packet_sample_rate_hz_ = rtc::Optional<int>();
     282             :   }
     283           0 :   return 0;
     284             : }
     285             : 
     286           0 : rtc::Optional<uint32_t> AcmReceiver::GetPlayoutTimestamp() {
     287           0 :   return neteq_->GetPlayoutTimestamp();
     288             : }
     289             : 
     290           0 : int AcmReceiver::FilteredCurrentDelayMs() const {
     291           0 :   return neteq_->FilteredCurrentDelayMs();
     292             : }
     293             : 
     294           0 : int AcmReceiver::LastAudioCodec(CodecInst* codec) const {
     295           0 :   rtc::CritScope lock(&crit_sect_);
     296           0 :   if (!last_audio_decoder_) {
     297           0 :     return -1;
     298             :   }
     299           0 :   *codec = *last_audio_decoder_;
     300           0 :   return 0;
     301             : }
     302             : 
     303           0 : rtc::Optional<SdpAudioFormat> AcmReceiver::LastAudioFormat() const {
     304           0 :   rtc::CritScope lock(&crit_sect_);
     305           0 :   return last_audio_format_;
     306             : }
     307             : 
     308           0 : void AcmReceiver::GetNetworkStatistics(NetworkStatistics* acm_stat) {
     309             :   NetEqNetworkStatistics neteq_stat;
     310             :   // NetEq function always returns zero, so we don't check the return value.
     311           0 :   neteq_->NetworkStatistics(&neteq_stat);
     312             : 
     313           0 :   acm_stat->currentBufferSize = neteq_stat.current_buffer_size_ms;
     314           0 :   acm_stat->preferredBufferSize = neteq_stat.preferred_buffer_size_ms;
     315           0 :   acm_stat->jitterPeaksFound = neteq_stat.jitter_peaks_found ? true : false;
     316           0 :   acm_stat->currentPacketLossRate = neteq_stat.packet_loss_rate;
     317           0 :   acm_stat->currentDiscardRate = neteq_stat.packet_discard_rate;
     318           0 :   acm_stat->currentExpandRate = neteq_stat.expand_rate;
     319           0 :   acm_stat->currentSpeechExpandRate = neteq_stat.speech_expand_rate;
     320           0 :   acm_stat->currentPreemptiveRate = neteq_stat.preemptive_rate;
     321           0 :   acm_stat->currentAccelerateRate = neteq_stat.accelerate_rate;
     322           0 :   acm_stat->currentSecondaryDecodedRate = neteq_stat.secondary_decoded_rate;
     323           0 :   acm_stat->clockDriftPPM = neteq_stat.clockdrift_ppm;
     324           0 :   acm_stat->addedSamples = neteq_stat.added_zero_samples;
     325           0 :   acm_stat->meanWaitingTimeMs = neteq_stat.mean_waiting_time_ms;
     326           0 :   acm_stat->medianWaitingTimeMs = neteq_stat.median_waiting_time_ms;
     327           0 :   acm_stat->minWaitingTimeMs = neteq_stat.min_waiting_time_ms;
     328           0 :   acm_stat->maxWaitingTimeMs = neteq_stat.max_waiting_time_ms;
     329           0 : }
     330             : 
     331           0 : int AcmReceiver::DecoderByPayloadType(uint8_t payload_type,
     332             :                                       CodecInst* codec) const {
     333           0 :   rtc::CritScope lock(&crit_sect_);
     334           0 :   const rtc::Optional<CodecInst> ci = neteq_->GetDecoder(payload_type);
     335           0 :   if (ci) {
     336           0 :     *codec = *ci;
     337           0 :     return 0;
     338             :   } else {
     339           0 :     LOG(LERROR) << "AcmReceiver::DecoderByPayloadType "
     340           0 :                 << static_cast<int>(payload_type);
     341           0 :     return -1;
     342             :   }
     343             : }
     344             : 
     345           0 : int AcmReceiver::EnableNack(size_t max_nack_list_size) {
     346           0 :   neteq_->EnableNack(max_nack_list_size);
     347           0 :   return 0;
     348             : }
     349             : 
     350           0 : void AcmReceiver::DisableNack() {
     351           0 :   neteq_->DisableNack();
     352           0 : }
     353             : 
     354           0 : std::vector<uint16_t> AcmReceiver::GetNackList(
     355             :     int64_t round_trip_time_ms) const {
     356           0 :   return neteq_->GetNackList(round_trip_time_ms);
     357             : }
     358             : 
     359           0 : void AcmReceiver::ResetInitialDelay() {
     360           0 :   neteq_->SetMinimumDelay(0);
     361             :   // TODO(turajs): Should NetEq Buffer be flushed?
     362           0 : }
     363             : 
     364           0 : const rtc::Optional<CodecInst> AcmReceiver::RtpHeaderToDecoder(
     365             :     const RTPHeader& rtp_header,
     366             :     uint8_t first_payload_byte) const {
     367             :   const rtc::Optional<CodecInst> ci =
     368           0 :       neteq_->GetDecoder(rtp_header.payloadType);
     369           0 :   if (ci && STR_CASE_CMP(ci->plname, "red") == 0) {
     370             :     // This is a RED packet. Get the payload of the audio codec.
     371           0 :     return neteq_->GetDecoder(first_payload_byte & 0x7f);
     372             :   } else {
     373           0 :     return ci;
     374             :   }
     375             : }
     376             : 
     377           0 : uint32_t AcmReceiver::NowInTimestamp(int decoder_sampling_rate) const {
     378             :   // Down-cast the time to (32-6)-bit since we only care about
     379             :   // the least significant bits. (32-6) bits cover 2^(32-6) = 67108864 ms.
     380             :   // We masked 6 most significant bits of 32-bit so there is no overflow in
     381             :   // the conversion from milliseconds to timestamp.
     382             :   const uint32_t now_in_ms = static_cast<uint32_t>(
     383           0 :       clock_->TimeInMilliseconds() & 0x03ffffff);
     384             :   return static_cast<uint32_t>(
     385           0 :       (decoder_sampling_rate / 1000) * now_in_ms);
     386             : }
     387             : 
     388           0 : void AcmReceiver::GetDecodingCallStatistics(
     389             :     AudioDecodingCallStats* stats) const {
     390           0 :   rtc::CritScope lock(&crit_sect_);
     391           0 :   *stats = call_stats_.GetDecodingStatistics();
     392           0 : }
     393             : 
     394             : }  // namespace acm2
     395             : 
     396             : }  // namespace webrtc

Generated by: LCOV version 1.13