Home | History | Annotate | Download | only in voice_engine
      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_file_impl.h"
     12 
     13 #include "webrtc/modules/media_file/interface/media_file.h"
     14 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
     15 #include "webrtc/system_wrappers/interface/file_wrapper.h"
     16 #include "webrtc/system_wrappers/interface/trace.h"
     17 #include "webrtc/voice_engine/channel.h"
     18 #include "webrtc/voice_engine/include/voe_errors.h"
     19 #include "webrtc/voice_engine/output_mixer.h"
     20 #include "webrtc/voice_engine/transmit_mixer.h"
     21 #include "webrtc/voice_engine/voice_engine_impl.h"
     22 
     23 namespace webrtc {
     24 
     25 VoEFile* VoEFile::GetInterface(VoiceEngine* voiceEngine)
     26 {
     27 #ifndef WEBRTC_VOICE_ENGINE_FILE_API
     28     return NULL;
     29 #else
     30     if (NULL == voiceEngine)
     31     {
     32         return NULL;
     33     }
     34     VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
     35     s->AddRef();
     36     return s;
     37 #endif
     38 }
     39 
     40 #ifdef WEBRTC_VOICE_ENGINE_FILE_API
     41 
     42 VoEFileImpl::VoEFileImpl(voe::SharedData* shared) : _shared(shared)
     43 {
     44     WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
     45                  "VoEFileImpl::VoEFileImpl() - ctor");
     46 }
     47 
     48 VoEFileImpl::~VoEFileImpl()
     49 {
     50     WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
     51                  "VoEFileImpl::~VoEFileImpl() - dtor");
     52 }
     53 
     54 int VoEFileImpl::StartPlayingFileLocally(
     55     int channel,
     56     const char fileNameUTF8[1024],
     57     bool loop, FileFormats format,
     58     float volumeScaling,
     59     int startPointMs,
     60     int stopPointMs)
     61 {
     62     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
     63                  "StartPlayingFileLocally(channel=%d, fileNameUTF8[]=%s, "
     64                  "loop=%d, format=%d, volumeScaling=%5.3f, startPointMs=%d,"
     65                  " stopPointMs=%d)",
     66                  channel, fileNameUTF8, loop, format, volumeScaling,
     67                  startPointMs, stopPointMs);
     68     assert(1024 == FileWrapper::kMaxFileNameSize);
     69     if (!_shared->statistics().Initialized())
     70     {
     71         _shared->SetLastError(VE_NOT_INITED, kTraceError);
     72         return -1;
     73     }
     74     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
     75     voe::Channel* channelPtr = ch.channel();
     76     if (channelPtr == NULL)
     77     {
     78         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
     79             "StartPlayingFileLocally() failed to locate channel");
     80         return -1;
     81     }
     82 
     83     return channelPtr->StartPlayingFileLocally(fileNameUTF8,
     84                                                loop,
     85                                                format,
     86                                                startPointMs,
     87                                                volumeScaling,
     88                                                stopPointMs,
     89                                                NULL);
     90 }
     91 
     92 int VoEFileImpl::StartPlayingFileLocally(int channel,
     93                                          InStream* stream,
     94                                          FileFormats format,
     95                                          float volumeScaling,
     96                                          int startPointMs,
     97                                          int stopPointMs)
     98 {
     99     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    100                  "StartPlayingFileLocally(channel=%d, stream, format=%d, "
    101                  "volumeScaling=%5.3f, startPointMs=%d, stopPointMs=%d)",
    102                  channel, format, volumeScaling, startPointMs, stopPointMs);
    103 
    104     if (!_shared->statistics().Initialized())
    105     {
    106         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    107         return -1;
    108     }
    109 
    110     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    111     voe::Channel* channelPtr = ch.channel();
    112     if (channelPtr == NULL)
    113     {
    114         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    115             "StartPlayingFileLocally() failed to locate channel");
    116         return -1;
    117     }
    118 
    119     return channelPtr->StartPlayingFileLocally(stream,
    120                                                format,
    121                                                startPointMs,
    122                                                volumeScaling,
    123                                                stopPointMs,
    124                                                NULL);
    125 }
    126 
    127 int VoEFileImpl::StopPlayingFileLocally(int channel)
    128 {
    129     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    130                  "StopPlayingFileLocally()");
    131     if (!_shared->statistics().Initialized())
    132     {
    133         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    134         return -1;
    135     }
    136     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    137     voe::Channel* channelPtr = ch.channel();
    138     if (channelPtr == NULL)
    139     {
    140         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    141             "StopPlayingFileLocally() failed to locate channel");
    142         return -1;
    143     }
    144     return channelPtr->StopPlayingFileLocally();
    145 }
    146 
    147 int VoEFileImpl::IsPlayingFileLocally(int channel)
    148 {
    149     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    150                  "IsPlayingFileLocally(channel=%d)", channel);
    151     if (!_shared->statistics().Initialized())
    152     {
    153         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    154         return -1;
    155     }
    156     voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    157     voe::Channel* channelPtr = ch.channel();
    158     if (channelPtr == NULL)
    159     {
    160         _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    161             "StopPlayingFileLocally() failed to locate channel");
    162         return -1;
    163     }
    164     return channelPtr->IsPlayingFileLocally();
    165 }
    166 
    167 int VoEFileImpl::StartPlayingFileAsMicrophone(int channel,
    168                                               const char fileNameUTF8[1024],
    169                                               bool loop,
    170                                               bool mixWithMicrophone,
    171                                               FileFormats format,
    172                                               float volumeScaling)
    173 {
    174     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    175                  "StartPlayingFileAsMicrophone(channel=%d, fileNameUTF8=%s, "
    176                  "loop=%d, mixWithMicrophone=%d, format=%d, "
    177                  "volumeScaling=%5.3f)",
    178                  channel, fileNameUTF8, loop, mixWithMicrophone, format,
    179                  volumeScaling);
    180     assert(1024 == FileWrapper::kMaxFileNameSize);
    181     if (!_shared->statistics().Initialized())
    182     {
    183         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    184         return -1;
    185     }
    186 
    187     const uint32_t startPointMs(0);
    188     const uint32_t stopPointMs(0);
    189 
    190     if (channel == -1)
    191     {
    192         int res = _shared->transmit_mixer()->StartPlayingFileAsMicrophone(
    193             fileNameUTF8,
    194             loop,
    195             format,
    196             startPointMs,
    197             volumeScaling,
    198             stopPointMs,
    199             NULL);
    200         if (res)
    201         {
    202             WEBRTC_TRACE(kTraceError, kTraceVoice,
    203                 VoEId(_shared->instance_id(), -1),
    204                 "StartPlayingFileAsMicrophone() failed to start playing file");
    205             return(-1);
    206         }
    207         else
    208         {
    209             _shared->transmit_mixer()->SetMixWithMicStatus(mixWithMicrophone);
    210             return(0);
    211         }
    212     }
    213     else
    214     {
    215         // Add file after demultiplexing <=> affects one channel only
    216         voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    217         voe::Channel* channelPtr = ch.channel();
    218         if (channelPtr == NULL)
    219         {
    220             _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    221                 "StartPlayingFileAsMicrophone() failed to locate channel");
    222             return -1;
    223         }
    224 
    225         int res = channelPtr->StartPlayingFileAsMicrophone(fileNameUTF8,
    226                                                            loop,
    227                                                            format,
    228                                                            startPointMs,
    229                                                            volumeScaling,
    230                                                            stopPointMs,
    231                                                            NULL);
    232         if (res)
    233         {
    234             WEBRTC_TRACE(kTraceError, kTraceVoice,
    235                 VoEId(_shared->instance_id(), -1),
    236                 "StartPlayingFileAsMicrophone() failed to start playing file");
    237             return -1;
    238         }
    239         else
    240         {
    241             channelPtr->SetMixWithMicStatus(mixWithMicrophone);
    242             return 0;
    243         }
    244     }
    245 }
    246 
    247 int VoEFileImpl::StartPlayingFileAsMicrophone(int channel,
    248                                               InStream* stream,
    249                                               bool mixWithMicrophone,
    250                                               FileFormats format,
    251                                               float volumeScaling)
    252 {
    253     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    254                  "StartPlayingFileAsMicrophone(channel=%d, stream,"
    255                  " mixWithMicrophone=%d, format=%d, volumeScaling=%5.3f)",
    256                  channel, mixWithMicrophone, format, volumeScaling);
    257 
    258     if (!_shared->statistics().Initialized())
    259     {
    260         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    261         return -1;
    262     }
    263 
    264     const uint32_t startPointMs(0);
    265     const uint32_t stopPointMs(0);
    266 
    267     if (channel == -1)
    268     {
    269         int res = _shared->transmit_mixer()->StartPlayingFileAsMicrophone(
    270             stream,
    271             format,
    272             startPointMs,
    273             volumeScaling,
    274             stopPointMs,
    275             NULL);
    276         if (res)
    277         {
    278             WEBRTC_TRACE(kTraceError, kTraceVoice,
    279                 VoEId(_shared->instance_id(), -1),
    280                 "StartPlayingFileAsMicrophone() failed to start "
    281                 "playing stream");
    282             return(-1);
    283         }
    284         else
    285         {
    286             _shared->transmit_mixer()->SetMixWithMicStatus(mixWithMicrophone);
    287             return(0);
    288         }
    289     }
    290     else
    291     {
    292         // Add file after demultiplexing <=> affects one channel only
    293         voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    294         voe::Channel* channelPtr = ch.channel();
    295         if (channelPtr == NULL)
    296         {
    297             _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    298                 "StartPlayingFileAsMicrophone() failed to locate channel");
    299             return -1;
    300         }
    301 
    302         int res = channelPtr->StartPlayingFileAsMicrophone(
    303             stream, format, startPointMs, volumeScaling, stopPointMs, NULL);
    304         if (res)
    305         {
    306             WEBRTC_TRACE(kTraceError, kTraceVoice,
    307                 VoEId(_shared->instance_id(), -1),
    308                 "StartPlayingFileAsMicrophone() failed to start "
    309                 "playing stream");
    310             return -1;
    311         }
    312         else
    313         {
    314             channelPtr->SetMixWithMicStatus(mixWithMicrophone);
    315             return 0;
    316         }
    317     }
    318 }
    319 
    320 int VoEFileImpl::StopPlayingFileAsMicrophone(int channel)
    321 {
    322     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    323                  "StopPlayingFileAsMicrophone(channel=%d)", channel);
    324     if (!_shared->statistics().Initialized())
    325     {
    326         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    327         return -1;
    328     }
    329     if (channel == -1)
    330     {
    331         // Stop adding file before demultiplexing <=> affects all channels
    332         return _shared->transmit_mixer()->StopPlayingFileAsMicrophone();
    333     }
    334     else
    335     {
    336         // Stop adding file after demultiplexing <=> affects one channel only
    337         voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    338         voe::Channel* channelPtr = ch.channel();
    339         if (channelPtr == NULL)
    340         {
    341             _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    342                 "StopPlayingFileAsMicrophone() failed to locate channel");
    343             return -1;
    344         }
    345         return channelPtr->StopPlayingFileAsMicrophone();
    346     }
    347 }
    348 
    349 int VoEFileImpl::IsPlayingFileAsMicrophone(int channel)
    350 {
    351     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    352                  "IsPlayingFileAsMicrophone(channel=%d)", channel);
    353     if (!_shared->statistics().Initialized())
    354     {
    355         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    356         return -1;
    357     }
    358     if (channel == -1)
    359     {
    360         return _shared->transmit_mixer()->IsPlayingFileAsMicrophone();
    361     }
    362     else
    363     {
    364         // Stop adding file after demultiplexing <=> affects one channel only
    365         voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    366         voe::Channel* channelPtr = ch.channel();
    367         if (channelPtr == NULL)
    368         {
    369             _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    370                 "IsPlayingFileAsMicrophone() failed to locate channel");
    371             return -1;
    372         }
    373         return channelPtr->IsPlayingFileAsMicrophone();
    374     }
    375 }
    376 
    377 int VoEFileImpl::StartRecordingPlayout(
    378     int channel, const char* fileNameUTF8, CodecInst* compression,
    379     int maxSizeBytes)
    380 {
    381     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    382                  "StartRecordingPlayout(channel=%d, fileNameUTF8=%s, "
    383                  "compression, maxSizeBytes=%d)",
    384                  channel, fileNameUTF8, maxSizeBytes);
    385     assert(1024 == FileWrapper::kMaxFileNameSize);
    386 
    387     if (!_shared->statistics().Initialized())
    388     {
    389         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    390         return -1;
    391     }
    392     if (channel == -1)
    393     {
    394         return _shared->output_mixer()->StartRecordingPlayout
    395           (fileNameUTF8, compression);
    396     }
    397     else
    398     {
    399         // Add file after demultiplexing <=> affects one channel only
    400         voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    401         voe::Channel* channelPtr = ch.channel();
    402         if (channelPtr == NULL)
    403         {
    404             _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    405                 "StartRecordingPlayout() failed to locate channel");
    406             return -1;
    407         }
    408         return channelPtr->StartRecordingPlayout(fileNameUTF8, compression);
    409     }
    410 }
    411 
    412 int VoEFileImpl::StartRecordingPlayout(
    413     int channel, OutStream* stream, CodecInst* compression)
    414 {
    415     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    416                  "StartRecordingPlayout(channel=%d, stream, compression)",
    417                  channel);
    418     if (!_shared->statistics().Initialized())
    419     {
    420         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    421         return -1;
    422     }
    423     if (channel == -1)
    424     {
    425         return _shared->output_mixer()->
    426             StartRecordingPlayout(stream, compression);
    427     }
    428     else
    429     {
    430         voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    431         voe::Channel* channelPtr = ch.channel();
    432         if (channelPtr == NULL)
    433         {
    434             _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    435                 "StartRecordingPlayout() failed to locate channel");
    436             return -1;
    437         }
    438         return channelPtr->StartRecordingPlayout(stream, compression);
    439     }
    440 }
    441 
    442 int VoEFileImpl::StopRecordingPlayout(int channel)
    443 {
    444     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    445                  "StopRecordingPlayout(channel=%d)", channel);
    446     if (!_shared->statistics().Initialized())
    447     {
    448         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    449         return -1;
    450     }
    451     if (channel == -1)
    452     {
    453         return _shared->output_mixer()->StopRecordingPlayout();
    454     }
    455     else
    456     {
    457         voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
    458         voe::Channel* channelPtr = ch.channel();
    459         if (channelPtr == NULL)
    460         {
    461             _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
    462                 "StopRecordingPlayout() failed to locate channel");
    463             return -1;
    464         }
    465         return channelPtr->StopRecordingPlayout();
    466     }
    467 }
    468 
    469 int VoEFileImpl::StartRecordingMicrophone(
    470     const char* fileNameUTF8, CodecInst* compression, int maxSizeBytes)
    471 {
    472     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    473                  "StartRecordingMicrophone(fileNameUTF8=%s, compression, "
    474                  "maxSizeBytes=%d)", fileNameUTF8, maxSizeBytes);
    475     assert(1024 == FileWrapper::kMaxFileNameSize);
    476 
    477     if (!_shared->statistics().Initialized())
    478     {
    479         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    480         return -1;
    481     }
    482     if (_shared->transmit_mixer()->StartRecordingMicrophone(fileNameUTF8,
    483                                                           compression))
    484     {
    485         WEBRTC_TRACE(kTraceError, kTraceVoice,
    486             VoEId(_shared->instance_id(), -1),
    487             "StartRecordingMicrophone() failed to start recording");
    488         return -1;
    489     }
    490     if (_shared->audio_device()->Recording())
    491     {
    492         return 0;
    493     }
    494     if (!_shared->ext_recording())
    495     {
    496         if (_shared->audio_device()->InitRecording() != 0)
    497         {
    498             WEBRTC_TRACE(kTraceError, kTraceVoice,
    499                 VoEId(_shared->instance_id(), -1),
    500                 "StartRecordingMicrophone() failed to initialize recording");
    501             return -1;
    502         }
    503         if (_shared->audio_device()->StartRecording() != 0)
    504         {
    505             WEBRTC_TRACE(kTraceError, kTraceVoice,
    506                 VoEId(_shared->instance_id(), -1),
    507                 "StartRecordingMicrophone() failed to start recording");
    508             return -1;
    509         }
    510     }
    511     return 0;
    512 }
    513 
    514 int VoEFileImpl::StartRecordingMicrophone(
    515     OutStream* stream, CodecInst* compression)
    516 {
    517     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    518                  "StartRecordingMicrophone(stream, compression)");
    519 
    520     if (!_shared->statistics().Initialized())
    521     {
    522         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    523         return -1;
    524     }
    525     if (_shared->transmit_mixer()->StartRecordingMicrophone(stream,
    526                                                           compression) == -1)
    527     {
    528         WEBRTC_TRACE(kTraceError, kTraceVoice,
    529             VoEId(_shared->instance_id(), -1),
    530             "StartRecordingMicrophone() failed to start recording");
    531         return -1;
    532     }
    533     if (_shared->audio_device()->Recording())
    534     {
    535         return 0;
    536     }
    537     if (!_shared->ext_recording())
    538     {
    539         if (_shared->audio_device()->InitRecording() != 0)
    540         {
    541             WEBRTC_TRACE(kTraceError, kTraceVoice,
    542                 VoEId(_shared->instance_id(), -1),
    543                 "StartRecordingMicrophone() failed to initialize recording");
    544             return -1;
    545         }
    546         if (_shared->audio_device()->StartRecording() != 0)
    547         {
    548             WEBRTC_TRACE(kTraceError, kTraceVoice,
    549                 VoEId(_shared->instance_id(), -1),
    550                 "StartRecordingMicrophone() failed to start recording");
    551             return -1;
    552         }
    553     }
    554     return 0;
    555 }
    556 
    557 int VoEFileImpl::StopRecordingMicrophone()
    558 {
    559     WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
    560                  "StopRecordingMicrophone()");
    561     if (!_shared->statistics().Initialized())
    562     {
    563         _shared->SetLastError(VE_NOT_INITED, kTraceError);
    564         return -1;
    565     }
    566 
    567     int err = 0;
    568 
    569     // TODO(xians): consider removing Start/StopRecording() in
    570     // Start/StopRecordingMicrophone() if no channel is recording.
    571     if (_shared->NumOfSendingChannels() == 0 &&
    572         _shared->audio_device()->Recording())
    573     {
    574         // Stop audio-device recording if no channel is recording
    575         if (_shared->audio_device()->StopRecording() != 0)
    576         {
    577             _shared->SetLastError(VE_CANNOT_STOP_RECORDING, kTraceError,
    578                 "StopRecordingMicrophone() failed to stop recording");
    579             err = -1;
    580         }
    581     }
    582 
    583     if (_shared->transmit_mixer()->StopRecordingMicrophone() != 0)
    584     {
    585         WEBRTC_TRACE(kTraceError, kTraceVoice,
    586                 VoEId(_shared->instance_id(), -1),
    587                 "StopRecordingMicrophone() failed to stop recording to mixer");
    588         err = -1;
    589     }
    590 
    591     return err;
    592 }
    593 
    594 #endif  // #ifdef WEBRTC_VOICE_ENGINE_FILE_API
    595 
    596 }  // namespace webrtc
    597