blob: 95e9d21b3917d73004e3fc9c405785e4a338b388 [file] [log] [blame]
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/voice_engine/voe_file_impl.h"
#include "webrtc/modules/media_file/interface/media_file.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/file_wrapper.h"
#include "webrtc/system_wrappers/interface/trace.h"
#include "webrtc/voice_engine/channel.h"
#include "webrtc/voice_engine/include/voe_errors.h"
#include "webrtc/voice_engine/output_mixer.h"
#include "webrtc/voice_engine/transmit_mixer.h"
#include "webrtc/voice_engine/voice_engine_impl.h"
namespace webrtc {
VoEFile* VoEFile::GetInterface(VoiceEngine* voiceEngine)
{
#ifndef WEBRTC_VOICE_ENGINE_FILE_API
return NULL;
#else
if (NULL == voiceEngine)
{
return NULL;
}
VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
s->AddRef();
return s;
#endif
}
#ifdef WEBRTC_VOICE_ENGINE_FILE_API
VoEFileImpl::VoEFileImpl(voe::SharedData* shared) : _shared(shared)
{
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
"VoEFileImpl::VoEFileImpl() - ctor");
}
VoEFileImpl::~VoEFileImpl()
{
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
"VoEFileImpl::~VoEFileImpl() - dtor");
}
int VoEFileImpl::StartPlayingFileLocally(
int channel,
const char fileNameUTF8[1024],
bool loop, FileFormats format,
float volumeScaling,
int startPointMs,
int stopPointMs)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StartPlayingFileLocally(channel=%d, fileNameUTF8[]=%s, "
"loop=%d, format=%d, volumeScaling=%5.3f, startPointMs=%d,"
" stopPointMs=%d)",
channel, fileNameUTF8, loop, format, volumeScaling,
startPointMs, stopPointMs);
assert(1024 == FileWrapper::kMaxFileNameSize);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StartPlayingFileLocally() failed to locate channel");
return -1;
}
return channelPtr->StartPlayingFileLocally(fileNameUTF8,
loop,
format,
startPointMs,
volumeScaling,
stopPointMs,
NULL);
}
int VoEFileImpl::StartPlayingFileLocally(int channel,
InStream* stream,
FileFormats format,
float volumeScaling,
int startPointMs,
int stopPointMs)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StartPlayingFileLocally(channel=%d, stream, format=%d, "
"volumeScaling=%5.3f, startPointMs=%d, stopPointMs=%d)",
channel, format, volumeScaling, startPointMs, stopPointMs);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StartPlayingFileLocally() failed to locate channel");
return -1;
}
return channelPtr->StartPlayingFileLocally(stream,
format,
startPointMs,
volumeScaling,
stopPointMs,
NULL);
}
int VoEFileImpl::StopPlayingFileLocally(int channel)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StopPlayingFileLocally()");
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StopPlayingFileLocally() failed to locate channel");
return -1;
}
return channelPtr->StopPlayingFileLocally();
}
int VoEFileImpl::IsPlayingFileLocally(int channel)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"IsPlayingFileLocally(channel=%d)", channel);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StopPlayingFileLocally() failed to locate channel");
return -1;
}
return channelPtr->IsPlayingFileLocally();
}
int VoEFileImpl::StartPlayingFileAsMicrophone(int channel,
const char fileNameUTF8[1024],
bool loop,
bool mixWithMicrophone,
FileFormats format,
float volumeScaling)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StartPlayingFileAsMicrophone(channel=%d, fileNameUTF8=%s, "
"loop=%d, mixWithMicrophone=%d, format=%d, "
"volumeScaling=%5.3f)",
channel, fileNameUTF8, loop, mixWithMicrophone, format,
volumeScaling);
assert(1024 == FileWrapper::kMaxFileNameSize);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
const uint32_t startPointMs(0);
const uint32_t stopPointMs(0);
if (channel == -1)
{
int res = _shared->transmit_mixer()->StartPlayingFileAsMicrophone(
fileNameUTF8,
loop,
format,
startPointMs,
volumeScaling,
stopPointMs,
NULL);
if (res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartPlayingFileAsMicrophone() failed to start playing file");
return(-1);
}
else
{
_shared->transmit_mixer()->SetMixWithMicStatus(mixWithMicrophone);
return(0);
}
}
else
{
// Add file after demultiplexing <=> affects one channel only
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StartPlayingFileAsMicrophone() failed to locate channel");
return -1;
}
int res = channelPtr->StartPlayingFileAsMicrophone(fileNameUTF8,
loop,
format,
startPointMs,
volumeScaling,
stopPointMs,
NULL);
if (res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartPlayingFileAsMicrophone() failed to start playing file");
return -1;
}
else
{
channelPtr->SetMixWithMicStatus(mixWithMicrophone);
return 0;
}
}
}
int VoEFileImpl::StartPlayingFileAsMicrophone(int channel,
InStream* stream,
bool mixWithMicrophone,
FileFormats format,
float volumeScaling)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StartPlayingFileAsMicrophone(channel=%d, stream,"
" mixWithMicrophone=%d, format=%d, volumeScaling=%5.3f)",
channel, mixWithMicrophone, format, volumeScaling);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
const uint32_t startPointMs(0);
const uint32_t stopPointMs(0);
if (channel == -1)
{
int res = _shared->transmit_mixer()->StartPlayingFileAsMicrophone(
stream,
format,
startPointMs,
volumeScaling,
stopPointMs,
NULL);
if (res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartPlayingFileAsMicrophone() failed to start "
"playing stream");
return(-1);
}
else
{
_shared->transmit_mixer()->SetMixWithMicStatus(mixWithMicrophone);
return(0);
}
}
else
{
// Add file after demultiplexing <=> affects one channel only
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StartPlayingFileAsMicrophone() failed to locate channel");
return -1;
}
int res = channelPtr->StartPlayingFileAsMicrophone(
stream, format, startPointMs, volumeScaling, stopPointMs, NULL);
if (res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartPlayingFileAsMicrophone() failed to start "
"playing stream");
return -1;
}
else
{
channelPtr->SetMixWithMicStatus(mixWithMicrophone);
return 0;
}
}
}
int VoEFileImpl::StopPlayingFileAsMicrophone(int channel)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StopPlayingFileAsMicrophone(channel=%d)", channel);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (channel == -1)
{
// Stop adding file before demultiplexing <=> affects all channels
return _shared->transmit_mixer()->StopPlayingFileAsMicrophone();
}
else
{
// Stop adding file after demultiplexing <=> affects one channel only
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StopPlayingFileAsMicrophone() failed to locate channel");
return -1;
}
return channelPtr->StopPlayingFileAsMicrophone();
}
}
int VoEFileImpl::IsPlayingFileAsMicrophone(int channel)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"IsPlayingFileAsMicrophone(channel=%d)", channel);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (channel == -1)
{
return _shared->transmit_mixer()->IsPlayingFileAsMicrophone();
}
else
{
// Stop adding file after demultiplexing <=> affects one channel only
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"IsPlayingFileAsMicrophone() failed to locate channel");
return -1;
}
return channelPtr->IsPlayingFileAsMicrophone();
}
}
int VoEFileImpl::StartRecordingPlayout(
int channel, const char* fileNameUTF8, CodecInst* compression,
int maxSizeBytes)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StartRecordingPlayout(channel=%d, fileNameUTF8=%s, "
"compression, maxSizeBytes=%d)",
channel, fileNameUTF8, maxSizeBytes);
assert(1024 == FileWrapper::kMaxFileNameSize);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (channel == -1)
{
return _shared->output_mixer()->StartRecordingPlayout
(fileNameUTF8, compression);
}
else
{
// Add file after demultiplexing <=> affects one channel only
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StartRecordingPlayout() failed to locate channel");
return -1;
}
return channelPtr->StartRecordingPlayout(fileNameUTF8, compression);
}
}
int VoEFileImpl::StartRecordingPlayout(
int channel, OutStream* stream, CodecInst* compression)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StartRecordingPlayout(channel=%d, stream, compression)",
channel);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (channel == -1)
{
return _shared->output_mixer()->
StartRecordingPlayout(stream, compression);
}
else
{
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StartRecordingPlayout() failed to locate channel");
return -1;
}
return channelPtr->StartRecordingPlayout(stream, compression);
}
}
int VoEFileImpl::StopRecordingPlayout(int channel)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StopRecordingPlayout(channel=%d)", channel);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (channel == -1)
{
return _shared->output_mixer()->StopRecordingPlayout();
}
else
{
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StopRecordingPlayout() failed to locate channel");
return -1;
}
return channelPtr->StopRecordingPlayout();
}
}
int VoEFileImpl::StartRecordingMicrophone(
const char* fileNameUTF8, CodecInst* compression, int maxSizeBytes)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StartRecordingMicrophone(fileNameUTF8=%s, compression, "
"maxSizeBytes=%d)", fileNameUTF8, maxSizeBytes);
assert(1024 == FileWrapper::kMaxFileNameSize);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (_shared->transmit_mixer()->StartRecordingMicrophone(fileNameUTF8,
compression))
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartRecordingMicrophone() failed to start recording");
return -1;
}
if (_shared->audio_device()->Recording())
{
return 0;
}
if (!_shared->ext_recording())
{
if (_shared->audio_device()->InitRecording() != 0)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartRecordingMicrophone() failed to initialize recording");
return -1;
}
if (_shared->audio_device()->StartRecording() != 0)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartRecordingMicrophone() failed to start recording");
return -1;
}
}
return 0;
}
int VoEFileImpl::StartRecordingMicrophone(
OutStream* stream, CodecInst* compression)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StartRecordingMicrophone(stream, compression)");
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (_shared->transmit_mixer()->StartRecordingMicrophone(stream,
compression) == -1)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartRecordingMicrophone() failed to start recording");
return -1;
}
if (_shared->audio_device()->Recording())
{
return 0;
}
if (!_shared->ext_recording())
{
if (_shared->audio_device()->InitRecording() != 0)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartRecordingMicrophone() failed to initialize recording");
return -1;
}
if (_shared->audio_device()->StartRecording() != 0)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartRecordingMicrophone() failed to start recording");
return -1;
}
}
return 0;
}
int VoEFileImpl::StopRecordingMicrophone()
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StopRecordingMicrophone()");
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
int err = 0;
// TODO(xians): consider removing Start/StopRecording() in
// Start/StopRecordingMicrophone() if no channel is recording.
if (_shared->NumOfSendingChannels() == 0 &&
_shared->audio_device()->Recording())
{
// Stop audio-device recording if no channel is recording
if (_shared->audio_device()->StopRecording() != 0)
{
_shared->SetLastError(VE_CANNOT_STOP_RECORDING, kTraceError,
"StopRecordingMicrophone() failed to stop recording");
err = -1;
}
}
if (_shared->transmit_mixer()->StopRecordingMicrophone() != 0)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StopRecordingMicrophone() failed to stop recording to mixer");
err = -1;
}
return err;
}
#endif // #ifdef WEBRTC_VOICE_ENGINE_FILE_API
} // namespace webrtc