• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetInterface(VoiceEngine * voiceEngine)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 
VoEFileImpl(voe::SharedData * shared)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 
~VoEFileImpl()48 VoEFileImpl::~VoEFileImpl()
49 {
50     WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
51                  "VoEFileImpl::~VoEFileImpl() - dtor");
52 }
53 
StartPlayingFileLocally(int channel,const char fileNameUTF8[1024],bool loop,FileFormats format,float volumeScaling,int startPointMs,int stopPointMs)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 
StartPlayingFileLocally(int channel,InStream * stream,FileFormats format,float volumeScaling,int startPointMs,int stopPointMs)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 
StopPlayingFileLocally(int channel)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 
IsPlayingFileLocally(int channel)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 
StartPlayingFileAsMicrophone(int channel,const char fileNameUTF8[1024],bool loop,bool mixWithMicrophone,FileFormats format,float volumeScaling)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 
StartPlayingFileAsMicrophone(int channel,InStream * stream,bool mixWithMicrophone,FileFormats format,float volumeScaling)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 
StopPlayingFileAsMicrophone(int channel)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 
IsPlayingFileAsMicrophone(int channel)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 
StartRecordingPlayout(int channel,const char * fileNameUTF8,CodecInst * compression,int maxSizeBytes)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 
StartRecordingPlayout(int channel,OutStream * stream,CodecInst * compression)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 
StopRecordingPlayout(int channel)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 
StartRecordingMicrophone(const char * fileNameUTF8,CodecInst * compression,int maxSizeBytes)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 
StartRecordingMicrophone(OutStream * stream,CodecInst * compression)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 
StopRecordingMicrophone()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