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

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2012 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/voice_engine/voe_external_media_impl.h"
      12             : 
      13             : #include "webrtc/audio/utility/audio_frame_operations.h"
      14             : #include "webrtc/system_wrappers/include/trace.h"
      15             : #include "webrtc/voice_engine/channel.h"
      16             : #include "webrtc/voice_engine/include/voe_errors.h"
      17             : #include "webrtc/voice_engine/output_mixer.h"
      18             : #include "webrtc/voice_engine/transmit_mixer.h"
      19             : #include "webrtc/voice_engine/voice_engine_impl.h"
      20             : 
      21             : namespace webrtc {
      22             : 
      23           0 : VoEExternalMedia* VoEExternalMedia::GetInterface(VoiceEngine* voiceEngine) {
      24           0 :   if (NULL == voiceEngine) {
      25           0 :     return NULL;
      26             :   }
      27           0 :   VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
      28           0 :   s->AddRef();
      29           0 :   return s;
      30             : }
      31             : 
      32           0 : VoEExternalMediaImpl::VoEExternalMediaImpl(voe::SharedData* shared)
      33             :     :
      34             : #ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT
      35             :       playout_delay_ms_(0),
      36             : #endif
      37           0 :       shared_(shared) {
      38             :   WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(shared_->instance_id(), -1),
      39             :                "VoEExternalMediaImpl() - ctor");
      40           0 : }
      41             : 
      42           0 : VoEExternalMediaImpl::~VoEExternalMediaImpl() {
      43             :   WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(shared_->instance_id(), -1),
      44             :                "~VoEExternalMediaImpl() - dtor");
      45           0 : }
      46             : 
      47           0 : int VoEExternalMediaImpl::RegisterExternalMediaProcessing(
      48             :     int channel,
      49             :     ProcessingTypes type,
      50             :     VoEMediaProcess& processObject) {
      51             :   WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(shared_->instance_id(), -1),
      52             :                "RegisterExternalMediaProcessing(channel=%d, type=%d, "
      53             :                "processObject=0x%x)",
      54             :                channel, type, &processObject);
      55           0 :   if (!shared_->statistics().Initialized()) {
      56           0 :     shared_->SetLastError(VE_NOT_INITED, kTraceError);
      57           0 :     return -1;
      58             :   }
      59           0 :   switch (type) {
      60             :     case kPlaybackPerChannel:
      61             :     case kRecordingPerChannel: {
      62           0 :       voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
      63           0 :       voe::Channel* channelPtr = ch.channel();
      64           0 :       if (channelPtr == NULL) {
      65           0 :         shared_->SetLastError(
      66             :             VE_CHANNEL_NOT_VALID, kTraceError,
      67             :             "RegisterExternalMediaProcessing() failed to locate "
      68           0 :             "channel");
      69           0 :         return -1;
      70             :       }
      71           0 :       return channelPtr->RegisterExternalMediaProcessing(type, processObject);
      72             :     }
      73             :     case kPlaybackAllChannelsMixed: {
      74           0 :       return shared_->output_mixer()->RegisterExternalMediaProcessing(
      75           0 :           processObject);
      76             :     }
      77             :     case kRecordingAllChannelsMixed:
      78             :     case kRecordingPreprocessing: {
      79           0 :       return shared_->transmit_mixer()->RegisterExternalMediaProcessing(
      80           0 :           &processObject, type);
      81             :     }
      82             :   }
      83           0 :   return -1;
      84             : }
      85             : 
      86           0 : int VoEExternalMediaImpl::DeRegisterExternalMediaProcessing(
      87             :     int channel,
      88             :     ProcessingTypes type) {
      89             :   WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(shared_->instance_id(), -1),
      90             :                "DeRegisterExternalMediaProcessing(channel=%d)", channel);
      91           0 :   if (!shared_->statistics().Initialized()) {
      92           0 :     shared_->SetLastError(VE_NOT_INITED, kTraceError);
      93           0 :     return -1;
      94             :   }
      95           0 :   switch (type) {
      96             :     case kPlaybackPerChannel:
      97             :     case kRecordingPerChannel: {
      98           0 :       voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
      99           0 :       voe::Channel* channelPtr = ch.channel();
     100           0 :       if (channelPtr == NULL) {
     101           0 :         shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
     102             :                               "RegisterExternalMediaProcessing() "
     103           0 :                               "failed to locate channel");
     104           0 :         return -1;
     105             :       }
     106           0 :       return channelPtr->DeRegisterExternalMediaProcessing(type);
     107             :     }
     108             :     case kPlaybackAllChannelsMixed: {
     109           0 :       return shared_->output_mixer()->DeRegisterExternalMediaProcessing();
     110             :     }
     111             :     case kRecordingAllChannelsMixed:
     112             :     case kRecordingPreprocessing: {
     113           0 :       return shared_->transmit_mixer()->DeRegisterExternalMediaProcessing(type);
     114             :     }
     115             :   }
     116           0 :   return -1;
     117             : }
     118             : 
     119           0 : int VoEExternalMediaImpl::SetExternalRecordingStatus(bool enable)
     120             : {
     121             :     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(shared_->instance_id(), -1),
     122             :                  "SetExternalRecordingStatus(enable=%d)", enable);
     123             : #ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT
     124           0 :     if (shared_->audio_device() && shared_->audio_device()->Recording())
     125             :     {
     126           0 :         shared_->SetLastError(VE_ALREADY_SENDING, kTraceError,
     127           0 :             "SetExternalRecordingStatus() cannot set state while sending");
     128           0 :         return -1;
     129             :     }
     130           0 :     shared_->set_ext_recording(enable);
     131           0 :     return 0;
     132             : #else
     133             :     shared_->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
     134             :         "SetExternalRecordingStatus() external recording is not supported");
     135             :     return -1;
     136             : #endif
     137             : }
     138             : 
     139           0 : int VoEExternalMediaImpl::ExternalRecordingInsertData(
     140             :         const int16_t speechData10ms[],
     141             :         int lengthSamples,
     142             :         int samplingFreqHz,
     143             :         int current_delay_ms)
     144             : {
     145             :     WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(shared_->instance_id(), -1),
     146             :                  "ExternalRecordingInsertData(speechData10ms=0x%x,"
     147             :                  " lengthSamples=%u, samplingFreqHz=%d, current_delay_ms=%d)",
     148             :                  &speechData10ms[0], lengthSamples, samplingFreqHz,
     149             :               current_delay_ms);
     150             : #ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT
     151           0 :     if (!shared_->statistics().Initialized())
     152             :     {
     153           0 :         shared_->SetLastError(VE_NOT_INITED, kTraceError);
     154           0 :         return -1;
     155             :     }
     156           0 :     if (!shared_->ext_recording())
     157             :     {
     158           0 :        shared_->SetLastError(VE_INVALID_OPERATION, kTraceError,
     159           0 :            "ExternalRecordingInsertData() external recording is not enabled");
     160           0 :         return -1;
     161             :     }
     162           0 :     if (shared_->NumOfSendingChannels() == 0)
     163             :     {
     164           0 :         shared_->SetLastError(VE_ALREADY_SENDING, kTraceError,
     165           0 :             "SetExternalRecordingStatus() no channel is sending");
     166           0 :         return -1;
     167             :     }
     168           0 :     if ((16000 != samplingFreqHz) && (32000 != samplingFreqHz) &&
     169           0 :         (48000 != samplingFreqHz) && (44100 != samplingFreqHz))
     170             :     {
     171           0 :          shared_->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
     172           0 :              "SetExternalRecordingStatus() invalid sample rate");
     173           0 :         return -1;
     174             :     }
     175           0 :     if ((0 == lengthSamples) ||
     176           0 :         ((lengthSamples % (samplingFreqHz / 100)) != 0))
     177             :     {
     178           0 :          shared_->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
     179           0 :              "SetExternalRecordingStatus() invalid buffer size");
     180           0 :         return -1;
     181             :     }
     182           0 :     if (current_delay_ms < 0)
     183             :     {
     184           0 :         shared_->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
     185           0 :             "SetExternalRecordingStatus() invalid delay)");
     186           0 :         return -1;
     187             :     }
     188             : 
     189           0 :     uint16_t blockSize = samplingFreqHz / 100;
     190             :     // We know the number of samples for 10ms of audio, so we can derive the
     191             :     // number of channels here:
     192           0 :     uint32_t channels = lengthSamples * 100 / samplingFreqHz;
     193           0 :     uint32_t nBlocks = lengthSamples / blockSize / channels;
     194           0 :     int16_t totalDelayMS = 0;
     195           0 :     uint16_t playoutDelayMS = 0;
     196             : 
     197           0 :     for (uint32_t i = 0; i < nBlocks; i++)
     198             :     {
     199           0 :         if (!shared_->ext_playout())
     200             :         {
     201             :             // Use real playout delay if external playout is not enabled.
     202           0 :             if (shared_->audio_device()->PlayoutDelay(&playoutDelayMS) != 0) {
     203           0 :               shared_->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceWarning,
     204           0 :                   "PlayoutDelay() unable to get the playout delay");
     205             :             }
     206           0 :             totalDelayMS = current_delay_ms + playoutDelayMS;
     207             :         }
     208             :         else
     209             :         {
     210             :             // Use stored delay value given the last call
     211             :             // to ExternalPlayoutGetData.
     212           0 :             totalDelayMS = current_delay_ms + playout_delay_ms_;
     213             :             // Compensate for block sizes larger than 10ms
     214           0 :             totalDelayMS -= (int16_t)(i*10);
     215           0 :             if (totalDelayMS < 0)
     216           0 :                 totalDelayMS = 0;
     217             :         }
     218           0 :         shared_->transmit_mixer()->PrepareDemux(
     219           0 :             (const int8_t*)(&speechData10ms[i*blockSize]),
     220             :             blockSize,
     221             :             channels,
     222             :             samplingFreqHz,
     223             :             totalDelayMS,
     224             :             0,
     225             :             0,
     226           0 :             false); // Typing detection not supported
     227             : 
     228           0 :         shared_->transmit_mixer()->DemuxAndMix();
     229           0 :         shared_->transmit_mixer()->EncodeAndSend();
     230             :     }
     231           0 :     return 0;
     232             : #else
     233             :        shared_->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
     234             :         "ExternalRecordingInsertData() external recording is not supported");
     235             :     return -1;
     236             : #endif
     237             : }
     238             : 
     239           0 : int VoEExternalMediaImpl::SetExternalPlayoutStatus(bool enable)
     240             : {
     241             :     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(shared_->instance_id(), -1),
     242             :                  "SetExternalPlayoutStatus(enable=%d)", enable);
     243             : #ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT
     244           0 :     if (shared_->audio_device() && shared_->audio_device()->Playing())
     245             :     {
     246           0 :         shared_->SetLastError(VE_ALREADY_SENDING, kTraceError,
     247           0 :             "SetExternalPlayoutStatus() cannot set state while playing");
     248           0 :         return -1;
     249             :     }
     250           0 :     shared_->set_ext_playout(enable);
     251           0 :     return 0;
     252             : #else
     253             :     shared_->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
     254             :         "SetExternalPlayoutStatus() external playout is not supported");
     255             :     return -1;
     256             : #endif
     257             : }
     258             : 
     259             : // This inserts a copy of the raw audio sent to the output drivers to use
     260             : // as the "far end" signal for the AEC.  Currently only 10ms chunks are
     261             : // supported unfortunately.  Since we have to rechunk to 10ms to call this,
     262             : // thre isn't much gained by allowing N*10ms here; external code can loop
     263             : // if needed.
     264           0 : int VoEExternalMediaImpl::ExternalPlayoutData(
     265             :     int16_t speechData10ms[],
     266             :     int samplingFreqHz,
     267             :     int num_channels,
     268             :     int current_delay_ms,
     269             :     int& lengthSamples)
     270             : {
     271             :     WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(shared_->instance_id(), -1),
     272             :                  "ExternalPlayoutData(speechData10ms=0x%x,"
     273             :                  " lengthSamples=%u, samplingFreqHz=%d, current_delay_ms=%d)",
     274             :                  &speechData10ms[0], lengthSamples, samplingFreqHz,
     275             :                  current_delay_ms);
     276             : 
     277             : #ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT
     278           0 :     if (!shared_->statistics().Initialized())
     279             :     {
     280           0 :         shared_->SetLastError(VE_NOT_INITED, kTraceError);
     281           0 :         return -1;
     282             :     }
     283             :     // FIX(jesup) - check if this is enabled?
     284           0 :     if (shared_->NumOfSendingChannels() == 0)
     285             :     {
     286           0 :         shared_->SetLastError(VE_ALREADY_SENDING, kTraceError,
     287           0 :             "SetExternalRecordingStatus() no channel is sending");
     288           0 :         return -1;
     289             :     }
     290           0 :     if ((16000 != samplingFreqHz) && (32000 != samplingFreqHz) &&
     291           0 :         (48000 != samplingFreqHz) && (44100 != samplingFreqHz))
     292             :     {
     293           0 :          shared_->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
     294           0 :              "SetExternalRecordingStatus() invalid sample rate");
     295           0 :         return -1;
     296             :     }
     297           0 :     if (current_delay_ms < 0)
     298             :     {
     299           0 :         shared_->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
     300           0 :             "SetExternalRecordingStatus() invalid delay)");
     301           0 :         return -1;
     302             :     }
     303             : 
     304             :     // Far-end data is inserted without going through neteq/etc.
     305             :     // Only supports 10ms chunks; AnalyzeReverseStream() enforces that
     306             :     // lower down.
     307           0 :     AudioFrame audioFrame;
     308           0 :     audioFrame.UpdateFrame(-1, 0xFFFFFFFF,
     309             :                            speechData10ms,
     310           0 :                            lengthSamples,
     311             :                            samplingFreqHz,
     312             :                            AudioFrame::kNormalSpeech,
     313             :                            AudioFrame::kVadUnknown,
     314           0 :                            num_channels);
     315             : 
     316           0 :     shared_->output_mixer()->APMAnalyzeReverseStream(audioFrame);
     317             : #endif
     318           0 :     return 0;
     319             : }
     320             : 
     321           0 : int VoEExternalMediaImpl::ExternalPlayoutGetData(
     322             :     int16_t speechData10ms[],
     323             :     int samplingFreqHz,
     324             :     int current_delay_ms,
     325             :     int& lengthSamples)
     326             : {
     327             :     WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(shared_->instance_id(), -1),
     328             :                  "ExternalPlayoutGetData(speechData10ms=0x%x, samplingFreqHz=%d"
     329             :                  ",  current_delay_ms=%d)", &speechData10ms[0], samplingFreqHz,
     330             :                  current_delay_ms);
     331             : #ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT
     332           0 :     if (!shared_->statistics().Initialized())
     333             :     {
     334           0 :         shared_->SetLastError(VE_NOT_INITED, kTraceError);
     335           0 :         return -1;
     336             :     }
     337           0 :     if (!shared_->ext_playout())
     338             :     {
     339           0 :        shared_->SetLastError(VE_INVALID_OPERATION, kTraceError,
     340           0 :            "ExternalPlayoutGetData() external playout is not enabled");
     341           0 :         return -1;
     342             :     }
     343           0 :     if ((16000 != samplingFreqHz) && (32000 != samplingFreqHz) &&
     344           0 :         (48000 != samplingFreqHz) && (44100 != samplingFreqHz))
     345             :     {
     346           0 :         shared_->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
     347           0 :             "ExternalPlayoutGetData() invalid sample rate");
     348           0 :         return -1;
     349             :     }
     350           0 :     if (current_delay_ms < 0)
     351             :     {
     352           0 :         shared_->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
     353           0 :             "ExternalPlayoutGetData() invalid delay)");
     354           0 :         return -1;
     355             :     }
     356             : 
     357           0 :     AudioFrame audioFrame;
     358             : 
     359           0 :     uint32_t channels = shared_->output_mixer()->GetOutputChannelCount();
     360             :     // If we have not received any data yet, consider it's mono since it's the
     361             :     // most common case.
     362           0 :     if (channels == 0) {
     363           0 :       channels = 1;
     364             :     }
     365             : 
     366             :     // Retrieve mixed output at the specified rate
     367           0 :     shared_->output_mixer()->MixActiveChannels();
     368           0 :     shared_->output_mixer()->DoOperationsOnCombinedSignal(true);
     369           0 :     shared_->output_mixer()->GetMixedAudio(samplingFreqHz, channels, &audioFrame);
     370             : 
     371             :     // Deliver audio (PCM) samples to the external sink
     372           0 :     memcpy(speechData10ms,
     373             :            audioFrame.data_,
     374           0 :            sizeof(int16_t)*audioFrame.samples_per_channel_*channels);
     375           0 :     lengthSamples = audioFrame.samples_per_channel_ * channels;
     376             : 
     377             :     // Store current playout delay (to be used by ExternalRecordingInsertData).
     378           0 :     playout_delay_ms_ = current_delay_ms;
     379             : 
     380           0 :     return 0;
     381             : #else
     382             :     shared_->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
     383             :        "ExternalPlayoutGetData() external playout is not supported");
     384             :     return -1;
     385             : #endif
     386             : }
     387             : 
     388           0 : int VoEExternalMediaImpl::GetAudioFrame(int channel, int desired_sample_rate_hz,
     389             :                                         AudioFrame* frame) {
     390           0 :   if (!shared_->statistics().Initialized()) {
     391           0 :     shared_->SetLastError(VE_NOT_INITED, kTraceError);
     392           0 :     return -1;
     393             :   }
     394           0 :   voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
     395           0 :   voe::Channel* channelPtr = ch.channel();
     396           0 :   if (channelPtr == NULL) {
     397           0 :     shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
     398           0 :                           "GetAudioFrame() failed to locate channel");
     399           0 :     return -1;
     400             :   }
     401           0 :   if (!channelPtr->ExternalMixing()) {
     402           0 :     shared_->SetLastError(VE_INVALID_OPERATION, kTraceError,
     403             :                           "GetAudioFrame() was called on channel that is not"
     404           0 :                           " externally mixed.");
     405           0 :     return -1;
     406             :   }
     407           0 :   if (!channelPtr->Playing()) {
     408           0 :     shared_->SetLastError(
     409             :         VE_INVALID_OPERATION, kTraceError,
     410           0 :         "GetAudioFrame() was called on channel that is not playing.");
     411           0 :     return -1;
     412             :   }
     413           0 :   if (desired_sample_rate_hz == -1) {
     414           0 :     shared_->SetLastError(VE_BAD_ARGUMENT, kTraceError,
     415           0 :                           "GetAudioFrame() was called with bad sample rate.");
     416           0 :     return -1;
     417             :   }
     418           0 :   frame->sample_rate_hz_ =
     419           0 :       desired_sample_rate_hz == 0 ? -1 : desired_sample_rate_hz;
     420           0 :   auto ret = channelPtr->GetAudioFrameWithMuted(channel, frame);
     421           0 :   if (ret == MixerParticipant::AudioFrameInfo::kMuted) {
     422           0 :     AudioFrameOperations::Mute(frame);
     423             :   }
     424           0 :   return ret == MixerParticipant::AudioFrameInfo::kError ? -1 : 0;
     425             : }
     426             : 
     427           0 : int VoEExternalMediaImpl::SetExternalMixing(int channel, bool enable) {
     428             :   WEBRTC_TRACE(kTraceApiCall, kTraceVoice,
     429             :                VoEId(shared_->instance_id(), channel),
     430             :                "SetExternalMixing(channel=%d, enable=%d)", channel, enable);
     431           0 :   if (!shared_->statistics().Initialized()) {
     432           0 :     shared_->SetLastError(VE_NOT_INITED, kTraceError);
     433           0 :     return -1;
     434             :   }
     435           0 :   voe::ChannelOwner ch = shared_->channel_manager().GetChannel(channel);
     436           0 :   voe::Channel* channelPtr = ch.channel();
     437           0 :   if (channelPtr == NULL) {
     438           0 :     shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
     439           0 :                           "SetExternalMixing() failed to locate channel");
     440           0 :     return -1;
     441             :   }
     442           0 :   return channelPtr->SetExternalMixing(enable);
     443             : }
     444             : 
     445             : }  // namespace webrtc

Generated by: LCOV version 1.13