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