Remove VoEFile and things it uses.

BUG=webrtc:4690

Review-Url: https://codereview.webrtc.org/3013033002
Cr-Commit-Position: refs/heads/master@{#19885}
This commit is contained in:
solenberg 2017-09-18 03:04:12 -07:00 committed by Commit Bot
parent 2352ce3c43
commit b63310a256
22 changed files with 5 additions and 3749 deletions

View File

@ -134,55 +134,6 @@ class MockVoiceEngine : public VoiceEngineImpl {
MOCK_METHOD2(SetOpusMaxPlaybackRate, int(int channel, int frequency_hz));
MOCK_METHOD2(SetOpusDtx, int(int channel, bool enable_dtx));
// VoEFile
MOCK_METHOD7(StartPlayingFileLocally,
int(int channel,
const char fileNameUTF8[1024],
bool loop,
FileFormats format,
float volumeScaling,
int startPointMs,
int stopPointMs));
MOCK_METHOD6(StartPlayingFileLocally,
int(int channel,
InStream* stream,
FileFormats format,
float volumeScaling,
int startPointMs,
int stopPointMs));
MOCK_METHOD1(StopPlayingFileLocally, int(int channel));
MOCK_METHOD1(IsPlayingFileLocally, int(int channel));
MOCK_METHOD6(StartPlayingFileAsMicrophone,
int(int channel,
const char fileNameUTF8[1024],
bool loop,
bool mixWithMicrophone,
FileFormats format,
float volumeScaling));
MOCK_METHOD5(StartPlayingFileAsMicrophone,
int(int channel,
InStream* stream,
bool mixWithMicrophone,
FileFormats format,
float volumeScaling));
MOCK_METHOD1(StopPlayingFileAsMicrophone, int(int channel));
MOCK_METHOD1(IsPlayingFileAsMicrophone, int(int channel));
MOCK_METHOD4(StartRecordingPlayout,
int(int channel,
const char* fileNameUTF8,
CodecInst* compression,
int maxSizeBytes));
MOCK_METHOD1(StopRecordingPlayout, int(int channel));
MOCK_METHOD3(StartRecordingPlayout,
int(int channel, OutStream* stream, CodecInst* compression));
MOCK_METHOD3(StartRecordingMicrophone,
int(const char* fileNameUTF8,
CodecInst* compression,
int maxSizeBytes));
MOCK_METHOD2(StartRecordingMicrophone,
int(OutStream* stream, CodecInst* compression));
MOCK_METHOD0(StopRecordingMicrophone, int());
// VoENetwork
MOCK_METHOD2(RegisterExternalTransport,
int(int channel, Transport& transport));

View File

@ -8,69 +8,6 @@
import("../webrtc.gni")
rtc_static_library("audio_coder") {
sources = [
"coder.cc",
"coder.h",
]
deps = [
"..:webrtc_common",
"../api/audio_codecs:builtin_audio_decoder_factory",
"../api/audio_codecs:builtin_audio_encoder_factory",
"../modules:module_api",
"../modules/audio_coding",
"../modules/audio_coding:audio_format_conversion",
"../modules/audio_coding:rent_a_codec",
]
if (!build_with_chromium && is_clang) {
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
}
}
rtc_static_library("file_player") {
sources = [
"file_player.cc",
"file_player.h",
]
deps = [
":audio_coder",
"..:webrtc_common",
"../common_audio",
"../modules:module_api",
"../modules/media_file",
"../rtc_base:rtc_base_approved",
]
if (!build_with_chromium && is_clang) {
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
}
}
rtc_static_library("file_recorder") {
sources = [
"file_recorder.cc",
"file_recorder.h",
]
deps = [
":audio_coder",
"..:webrtc_common",
"../audio/utility:audio_frame_operations",
"../common_audio",
"../modules:module_api",
"../modules/media_file:media_file",
"../rtc_base:rtc_base_approved",
"../system_wrappers",
]
if (!build_with_chromium && is_clang) {
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
}
}
rtc_static_library("voice_engine") {
sources = [
"channel.cc",
@ -82,7 +19,6 @@ rtc_static_library("voice_engine") {
"include/voe_base.h",
"include/voe_codec.h",
"include/voe_errors.h",
"include/voe_file.h",
"include/voe_network.h",
"include/voe_rtp_rtcp.h",
"monitor_module.h",
@ -102,8 +38,6 @@ rtc_static_library("voice_engine") {
"voe_base_impl.h",
"voe_codec_impl.cc",
"voe_codec_impl.h",
"voe_file_impl.cc",
"voe_file_impl.h",
"voe_network_impl.cc",
"voe_network_impl.h",
"voe_rtp_rtcp_impl.cc",
@ -132,8 +66,6 @@ rtc_static_library("voice_engine") {
]
deps = [
":audio_level",
":file_player",
":file_recorder",
"..:webrtc_common",
"../api:array_view",
"../api:audio_mixer_api",
@ -182,7 +114,6 @@ rtc_static_library("audio_level") {
if (rtc_include_tests) {
rtc_test("voice_engine_unittests") {
deps = [
":file_player",
":voice_engine",
"../common_audio",
"../modules:module_api",
@ -211,7 +142,6 @@ if (rtc_include_tests) {
sources = [
"channel_unittest.cc",
"file_player_unittests.cc",
"transport_feedback_packet_loss_tracker_unittest.cc",
"utility_unittest.cc",
"voe_base_unittest.cc",

View File

@ -651,8 +651,6 @@ MixerParticipant::AudioFrameInfo Channel::GetAudioFrameWithMuted(
// Store speech type for dead-or-alive detection
_outputSpeechType = audioFrame->speech_type_;
ChannelState::State state = channel_state_.Get();
{
// Pass the audio buffers to an optional sink callback, before applying
// scaling/panning, as that applies to the mix operation.
@ -680,21 +678,6 @@ MixerParticipant::AudioFrameInfo Channel::GetAudioFrameWithMuted(
AudioFrameOperations::ScaleWithSat(output_gain, audioFrame);
}
// Mix decoded PCM output with file if file mixing is enabled
if (state.output_file_playing) {
MixAudioWithFile(*audioFrame, audioFrame->sample_rate_hz_);
muted = false; // We may have added non-zero samples.
}
// Record playout if enabled
{
rtc::CritScope cs(&_fileCritSect);
if (_outputFileRecording && output_file_recorder_) {
output_file_recorder_->RecordAudioToFile(*audioFrame);
}
}
// Measure audio level (0-9)
// TODO(henrik.lundin) Use the |muted| information here too.
// TODO(deadbeef): Use RmsLevel for |_outputAudioLevel| (see
@ -774,20 +757,7 @@ int32_t Channel::NeededFrequency(int32_t id) const {
highestNeeded = receiveFrequency;
}
// Special case, if we're playing a file on the playout side
// we take that frequency into consideration as well
// This is not needed on sending side, since the codec will
// limit the spectrum anyway.
if (channel_state_.Get().output_file_playing) {
rtc::CritScope cs(&_fileCritSect);
if (output_file_player_) {
if (output_file_player_->Frequency() > highestNeeded) {
highestNeeded = output_file_player_->Frequency();
}
}
}
return (highestNeeded);
return highestNeeded;
}
int32_t Channel::CreateChannel(Channel*& channel,
@ -808,53 +778,6 @@ int32_t Channel::CreateChannel(Channel*& channel,
return 0;
}
void Channel::PlayNotification(int32_t id, uint32_t durationMs) {
WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::PlayNotification(id=%d, durationMs=%d)", id,
durationMs);
// Not implement yet
}
void Channel::RecordNotification(int32_t id, uint32_t durationMs) {
WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::RecordNotification(id=%d, durationMs=%d)", id,
durationMs);
// Not implement yet
}
void Channel::PlayFileEnded(int32_t id) {
WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::PlayFileEnded(id=%d)", id);
if (id == _inputFilePlayerId) {
channel_state_.SetInputFilePlaying(false);
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::PlayFileEnded() => input file player module is"
" shutdown");
} else if (id == _outputFilePlayerId) {
channel_state_.SetOutputFilePlaying(false);
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::PlayFileEnded() => output file player module is"
" shutdown");
}
}
void Channel::RecordFileEnded(int32_t id) {
WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::RecordFileEnded(id=%d)", id);
assert(id == _outputFileRecorderId);
rtc::CritScope cs(&_fileCritSect);
_outputFileRecording = false;
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::RecordFileEnded() => output file recorder module is"
" shutdown");
}
Channel::Channel(int32_t channelId,
uint32_t instanceId,
const VoEBase::ChannelConfig& config)
@ -874,12 +797,6 @@ Channel::Channel(int32_t channelId,
telephone_event_handler_(rtp_receiver_->GetTelephoneEventHandler()),
_outputAudioLevel(),
_externalTransport(false),
// Avoid conflict with other channels by adding 1024 - 1026,
// won't use as much as 1024 channels.
_inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024),
_outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025),
_outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026),
_outputFileRecording(false),
_timeStamp(0), // This is just an offset, RTP module will add it's own
// random offset
ntp_estimator_(Clock::GetRealTimeClock()),
@ -899,7 +816,6 @@ Channel::Channel(int32_t channelId,
input_mute_(false),
previous_frame_muted_(false),
_outputGain(1.0f),
_mixFileWithMicrophone(false),
_includeAudioLevelIndication(false),
transport_overhead_per_packet_(0),
rtp_overhead_per_packet_(0),
@ -1088,22 +1004,6 @@ void Channel::Terminate() {
StopSend();
StopPlayout();
{
rtc::CritScope cs(&_fileCritSect);
if (input_file_player_) {
input_file_player_->RegisterModuleFileCallback(NULL);
input_file_player_->StopPlayingFile();
}
if (output_file_player_) {
output_file_player_->RegisterModuleFileCallback(NULL);
output_file_player_->StopPlayingFile();
}
if (output_file_recorder_) {
output_file_recorder_->RegisterModuleFileCallback(NULL);
output_file_recorder_->StopRecording();
}
}
// The order to safely shutdown modules in a channel is:
// 1. De-register callbacks in modules
// 2. De-register modules in process thread
@ -1174,8 +1074,6 @@ int32_t Channel::StartPlayout() {
}
channel_state_.SetPlaying(true);
if (RegisterFilePlayingToMixer() != 0)
return -1;
return 0;
}
@ -1823,508 +1721,6 @@ int32_t Channel::ReceivedRTCPPacket(const uint8_t* data, size_t length) {
return 0;
}
int Channel::StartPlayingFileLocally(const char* fileName,
bool loop,
FileFormats format,
int startPosition,
float volumeScaling,
int stopPosition,
const CodecInst* codecInst) {
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::StartPlayingFileLocally(fileNameUTF8[]=%s, loop=%d,"
" format=%d, volumeScaling=%5.3f, startPosition=%d, "
"stopPosition=%d)",
fileName, loop, format, volumeScaling, startPosition,
stopPosition);
if (channel_state_.Get().output_file_playing) {
_engineStatisticsPtr->SetLastError(
VE_ALREADY_PLAYING, kTraceError,
"StartPlayingFileLocally() is already playing");
return -1;
}
{
rtc::CritScope cs(&_fileCritSect);
if (output_file_player_) {
output_file_player_->RegisterModuleFileCallback(NULL);
output_file_player_.reset();
}
output_file_player_ = FilePlayer::CreateFilePlayer(
_outputFilePlayerId, (const FileFormats)format);
if (!output_file_player_) {
_engineStatisticsPtr->SetLastError(
VE_INVALID_ARGUMENT, kTraceError,
"StartPlayingFileLocally() filePlayer format is not correct");
return -1;
}
const uint32_t notificationTime(0);
if (output_file_player_->StartPlayingFile(
fileName, loop, startPosition, volumeScaling, notificationTime,
stopPosition, (const CodecInst*)codecInst) != 0) {
_engineStatisticsPtr->SetLastError(
VE_BAD_FILE, kTraceError,
"StartPlayingFile() failed to start file playout");
output_file_player_->StopPlayingFile();
output_file_player_.reset();
return -1;
}
output_file_player_->RegisterModuleFileCallback(this);
channel_state_.SetOutputFilePlaying(true);
}
if (RegisterFilePlayingToMixer() != 0)
return -1;
return 0;
}
int Channel::StartPlayingFileLocally(InStream* stream,
FileFormats format,
int startPosition,
float volumeScaling,
int stopPosition,
const CodecInst* codecInst) {
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::StartPlayingFileLocally(format=%d,"
" volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
format, volumeScaling, startPosition, stopPosition);
if (stream == NULL) {
_engineStatisticsPtr->SetLastError(
VE_BAD_FILE, kTraceError,
"StartPlayingFileLocally() NULL as input stream");
return -1;
}
if (channel_state_.Get().output_file_playing) {
_engineStatisticsPtr->SetLastError(
VE_ALREADY_PLAYING, kTraceError,
"StartPlayingFileLocally() is already playing");
return -1;
}
{
rtc::CritScope cs(&_fileCritSect);
// Destroy the old instance
if (output_file_player_) {
output_file_player_->RegisterModuleFileCallback(NULL);
output_file_player_.reset();
}
// Create the instance
output_file_player_ = FilePlayer::CreateFilePlayer(
_outputFilePlayerId, (const FileFormats)format);
if (!output_file_player_) {
_engineStatisticsPtr->SetLastError(
VE_INVALID_ARGUMENT, kTraceError,
"StartPlayingFileLocally() filePlayer format isnot correct");
return -1;
}
const uint32_t notificationTime(0);
if (output_file_player_->StartPlayingFile(stream, startPosition,
volumeScaling, notificationTime,
stopPosition, codecInst) != 0) {
_engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
"StartPlayingFile() failed to "
"start file playout");
output_file_player_->StopPlayingFile();
output_file_player_.reset();
return -1;
}
output_file_player_->RegisterModuleFileCallback(this);
channel_state_.SetOutputFilePlaying(true);
}
if (RegisterFilePlayingToMixer() != 0)
return -1;
return 0;
}
int Channel::StopPlayingFileLocally() {
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::StopPlayingFileLocally()");
if (!channel_state_.Get().output_file_playing) {
return 0;
}
{
rtc::CritScope cs(&_fileCritSect);
if (output_file_player_->StopPlayingFile() != 0) {
_engineStatisticsPtr->SetLastError(
VE_STOP_RECORDING_FAILED, kTraceError,
"StopPlayingFile() could not stop playing");
return -1;
}
output_file_player_->RegisterModuleFileCallback(NULL);
output_file_player_.reset();
channel_state_.SetOutputFilePlaying(false);
}
// _fileCritSect cannot be taken while calling
// SetAnonymousMixibilityStatus. Refer to comments in
// StartPlayingFileLocally(const char* ...) for more details.
if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, false) != 0) {
_engineStatisticsPtr->SetLastError(
VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
"StopPlayingFile() failed to stop participant from playing as"
"file in the mixer");
return -1;
}
return 0;
}
int Channel::IsPlayingFileLocally() const {
return channel_state_.Get().output_file_playing;
}
int Channel::RegisterFilePlayingToMixer() {
// Return success for not registering for file playing to mixer if:
// 1. playing file before playout is started on that channel.
// 2. starting playout without file playing on that channel.
if (!channel_state_.Get().playing ||
!channel_state_.Get().output_file_playing) {
return 0;
}
// |_fileCritSect| cannot be taken while calling
// SetAnonymousMixabilityStatus() since as soon as the participant is added
// frames can be pulled by the mixer. Since the frames are generated from
// the file, _fileCritSect will be taken. This would result in a deadlock.
if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0) {
channel_state_.SetOutputFilePlaying(false);
rtc::CritScope cs(&_fileCritSect);
_engineStatisticsPtr->SetLastError(
VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
"StartPlayingFile() failed to add participant as file to mixer");
output_file_player_->StopPlayingFile();
output_file_player_.reset();
return -1;
}
return 0;
}
int Channel::StartPlayingFileAsMicrophone(const char* fileName,
bool loop,
FileFormats format,
int startPosition,
float volumeScaling,
int stopPosition,
const CodecInst* codecInst) {
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::StartPlayingFileAsMicrophone(fileNameUTF8[]=%s, "
"loop=%d, format=%d, volumeScaling=%5.3f, startPosition=%d, "
"stopPosition=%d)",
fileName, loop, format, volumeScaling, startPosition,
stopPosition);
rtc::CritScope cs(&_fileCritSect);
if (channel_state_.Get().input_file_playing) {
_engineStatisticsPtr->SetLastError(
VE_ALREADY_PLAYING, kTraceWarning,
"StartPlayingFileAsMicrophone() filePlayer is playing");
return 0;
}
// Destroy the old instance
if (input_file_player_) {
input_file_player_->RegisterModuleFileCallback(NULL);
input_file_player_.reset();
}
// Create the instance
input_file_player_ = FilePlayer::CreateFilePlayer(_inputFilePlayerId,
(const FileFormats)format);
if (!input_file_player_) {
_engineStatisticsPtr->SetLastError(
VE_INVALID_ARGUMENT, kTraceError,
"StartPlayingFileAsMicrophone() filePlayer format isnot correct");
return -1;
}
const uint32_t notificationTime(0);
if (input_file_player_->StartPlayingFile(
fileName, loop, startPosition, volumeScaling, notificationTime,
stopPosition, (const CodecInst*)codecInst) != 0) {
_engineStatisticsPtr->SetLastError(
VE_BAD_FILE, kTraceError,
"StartPlayingFile() failed to start file playout");
input_file_player_->StopPlayingFile();
input_file_player_.reset();
return -1;
}
input_file_player_->RegisterModuleFileCallback(this);
channel_state_.SetInputFilePlaying(true);
return 0;
}
int Channel::StartPlayingFileAsMicrophone(InStream* stream,
FileFormats format,
int startPosition,
float volumeScaling,
int stopPosition,
const CodecInst* codecInst) {
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::StartPlayingFileAsMicrophone(format=%d, "
"volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
format, volumeScaling, startPosition, stopPosition);
if (stream == NULL) {
_engineStatisticsPtr->SetLastError(
VE_BAD_FILE, kTraceError,
"StartPlayingFileAsMicrophone NULL as input stream");
return -1;
}
rtc::CritScope cs(&_fileCritSect);
if (channel_state_.Get().input_file_playing) {
_engineStatisticsPtr->SetLastError(
VE_ALREADY_PLAYING, kTraceWarning,
"StartPlayingFileAsMicrophone() is playing");
return 0;
}
// Destroy the old instance
if (input_file_player_) {
input_file_player_->RegisterModuleFileCallback(NULL);
input_file_player_.reset();
}
// Create the instance
input_file_player_ = FilePlayer::CreateFilePlayer(_inputFilePlayerId,
(const FileFormats)format);
if (!input_file_player_) {
_engineStatisticsPtr->SetLastError(
VE_INVALID_ARGUMENT, kTraceError,
"StartPlayingInputFile() filePlayer format isnot correct");
return -1;
}
const uint32_t notificationTime(0);
if (input_file_player_->StartPlayingFile(stream, startPosition, volumeScaling,
notificationTime, stopPosition,
codecInst) != 0) {
_engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
"StartPlayingFile() failed to start "
"file playout");
input_file_player_->StopPlayingFile();
input_file_player_.reset();
return -1;
}
input_file_player_->RegisterModuleFileCallback(this);
channel_state_.SetInputFilePlaying(true);
return 0;
}
int Channel::StopPlayingFileAsMicrophone() {
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::StopPlayingFileAsMicrophone()");
rtc::CritScope cs(&_fileCritSect);
if (!channel_state_.Get().input_file_playing) {
return 0;
}
if (input_file_player_->StopPlayingFile() != 0) {
_engineStatisticsPtr->SetLastError(
VE_STOP_RECORDING_FAILED, kTraceError,
"StopPlayingFile() could not stop playing");
return -1;
}
input_file_player_->RegisterModuleFileCallback(NULL);
input_file_player_.reset();
channel_state_.SetInputFilePlaying(false);
return 0;
}
int Channel::IsPlayingFileAsMicrophone() const {
return channel_state_.Get().input_file_playing;
}
int Channel::StartRecordingPlayout(const char* fileName,
const CodecInst* codecInst) {
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::StartRecordingPlayout(fileName=%s)", fileName);
if (_outputFileRecording) {
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
"StartRecordingPlayout() is already recording");
return 0;
}
FileFormats format;
const uint32_t notificationTime(0); // Not supported in VoE
CodecInst dummyCodec = {100, "L16", 16000, 320, 1, 320000};
if ((codecInst != NULL) &&
((codecInst->channels < 1) || (codecInst->channels > 2))) {
_engineStatisticsPtr->SetLastError(
VE_BAD_ARGUMENT, kTraceError,
"StartRecordingPlayout() invalid compression");
return (-1);
}
if (codecInst == NULL) {
format = kFileFormatPcm16kHzFile;
codecInst = &dummyCodec;
} else if ((STR_CASE_CMP(codecInst->plname, "L16") == 0) ||
(STR_CASE_CMP(codecInst->plname, "PCMU") == 0) ||
(STR_CASE_CMP(codecInst->plname, "PCMA") == 0)) {
format = kFileFormatWavFile;
} else {
format = kFileFormatCompressedFile;
}
rtc::CritScope cs(&_fileCritSect);
// Destroy the old instance
if (output_file_recorder_) {
output_file_recorder_->RegisterModuleFileCallback(NULL);
output_file_recorder_.reset();
}
output_file_recorder_ = FileRecorder::CreateFileRecorder(
_outputFileRecorderId, (const FileFormats)format);
if (!output_file_recorder_) {
_engineStatisticsPtr->SetLastError(
VE_INVALID_ARGUMENT, kTraceError,
"StartRecordingPlayout() fileRecorder format isnot correct");
return -1;
}
if (output_file_recorder_->StartRecordingAudioFile(
fileName, (const CodecInst&)*codecInst, notificationTime) != 0) {
_engineStatisticsPtr->SetLastError(
VE_BAD_FILE, kTraceError,
"StartRecordingAudioFile() failed to start file recording");
output_file_recorder_->StopRecording();
output_file_recorder_.reset();
return -1;
}
output_file_recorder_->RegisterModuleFileCallback(this);
_outputFileRecording = true;
return 0;
}
int Channel::StartRecordingPlayout(OutStream* stream,
const CodecInst* codecInst) {
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::StartRecordingPlayout()");
if (_outputFileRecording) {
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
"StartRecordingPlayout() is already recording");
return 0;
}
FileFormats format;
const uint32_t notificationTime(0); // Not supported in VoE
CodecInst dummyCodec = {100, "L16", 16000, 320, 1, 320000};
if (codecInst != NULL && codecInst->channels != 1) {
_engineStatisticsPtr->SetLastError(
VE_BAD_ARGUMENT, kTraceError,
"StartRecordingPlayout() invalid compression");
return (-1);
}
if (codecInst == NULL) {
format = kFileFormatPcm16kHzFile;
codecInst = &dummyCodec;
} else if ((STR_CASE_CMP(codecInst->plname, "L16") == 0) ||
(STR_CASE_CMP(codecInst->plname, "PCMU") == 0) ||
(STR_CASE_CMP(codecInst->plname, "PCMA") == 0)) {
format = kFileFormatWavFile;
} else {
format = kFileFormatCompressedFile;
}
rtc::CritScope cs(&_fileCritSect);
// Destroy the old instance
if (output_file_recorder_) {
output_file_recorder_->RegisterModuleFileCallback(NULL);
output_file_recorder_.reset();
}
output_file_recorder_ = FileRecorder::CreateFileRecorder(
_outputFileRecorderId, (const FileFormats)format);
if (!output_file_recorder_) {
_engineStatisticsPtr->SetLastError(
VE_INVALID_ARGUMENT, kTraceError,
"StartRecordingPlayout() fileRecorder format isnot correct");
return -1;
}
if (output_file_recorder_->StartRecordingAudioFile(stream, *codecInst,
notificationTime) != 0) {
_engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
"StartRecordingPlayout() failed to "
"start file recording");
output_file_recorder_->StopRecording();
output_file_recorder_.reset();
return -1;
}
output_file_recorder_->RegisterModuleFileCallback(this);
_outputFileRecording = true;
return 0;
}
int Channel::StopRecordingPlayout() {
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
"Channel::StopRecordingPlayout()");
if (!_outputFileRecording) {
WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, -1),
"StopRecordingPlayout() isnot recording");
return -1;
}
rtc::CritScope cs(&_fileCritSect);
if (output_file_recorder_->StopRecording() != 0) {
_engineStatisticsPtr->SetLastError(
VE_STOP_RECORDING_FAILED, kTraceError,
"StopRecording() could not stop recording");
return (-1);
}
output_file_recorder_->RegisterModuleFileCallback(NULL);
output_file_recorder_.reset();
_outputFileRecording = false;
return 0;
}
void Channel::SetMixWithMicStatus(bool mix) {
rtc::CritScope cs(&_fileCritSect);
_mixFileWithMicrophone = mix;
}
int Channel::GetSpeechOutputLevel() const {
return _outputAudioLevel.Level();
}
@ -2760,10 +2156,6 @@ void Channel::ProcessAndEncodeAudioOnTaskQueue(AudioFrame* audio_input) {
RTC_DCHECK_LE(audio_input->num_channels_, 2);
RTC_DCHECK_EQ(audio_input->id_, ChannelId());
if (channel_state_.Get().input_file_playing) {
MixOrReplaceAudioWithFile(audio_input);
}
bool is_muted = InputMute();
AudioFrameOperations::Mute(audio_input, previous_frame_muted_, is_muted);
@ -2903,96 +2295,6 @@ int Channel::GetRtpRtcp(RtpRtcp** rtpRtcpModule,
return 0;
}
// TODO(andrew): refactor Mix functions here and in transmit_mixer.cc to use
// a shared helper.
int32_t Channel::MixOrReplaceAudioWithFile(AudioFrame* audio_input) {
RTC_DCHECK_RUN_ON(encoder_queue_);
std::unique_ptr<int16_t[]> fileBuffer(new int16_t[640]);
size_t fileSamples(0);
const int mixingFrequency = audio_input->sample_rate_hz_;
{
rtc::CritScope cs(&_fileCritSect);
if (!input_file_player_) {
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::MixOrReplaceAudioWithFile() fileplayer"
" doesnt exist");
return -1;
}
if (input_file_player_->Get10msAudioFromFile(fileBuffer.get(), &fileSamples,
mixingFrequency) == -1) {
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::MixOrReplaceAudioWithFile() file mixing "
"failed");
return -1;
}
if (fileSamples == 0) {
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::MixOrReplaceAudioWithFile() file is ended");
return 0;
}
}
RTC_DCHECK_EQ(audio_input->samples_per_channel_, fileSamples);
if (_mixFileWithMicrophone) {
// Currently file stream is always mono.
// TODO(xians): Change the code when FilePlayer supports real stereo.
MixWithSat(audio_input->mutable_data(), audio_input->num_channels_,
fileBuffer.get(), 1, fileSamples);
} else {
// Replace ACM audio with file.
// Currently file stream is always mono.
// TODO(xians): Change the code when FilePlayer supports real stereo.
audio_input->UpdateFrame(
_channelId, 0xFFFFFFFF, fileBuffer.get(), fileSamples, mixingFrequency,
AudioFrame::kNormalSpeech, AudioFrame::kVadUnknown, 1);
}
return 0;
}
int32_t Channel::MixAudioWithFile(AudioFrame& audioFrame, int mixingFrequency) {
assert(mixingFrequency <= 48000);
std::unique_ptr<int16_t[]> fileBuffer(new int16_t[960]);
size_t fileSamples(0);
{
rtc::CritScope cs(&_fileCritSect);
if (!output_file_player_) {
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::MixAudioWithFile() file mixing failed");
return -1;
}
// We should get the frequency we ask for.
if (output_file_player_->Get10msAudioFromFile(
fileBuffer.get(), &fileSamples, mixingFrequency) == -1) {
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::MixAudioWithFile() file mixing failed");
return -1;
}
}
if (audioFrame.samples_per_channel_ == fileSamples) {
// Currently file stream is always mono.
// TODO(xians): Change the code when FilePlayer supports real stereo.
MixWithSat(audioFrame.mutable_data(), audioFrame.num_channels_,
fileBuffer.get(), 1, fileSamples);
} else {
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::MixAudioWithFile() samples_per_channel_(%" PRIuS
") != "
"fileSamples(%" PRIuS ")",
audioFrame.samples_per_channel_, fileSamples);
return -1;
}
return 0;
}
void Channel::UpdatePlayoutTimestamp(bool rtcp) {
jitter_buffer_playout_timestamp_ = audio_coding_->PlayoutTimestamp();

View File

@ -32,8 +32,6 @@
#include "rtc_base/event.h"
#include "rtc_base/thread_checker.h"
#include "voice_engine/audio_level.h"
#include "voice_engine/file_player.h"
#include "voice_engine/file_recorder.h"
#include "voice_engine/include/voe_base.h"
#include "voice_engine/include/voe_network.h"
#include "voice_engine/shared_data.h"
@ -46,7 +44,6 @@ class TimestampWrapAroundHandler;
namespace webrtc {
class AudioDeviceModule;
class FileWrapper;
class PacketRouter;
class ProcessThread;
class RateLimiter;
@ -85,8 +82,6 @@ class VoERtcpObserver;
class ChannelState {
public:
struct State {
bool output_file_playing = false;
bool input_file_playing = false;
bool playing = false;
bool sending = false;
};
@ -104,16 +99,6 @@ class ChannelState {
return state_;
}
void SetOutputFilePlaying(bool enable) {
rtc::CritScope lock(&lock_);
state_.output_file_playing = enable;
}
void SetInputFilePlaying(bool enable) {
rtc::CritScope lock(&lock_);
state_.input_file_playing = enable;
}
void SetPlaying(bool enable) {
rtc::CritScope lock(&lock_);
state_.playing = enable;
@ -132,8 +117,6 @@ class ChannelState {
class Channel
: public RtpData,
public RtpFeedback,
public FileCallback, // receiving notification from file player &
// recorder
public Transport,
public AudioPacketizationCallback, // receive encoded packets from the
// ACM
@ -217,44 +200,6 @@ class Channel
int32_t ReceivedRTCPPacket(const uint8_t* data, size_t length);
void OnRtpPacket(const RtpPacketReceived& packet);
// VoEFile
int StartPlayingFileLocally(const char* fileName,
bool loop,
FileFormats format,
int startPosition,
float volumeScaling,
int stopPosition,
const CodecInst* codecInst);
int StartPlayingFileLocally(InStream* stream,
FileFormats format,
int startPosition,
float volumeScaling,
int stopPosition,
const CodecInst* codecInst);
int StopPlayingFileLocally();
int IsPlayingFileLocally() const;
int RegisterFilePlayingToMixer();
int StartPlayingFileAsMicrophone(const char* fileName,
bool loop,
FileFormats format,
int startPosition,
float volumeScaling,
int stopPosition,
const CodecInst* codecInst);
int StartPlayingFileAsMicrophone(InStream* stream,
FileFormats format,
int startPosition,
float volumeScaling,
int stopPosition,
const CodecInst* codecInst);
int StopPlayingFileAsMicrophone();
int IsPlayingFileAsMicrophone() const;
int StartRecordingPlayout(const char* fileName, const CodecInst* codecInst);
int StartRecordingPlayout(OutStream* stream, const CodecInst* codecInst);
int StopRecordingPlayout();
void SetMixWithMicStatus(bool mix);
// Muting, Volume and Level.
void SetInputMute(bool enable);
void SetChannelOutputVolumeScaling(float scaling);
@ -348,12 +293,6 @@ class Channel
int sample_rate_hz,
AudioFrame* audio_frame);
// From FileCallback
void PlayNotification(int32_t id, uint32_t durationMs) override;
void RecordNotification(int32_t id, uint32_t durationMs) override;
void PlayFileEnded(int32_t id) override;
void RecordFileEnded(int32_t id) override;
uint32_t InstanceId() const { return _instanceId; }
int32_t ChannelId() const { return _channelId; }
bool Playing() const { return channel_state_.Get().playing; }
@ -430,8 +369,6 @@ class Channel
bool IsPacketInOrder(const RTPHeader& header) const;
bool IsPacketRetransmitted(const RTPHeader& header, bool in_order) const;
int ResendPackets(const uint16_t* sequence_numbers, int length);
int32_t MixOrReplaceAudioWithFile(AudioFrame* audio_frame);
int32_t MixAudioWithFile(AudioFrame& audioFrame, int mixingFrequency);
void UpdatePlayoutTimestamp(bool rtcp);
void RegisterReceiveCodecsToRTPModule();
@ -452,7 +389,6 @@ class Channel
uint32_t _instanceId;
int32_t _channelId;
rtc::CriticalSection _fileCritSect;
rtc::CriticalSection _callbackCritSect;
rtc::CriticalSection volume_settings_critsect_;
@ -475,13 +411,6 @@ class Channel
bool _externalTransport;
// Downsamples to the codec rate if necessary.
PushResampler<int16_t> input_resampler_;
std::unique_ptr<FilePlayer> input_file_player_;
std::unique_ptr<FilePlayer> output_file_player_;
std::unique_ptr<FileRecorder> output_file_recorder_;
int _inputFilePlayerId;
int _outputFilePlayerId;
int _outputFileRecorderId;
bool _outputFileRecording;
uint32_t _timeStamp RTC_ACCESS_ON(encoder_queue_);
RemoteNtpTimeEstimator ntp_estimator_ RTC_GUARDED_BY(ts_stats_lock_);
@ -515,8 +444,6 @@ class Channel
bool input_mute_ RTC_GUARDED_BY(volume_settings_critsect_);
bool previous_frame_muted_ RTC_ACCESS_ON(encoder_queue_);
float _outputGain RTC_GUARDED_BY(volume_settings_critsect_);
// VoEBase
bool _mixFileWithMicrophone;
// VoeRTP_RTCP
// TODO(henrika): can today be accessed on the main thread and on the
// task queue; hence potential race.

View File

@ -1,118 +0,0 @@
/*
* 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 "voice_engine/coder.h"
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "common_types.h" // NOLINT(build/include)
#include "modules/audio_coding/codecs/audio_format_conversion.h"
#include "modules/include/module_common_types.h"
namespace webrtc {
namespace {
AudioCodingModule::Config GetAcmConfig(uint32_t id) {
AudioCodingModule::Config config;
// This class does not handle muted output.
config.neteq_config.enable_muted_state = false;
config.id = id;
config.decoder_factory = CreateBuiltinAudioDecoderFactory();
return config;
}
} // namespace
AudioCoder::AudioCoder(uint32_t instance_id)
: acm_(AudioCodingModule::Create(GetAcmConfig(instance_id))),
receive_codec_(),
encode_timestamp_(0),
encoded_data_(nullptr),
encoded_length_in_bytes_(0),
decode_timestamp_(0) {
acm_->InitializeReceiver();
acm_->RegisterTransportCallback(this);
}
AudioCoder::~AudioCoder() {}
int32_t AudioCoder::SetEncodeCodec(const CodecInst& codec_inst) {
const bool success = codec_manager_.RegisterEncoder(codec_inst) &&
codec_manager_.MakeEncoder(&rent_a_codec_, acm_.get());
return success ? 0 : -1;
}
int32_t AudioCoder::SetDecodeCodec(const CodecInst& codec_inst) {
if (!acm_->RegisterReceiveCodec(codec_inst.pltype,
CodecInstToSdp(codec_inst))) {
return -1;
}
memcpy(&receive_codec_, &codec_inst, sizeof(CodecInst));
return 0;
}
int32_t AudioCoder::Decode(AudioFrame* decoded_audio,
uint32_t samp_freq_hz,
const int8_t* incoming_payload,
size_t payload_length) {
if (payload_length > 0) {
const uint8_t payload_type = receive_codec_.pltype;
decode_timestamp_ += receive_codec_.pacsize;
if (acm_->IncomingPayload((const uint8_t*)incoming_payload, payload_length,
payload_type, decode_timestamp_) == -1) {
return -1;
}
}
bool muted;
int32_t ret =
acm_->PlayoutData10Ms((uint16_t)samp_freq_hz, decoded_audio, &muted);
RTC_DCHECK(!muted);
return ret;
}
int32_t AudioCoder::PlayoutData(AudioFrame* decoded_audio,
uint16_t samp_freq_hz) {
bool muted;
int32_t ret = acm_->PlayoutData10Ms(samp_freq_hz, decoded_audio, &muted);
RTC_DCHECK(!muted);
return ret;
}
int32_t AudioCoder::Encode(const AudioFrame& audio,
int8_t* encoded_data,
size_t* encoded_length_in_bytes) {
// Fake a timestamp in case audio doesn't contain a correct timestamp.
// Make a local copy of the audio frame since audio is const
AudioFrame audio_frame;
audio_frame.CopyFrom(audio);
audio_frame.timestamp_ = encode_timestamp_;
encode_timestamp_ += static_cast<uint32_t>(audio_frame.samples_per_channel_);
// For any codec with a frame size that is longer than 10 ms the encoded
// length in bytes should be zero until a a full frame has been encoded.
encoded_length_in_bytes_ = 0;
encoded_data_ = encoded_data;
if (acm_->Add10MsData((AudioFrame&)audio_frame) == -1) {
return -1;
}
*encoded_length_in_bytes = encoded_length_in_bytes_;
return 0;
}
int32_t AudioCoder::SendData(FrameType /* frame_type */,
uint8_t /* payload_type */,
uint32_t /* time_stamp */,
const uint8_t* payload_data,
size_t payload_size,
const RTPFragmentationHeader* /* fragmentation*/) {
memcpy(encoded_data_, payload_data, sizeof(uint8_t) * payload_size);
encoded_length_in_bytes_ = payload_size;
return 0;
}
} // namespace webrtc

View File

@ -1,68 +0,0 @@
/*
* Copyright (c) 2011 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.
*/
#ifndef VOICE_ENGINE_CODER_H_
#define VOICE_ENGINE_CODER_H_
#include <memory>
#include "common_types.h" // NOLINT(build/include)
#include "modules/audio_coding/acm2/codec_manager.h"
#include "modules/audio_coding/acm2/rent_a_codec.h"
#include "modules/audio_coding/include/audio_coding_module.h"
#include "typedefs.h" // NOLINT(build/include)
namespace webrtc {
class AudioFrame;
class AudioCoder : public AudioPacketizationCallback {
public:
explicit AudioCoder(uint32_t instance_id);
~AudioCoder();
int32_t SetEncodeCodec(const CodecInst& codec_inst);
int32_t SetDecodeCodec(const CodecInst& codec_inst);
int32_t Decode(AudioFrame* decoded_audio,
uint32_t samp_freq_hz,
const int8_t* incoming_payload,
size_t payload_length);
int32_t PlayoutData(AudioFrame* decoded_audio, uint16_t samp_freq_hz);
int32_t Encode(const AudioFrame& audio,
int8_t* encoded_data,
size_t* encoded_length_in_bytes);
protected:
int32_t SendData(FrameType frame_type,
uint8_t payload_type,
uint32_t time_stamp,
const uint8_t* payload_data,
size_t payload_size,
const RTPFragmentationHeader* fragmentation) override;
private:
std::unique_ptr<AudioCodingModule> acm_;
acm2::CodecManager codec_manager_;
acm2::RentACodec rent_a_codec_;
CodecInst receive_codec_;
uint32_t encode_timestamp_;
int8_t* encoded_data_;
size_t encoded_length_in_bytes_;
uint32_t decode_timestamp_;
};
} // namespace webrtc
#endif // VOICE_ENGINE_CODER_H_

View File

@ -1,397 +0,0 @@
/*
* 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 "voice_engine/file_player.h"
#include "common_audio/resampler/include/resampler.h"
#include "common_types.h" // NOLINT(build/include)
#include "modules/media_file/media_file.h"
#include "modules/media_file/media_file_defines.h"
#include "rtc_base/logging.h"
#include "typedefs.h" // NOLINT(build/include)
#include "voice_engine/coder.h"
namespace webrtc {
namespace {
class FilePlayerImpl : public FilePlayer {
public:
FilePlayerImpl(uint32_t instanceID, FileFormats fileFormat);
~FilePlayerImpl() override;
int Get10msAudioFromFile(int16_t* outBuffer,
size_t* lengthInSamples,
int frequencyInHz) override;
int32_t RegisterModuleFileCallback(FileCallback* callback) override;
int32_t StartPlayingFile(const char* fileName,
bool loop,
uint32_t startPosition,
float volumeScaling,
uint32_t notification,
uint32_t stopPosition,
const CodecInst* codecInst) override;
int32_t StartPlayingFile(InStream* sourceStream,
uint32_t startPosition,
float volumeScaling,
uint32_t notification,
uint32_t stopPosition,
const CodecInst* codecInst) override;
int32_t StopPlayingFile() override;
bool IsPlayingFile() const override;
int32_t GetPlayoutPosition(uint32_t* durationMs) override;
int32_t AudioCodec(CodecInst* audioCodec) const override;
int32_t Frequency() const override;
int32_t SetAudioScaling(float scaleFactor) override;
private:
int32_t SetUpAudioDecoder();
const FileFormats _fileFormat;
MediaFile& _fileModule;
uint32_t _decodedLengthInMS;
AudioCoder _audioDecoder;
CodecInst _codec;
int32_t _numberOf10MsPerFrame;
int32_t _numberOf10MsInDecoder;
Resampler _resampler;
float _scaling;
};
FilePlayerImpl::FilePlayerImpl(const uint32_t instanceID,
const FileFormats fileFormat)
: _fileFormat(fileFormat),
_fileModule(*MediaFile::CreateMediaFile(instanceID)),
_decodedLengthInMS(0),
_audioDecoder(instanceID),
_codec(),
_numberOf10MsPerFrame(0),
_numberOf10MsInDecoder(0),
_resampler(),
_scaling(1.0) {
_codec.plfreq = 0;
}
FilePlayerImpl::~FilePlayerImpl() {
MediaFile::DestroyMediaFile(&_fileModule);
}
int32_t FilePlayerImpl::Frequency() const {
if (_codec.plfreq == 0) {
return -1;
}
// Make sure that sample rate is 8,16 or 32 kHz. E.g. WAVE files may have
// other sampling rates.
if (_codec.plfreq == 11000) {
return 16000;
} else if (_codec.plfreq == 22000) {
return 32000;
} else if (_codec.plfreq == 44000) {
return 32000;
} else if (_codec.plfreq == 48000) {
return 48000;
} else {
return _codec.plfreq;
}
}
int32_t FilePlayerImpl::AudioCodec(CodecInst* audioCodec) const {
*audioCodec = _codec;
return 0;
}
int32_t FilePlayerImpl::Get10msAudioFromFile(int16_t* outBuffer,
size_t* lengthInSamples,
int frequencyInHz) {
if (_codec.plfreq == 0) {
LOG(LS_WARNING) << "Get10msAudioFromFile() playing not started!"
<< " codec freq = " << _codec.plfreq
<< ", wanted freq = " << frequencyInHz;
return -1;
}
AudioFrame unresampledAudioFrame;
if (STR_CASE_CMP(_codec.plname, "L16") == 0) {
unresampledAudioFrame.sample_rate_hz_ = _codec.plfreq;
// L16 is un-encoded data. Just pull 10 ms.
size_t lengthInBytes = AudioFrame::kMaxDataSizeBytes;
if (_fileModule.PlayoutAudioData(
reinterpret_cast<int8_t*>(unresampledAudioFrame.mutable_data()),
lengthInBytes) == -1) {
// End of file reached.
return -1;
}
if (lengthInBytes == 0) {
*lengthInSamples = 0;
return 0;
}
// One sample is two bytes.
unresampledAudioFrame.samples_per_channel_ = lengthInBytes >> 1;
} else {
// Decode will generate 10 ms of audio data. PlayoutAudioData(..)
// expects a full frame. If the frame size is larger than 10 ms,
// PlayoutAudioData(..) data should be called proportionally less often.
int16_t encodedBuffer[MAX_AUDIO_BUFFER_IN_SAMPLES];
size_t encodedLengthInBytes = 0;
if (++_numberOf10MsInDecoder >= _numberOf10MsPerFrame) {
_numberOf10MsInDecoder = 0;
size_t bytesFromFile = sizeof(encodedBuffer);
if (_fileModule.PlayoutAudioData(reinterpret_cast<int8_t*>(encodedBuffer),
bytesFromFile) == -1) {
// End of file reached.
return -1;
}
encodedLengthInBytes = bytesFromFile;
}
if (_audioDecoder.Decode(&unresampledAudioFrame, frequencyInHz,
reinterpret_cast<int8_t*>(encodedBuffer),
encodedLengthInBytes) == -1) {
return -1;
}
}
size_t outLen = 0;
if (_resampler.ResetIfNeeded(unresampledAudioFrame.sample_rate_hz_,
frequencyInHz, 1)) {
LOG(LS_WARNING) << "Get10msAudioFromFile() unexpected codec.";
// New sampling frequency. Update state.
outLen = static_cast<size_t>(frequencyInHz / 100);
memset(outBuffer, 0, outLen * sizeof(int16_t));
return 0;
}
_resampler.Push(unresampledAudioFrame.data(),
unresampledAudioFrame.samples_per_channel_, outBuffer,
MAX_AUDIO_BUFFER_IN_SAMPLES, outLen);
*lengthInSamples = outLen;
if (_scaling != 1.0) {
for (size_t i = 0; i < outLen; i++) {
outBuffer[i] = (int16_t)(outBuffer[i] * _scaling);
}
}
_decodedLengthInMS += 10;
return 0;
}
int32_t FilePlayerImpl::RegisterModuleFileCallback(FileCallback* callback) {
return _fileModule.SetModuleFileCallback(callback);
}
int32_t FilePlayerImpl::SetAudioScaling(float scaleFactor) {
if ((scaleFactor >= 0) && (scaleFactor <= 2.0)) {
_scaling = scaleFactor;
return 0;
}
LOG(LS_WARNING) << "SetAudioScaling() non-allowed scale factor.";
return -1;
}
int32_t FilePlayerImpl::StartPlayingFile(const char* fileName,
bool loop,
uint32_t startPosition,
float volumeScaling,
uint32_t notification,
uint32_t stopPosition,
const CodecInst* codecInst) {
if (_fileFormat == kFileFormatPcm16kHzFile ||
_fileFormat == kFileFormatPcm8kHzFile ||
_fileFormat == kFileFormatPcm32kHzFile) {
CodecInst codecInstL16;
strncpy(codecInstL16.plname, "L16", 32);
codecInstL16.pltype = 93;
codecInstL16.channels = 1;
if (_fileFormat == kFileFormatPcm8kHzFile) {
codecInstL16.rate = 128000;
codecInstL16.plfreq = 8000;
codecInstL16.pacsize = 80;
} else if (_fileFormat == kFileFormatPcm16kHzFile) {
codecInstL16.rate = 256000;
codecInstL16.plfreq = 16000;
codecInstL16.pacsize = 160;
} else if (_fileFormat == kFileFormatPcm32kHzFile) {
codecInstL16.rate = 512000;
codecInstL16.plfreq = 32000;
codecInstL16.pacsize = 320;
} else if (_fileFormat == kFileFormatPcm48kHzFile) {
codecInstL16.rate = 768000;
codecInstL16.plfreq = 48000;
codecInstL16.pacsize = 480;
} else {
LOG(LS_ERROR) << "StartPlayingFile() sample frequency not "
<< "supported for PCM format.";
return -1;
}
if (_fileModule.StartPlayingAudioFile(fileName, notification, loop,
_fileFormat, &codecInstL16,
startPosition, stopPosition) == -1) {
LOG(LS_WARNING) << "StartPlayingFile() failed to initialize "
<< "pcm file " << fileName;
return -1;
}
SetAudioScaling(volumeScaling);
} else if (_fileFormat == kFileFormatPreencodedFile) {
if (_fileModule.StartPlayingAudioFile(fileName, notification, loop,
_fileFormat, codecInst) == -1) {
LOG(LS_WARNING) << "StartPlayingFile() failed to initialize "
<< "pre-encoded file " << fileName;
return -1;
}
} else {
CodecInst* no_inst = NULL;
if (_fileModule.StartPlayingAudioFile(fileName, notification, loop,
_fileFormat, no_inst, startPosition,
stopPosition) == -1) {
LOG(LS_WARNING) << "StartPlayingFile() failed to initialize file "
<< fileName;
return -1;
}
SetAudioScaling(volumeScaling);
}
if (SetUpAudioDecoder() == -1) {
StopPlayingFile();
return -1;
}
return 0;
}
int32_t FilePlayerImpl::StartPlayingFile(InStream* sourceStream,
uint32_t startPosition,
float volumeScaling,
uint32_t notification,
uint32_t stopPosition,
const CodecInst* codecInst) {
if (_fileFormat == kFileFormatPcm16kHzFile ||
_fileFormat == kFileFormatPcm32kHzFile ||
_fileFormat == kFileFormatPcm8kHzFile ||
_fileFormat == kFileFormatPcm48kHzFile) {
CodecInst codecInstL16;
strncpy(codecInstL16.plname, "L16", 32);
codecInstL16.pltype = 93;
codecInstL16.channels = 1;
if (_fileFormat == kFileFormatPcm8kHzFile) {
codecInstL16.rate = 128000;
codecInstL16.plfreq = 8000;
codecInstL16.pacsize = 80;
} else if (_fileFormat == kFileFormatPcm16kHzFile) {
codecInstL16.rate = 256000;
codecInstL16.plfreq = 16000;
codecInstL16.pacsize = 160;
} else if (_fileFormat == kFileFormatPcm32kHzFile) {
codecInstL16.rate = 512000;
codecInstL16.plfreq = 32000;
codecInstL16.pacsize = 320;
} else if (_fileFormat == kFileFormatPcm48kHzFile) {
codecInstL16.rate = 768000;
codecInstL16.plfreq = 48000;
codecInstL16.pacsize = 480;
} else {
LOG(LS_ERROR) << "StartPlayingFile() sample frequency not "
<< "supported for PCM format.";
return -1;
}
if (_fileModule.StartPlayingAudioStream(
*sourceStream, notification, _fileFormat, &codecInstL16,
startPosition, stopPosition) == -1) {
LOG(LS_ERROR) << "StartPlayingFile() failed to initialize stream "
<< "playout.";
return -1;
}
} else if (_fileFormat == kFileFormatPreencodedFile) {
if (_fileModule.StartPlayingAudioStream(*sourceStream, notification,
_fileFormat, codecInst) == -1) {
LOG(LS_ERROR) << "StartPlayingFile() failed to initialize stream "
<< "playout.";
return -1;
}
} else {
CodecInst* no_inst = NULL;
if (_fileModule.StartPlayingAudioStream(*sourceStream, notification,
_fileFormat, no_inst, startPosition,
stopPosition) == -1) {
LOG(LS_ERROR) << "StartPlayingFile() failed to initialize stream "
<< "playout.";
return -1;
}
}
SetAudioScaling(volumeScaling);
if (SetUpAudioDecoder() == -1) {
StopPlayingFile();
return -1;
}
return 0;
}
int32_t FilePlayerImpl::StopPlayingFile() {
memset(&_codec, 0, sizeof(CodecInst));
_numberOf10MsPerFrame = 0;
_numberOf10MsInDecoder = 0;
return _fileModule.StopPlaying();
}
bool FilePlayerImpl::IsPlayingFile() const {
return _fileModule.IsPlaying();
}
int32_t FilePlayerImpl::GetPlayoutPosition(uint32_t* durationMs) {
return _fileModule.PlayoutPositionMs(*durationMs);
}
int32_t FilePlayerImpl::SetUpAudioDecoder() {
if ((_fileModule.codec_info(_codec) == -1)) {
LOG(LS_WARNING) << "Failed to retrieve codec info of file data.";
return -1;
}
if (STR_CASE_CMP(_codec.plname, "L16") != 0 &&
_audioDecoder.SetDecodeCodec(_codec) == -1) {
LOG(LS_WARNING) << "SetUpAudioDecoder() codec " << _codec.plname
<< " not supported.";
return -1;
}
_numberOf10MsPerFrame = _codec.pacsize / (_codec.plfreq / 100);
_numberOf10MsInDecoder = 0;
return 0;
}
} // namespace
std::unique_ptr<FilePlayer> FilePlayer::CreateFilePlayer(
uint32_t instanceID,
FileFormats fileFormat) {
switch (fileFormat) {
case kFileFormatWavFile:
case kFileFormatCompressedFile:
case kFileFormatPreencodedFile:
case kFileFormatPcm16kHzFile:
case kFileFormatPcm8kHzFile:
case kFileFormatPcm32kHzFile:
case kFileFormatPcm48kHzFile:
// audio formats
return std::unique_ptr<FilePlayer>(
new FilePlayerImpl(instanceID, fileFormat));
default:
assert(false);
return nullptr;
}
}
} // namespace webrtc

View File

@ -1,80 +0,0 @@
/*
* 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.
*/
#ifndef VOICE_ENGINE_FILE_PLAYER_H_
#define VOICE_ENGINE_FILE_PLAYER_H_
#include <memory>
#include "common_types.h" // NOLINT(build/include)
#include "modules/include/module_common_types.h"
#include "typedefs.h" // NOLINT(build/include)
namespace webrtc {
class FileCallback;
class FilePlayer {
public:
// The largest decoded frame size in samples (60ms with 48kHz sample rate).
enum { MAX_AUDIO_BUFFER_IN_SAMPLES = 60 * 48 };
enum { MAX_AUDIO_BUFFER_IN_BYTES = MAX_AUDIO_BUFFER_IN_SAMPLES * 2 };
// Note: will return NULL for unsupported formats.
static std::unique_ptr<FilePlayer> CreateFilePlayer(
const uint32_t instanceID,
const FileFormats fileFormat);
virtual ~FilePlayer() = default;
// Read 10 ms of audio at |frequencyInHz| to |outBuffer|. |lengthInSamples|
// will be set to the number of samples read (not the number of samples per
// channel).
virtual int Get10msAudioFromFile(int16_t* outBuffer,
size_t* lengthInSamples,
int frequencyInHz) = 0;
// Register callback for receiving file playing notifications.
virtual int32_t RegisterModuleFileCallback(FileCallback* callback) = 0;
// API for playing audio from fileName to channel.
// Note: codecInst is used for pre-encoded files.
virtual int32_t StartPlayingFile(const char* fileName,
bool loop,
uint32_t startPosition,
float volumeScaling,
uint32_t notification,
uint32_t stopPosition,
const CodecInst* codecInst) = 0;
// Note: codecInst is used for pre-encoded files.
virtual int32_t StartPlayingFile(InStream* sourceStream,
uint32_t startPosition,
float volumeScaling,
uint32_t notification,
uint32_t stopPosition,
const CodecInst* codecInst) = 0;
virtual int32_t StopPlayingFile() = 0;
virtual bool IsPlayingFile() const = 0;
virtual int32_t GetPlayoutPosition(uint32_t* durationMs) = 0;
// Set audioCodec to the currently used audio codec.
virtual int32_t AudioCodec(CodecInst* audioCodec) const = 0;
virtual int32_t Frequency() const = 0;
// Note: scaleFactor is in the range [0.0 - 2.0]
virtual int32_t SetAudioScaling(float scaleFactor) = 0;
};
} // namespace webrtc
#endif // VOICE_ENGINE_FILE_PLAYER_H_

View File

@ -1,115 +0,0 @@
/*
* Copyright (c) 2014 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.
*/
// Unit tests for FilePlayer.
#include "voice_engine/file_player.h"
#include <stdio.h>
#include <memory>
#include <string>
#include "rtc_base/flags.h"
#include "rtc_base/md5digest.h"
#include "rtc_base/stringencode.h"
#include "test/gtest.h"
#include "test/testsupport/fileutils.h"
DEFINE_bool(file_player_output, false, "Generate reference files.");
namespace webrtc {
class FilePlayerTest : public ::testing::Test {
protected:
static const uint32_t kId = 0;
static const FileFormats kFileFormat = kFileFormatWavFile;
static const int kSampleRateHz = 8000;
FilePlayerTest()
: player_(FilePlayer::CreateFilePlayer(kId, kFileFormat)),
output_file_(NULL) {}
void SetUp() override {
if (FLAG_file_player_output) {
std::string output_file =
webrtc::test::OutputPath() + "file_player_unittest_out.pcm";
output_file_ = fopen(output_file.c_str(), "wb");
ASSERT_TRUE(output_file_ != NULL);
}
}
void TearDown() override {
if (output_file_)
fclose(output_file_);
}
void PlayFileAndCheck(const std::string& input_file,
const std::string& ref_checksum,
int output_length_ms) {
const float kScaling = 1;
ASSERT_EQ(0, player_->StartPlayingFile(input_file.c_str(), false, 0,
kScaling, 0, 0, NULL));
rtc::Md5Digest checksum;
for (int i = 0; i < output_length_ms / 10; ++i) {
int16_t out[10 * kSampleRateHz / 1000] = {0};
size_t num_samples;
EXPECT_EQ(
0, player_->Get10msAudioFromFile(out, &num_samples, kSampleRateHz));
checksum.Update(out, num_samples * sizeof(out[0]));
if (FLAG_file_player_output) {
ASSERT_EQ(num_samples,
fwrite(out, sizeof(out[0]), num_samples, output_file_));
}
}
char checksum_result[rtc::Md5Digest::kSize];
EXPECT_EQ(rtc::Md5Digest::kSize,
checksum.Finish(checksum_result, rtc::Md5Digest::kSize));
EXPECT_EQ(ref_checksum,
rtc::hex_encode(checksum_result, sizeof(checksum_result)));
}
std::unique_ptr<FilePlayer> player_;
FILE* output_file_;
};
#if defined(WEBRTC_IOS)
#define MAYBE_PlayWavPcmuFile DISABLED_PlayWavPcmuFile
#else
#define MAYBE_PlayWavPcmuFile PlayWavPcmuFile
#endif
TEST_F(FilePlayerTest, MAYBE_PlayWavPcmuFile) {
const std::string kFileName =
test::ResourcePath("utility/encapsulated_pcmu_8khz", "wav");
// The file is longer than this, but keeping the output shorter limits the
// runtime for the test.
const int kOutputLengthMs = 10000;
const std::string kRefChecksum = "c74e7fd432d439b1311e1c16815b3e9a";
PlayFileAndCheck(kFileName, kRefChecksum, kOutputLengthMs);
}
#if defined(WEBRTC_IOS)
#define MAYBE_PlayWavPcm16File DISABLED_PlayWavPcm16File
#else
#define MAYBE_PlayWavPcm16File PlayWavPcm16File
#endif
TEST_F(FilePlayerTest, MAYBE_PlayWavPcm16File) {
const std::string kFileName =
test::ResourcePath("utility/encapsulated_pcm16b_8khz", "wav");
// The file is longer than this, but keeping the output shorter limits the
// runtime for the test.
const int kOutputLengthMs = 10000;
const std::string kRefChecksum = "e41d7e1dac8aeae9f21e8e03cd7ecd71";
PlayFileAndCheck(kFileName, kRefChecksum, kOutputLengthMs);
}
} // namespace webrtc

View File

@ -1,260 +0,0 @@
/*
* 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 "voice_engine/file_recorder.h"
#include <list>
#include "audio/utility/audio_frame_operations.h"
#include "common_audio/resampler/include/resampler.h"
#include "common_types.h" // NOLINT(build/include)
#include "modules/include/module_common_types.h"
#include "modules/media_file/media_file.h"
#include "modules/media_file/media_file_defines.h"
#include "rtc_base/logging.h"
#include "rtc_base/platform_thread.h"
#include "system_wrappers/include/event_wrapper.h"
#include "typedefs.h" // NOLINT(build/include)
#include "voice_engine/coder.h"
namespace webrtc {
namespace {
// The largest decoded frame size in samples (60ms with 32kHz sample rate).
enum { MAX_AUDIO_BUFFER_IN_SAMPLES = 60 * 32 };
enum { MAX_AUDIO_BUFFER_IN_BYTES = MAX_AUDIO_BUFFER_IN_SAMPLES * 2 };
enum { kMaxAudioBufferQueueLength = 100 };
class FileRecorderImpl : public FileRecorder {
public:
FileRecorderImpl(uint32_t instanceID, FileFormats fileFormat);
~FileRecorderImpl() override;
// FileRecorder functions.
int32_t RegisterModuleFileCallback(FileCallback* callback) override;
FileFormats RecordingFileFormat() const override;
int32_t StartRecordingAudioFile(const char* fileName,
const CodecInst& codecInst,
uint32_t notificationTimeMs) override;
int32_t StartRecordingAudioFile(OutStream* destStream,
const CodecInst& codecInst,
uint32_t notificationTimeMs) override;
int32_t StopRecording() override;
bool IsRecording() const override;
int32_t codec_info(CodecInst* codecInst) const override;
int32_t RecordAudioToFile(const AudioFrame& frame) override;
private:
int32_t WriteEncodedAudioData(const int8_t* audioBuffer, size_t bufferLength);
int32_t SetUpAudioEncoder();
uint32_t _instanceID;
FileFormats _fileFormat;
MediaFile* _moduleFile;
CodecInst codec_info_;
int8_t _audioBuffer[MAX_AUDIO_BUFFER_IN_BYTES];
AudioCoder _audioEncoder;
Resampler _audioResampler;
};
FileRecorderImpl::FileRecorderImpl(uint32_t instanceID, FileFormats fileFormat)
: _instanceID(instanceID),
_fileFormat(fileFormat),
_moduleFile(MediaFile::CreateMediaFile(_instanceID)),
codec_info_(),
_audioBuffer(),
_audioEncoder(instanceID),
_audioResampler() {}
FileRecorderImpl::~FileRecorderImpl() {
MediaFile::DestroyMediaFile(_moduleFile);
}
FileFormats FileRecorderImpl::RecordingFileFormat() const {
return _fileFormat;
}
int32_t FileRecorderImpl::RegisterModuleFileCallback(FileCallback* callback) {
if (_moduleFile == NULL) {
return -1;
}
return _moduleFile->SetModuleFileCallback(callback);
}
int32_t FileRecorderImpl::StartRecordingAudioFile(const char* fileName,
const CodecInst& codecInst,
uint32_t notificationTimeMs) {
if (_moduleFile == NULL) {
return -1;
}
codec_info_ = codecInst;
int32_t retVal = 0;
retVal = _moduleFile->StartRecordingAudioFile(fileName, _fileFormat,
codecInst, notificationTimeMs);
if (retVal == 0) {
retVal = SetUpAudioEncoder();
}
if (retVal != 0) {
LOG(LS_WARNING) << "Failed to initialize file " << fileName
<< " for recording.";
if (IsRecording()) {
StopRecording();
}
}
return retVal;
}
int32_t FileRecorderImpl::StartRecordingAudioFile(OutStream* destStream,
const CodecInst& codecInst,
uint32_t notificationTimeMs) {
codec_info_ = codecInst;
int32_t retVal = _moduleFile->StartRecordingAudioStream(
*destStream, _fileFormat, codecInst, notificationTimeMs);
if (retVal == 0) {
retVal = SetUpAudioEncoder();
}
if (retVal != 0) {
LOG(LS_WARNING) << "Failed to initialize outStream for recording.";
if (IsRecording()) {
StopRecording();
}
}
return retVal;
}
int32_t FileRecorderImpl::StopRecording() {
memset(&codec_info_, 0, sizeof(CodecInst));
return _moduleFile->StopRecording();
}
bool FileRecorderImpl::IsRecording() const {
return _moduleFile->IsRecording();
}
int32_t FileRecorderImpl::RecordAudioToFile(
const AudioFrame& incomingAudioFrame) {
if (codec_info_.plfreq == 0) {
LOG(LS_WARNING) << "RecordAudioToFile() recording audio is not "
<< "turned on.";
return -1;
}
AudioFrame tempAudioFrame;
tempAudioFrame.samples_per_channel_ = 0;
if (incomingAudioFrame.num_channels_ == 2 && !_moduleFile->IsStereo()) {
// Recording mono but incoming audio is (interleaved) stereo.
tempAudioFrame.num_channels_ = 1;
tempAudioFrame.sample_rate_hz_ = incomingAudioFrame.sample_rate_hz_;
tempAudioFrame.samples_per_channel_ =
incomingAudioFrame.samples_per_channel_;
if (!incomingAudioFrame.muted()) {
AudioFrameOperations::StereoToMono(
incomingAudioFrame.data(), incomingAudioFrame.samples_per_channel_,
tempAudioFrame.mutable_data());
}
} else if (incomingAudioFrame.num_channels_ == 1 && _moduleFile->IsStereo()) {
// Recording stereo but incoming audio is mono.
tempAudioFrame.num_channels_ = 2;
tempAudioFrame.sample_rate_hz_ = incomingAudioFrame.sample_rate_hz_;
tempAudioFrame.samples_per_channel_ =
incomingAudioFrame.samples_per_channel_;
if (!incomingAudioFrame.muted()) {
AudioFrameOperations::MonoToStereo(
incomingAudioFrame.data(), incomingAudioFrame.samples_per_channel_,
tempAudioFrame.mutable_data());
}
}
const AudioFrame* ptrAudioFrame = &incomingAudioFrame;
if (tempAudioFrame.samples_per_channel_ != 0) {
// If ptrAudioFrame is not empty it contains the audio to be recorded.
ptrAudioFrame = &tempAudioFrame;
}
// Encode the audio data before writing to file. Don't encode if the codec
// is PCM.
// NOTE: stereo recording is only supported for WAV files.
// TODO(hellner): WAV expect PCM in little endian byte order. Not
// "encoding" with PCM coder should be a problem for big endian systems.
size_t encodedLenInBytes = 0;
if (_fileFormat == kFileFormatPreencodedFile ||
STR_CASE_CMP(codec_info_.plname, "L16") != 0) {
if (_audioEncoder.Encode(*ptrAudioFrame, _audioBuffer,
&encodedLenInBytes) == -1) {
LOG(LS_WARNING) << "RecordAudioToFile() codec " << codec_info_.plname
<< " not supported or failed to encode stream.";
return -1;
}
} else {
size_t outLen = 0;
_audioResampler.ResetIfNeeded(ptrAudioFrame->sample_rate_hz_,
codec_info_.plfreq,
ptrAudioFrame->num_channels_);
// TODO(yujo): skip resample if frame is muted.
_audioResampler.Push(
ptrAudioFrame->data(),
ptrAudioFrame->samples_per_channel_ * ptrAudioFrame->num_channels_,
reinterpret_cast<int16_t*>(_audioBuffer), MAX_AUDIO_BUFFER_IN_BYTES,
outLen);
encodedLenInBytes = outLen * sizeof(int16_t);
}
// Codec may not be operating at a frame rate of 10 ms. Whenever enough
// 10 ms chunks of data has been pushed to the encoder an encoded frame
// will be available. Wait until then.
if (encodedLenInBytes) {
if (WriteEncodedAudioData(_audioBuffer, encodedLenInBytes) == -1) {
return -1;
}
}
return 0;
}
int32_t FileRecorderImpl::SetUpAudioEncoder() {
if (_fileFormat == kFileFormatPreencodedFile ||
STR_CASE_CMP(codec_info_.plname, "L16") != 0) {
if (_audioEncoder.SetEncodeCodec(codec_info_) == -1) {
LOG(LS_ERROR) << "SetUpAudioEncoder() codec " << codec_info_.plname
<< " not supported.";
return -1;
}
}
return 0;
}
int32_t FileRecorderImpl::codec_info(CodecInst* codecInst) const {
if (codec_info_.plfreq == 0) {
return -1;
}
*codecInst = codec_info_;
return 0;
}
int32_t FileRecorderImpl::WriteEncodedAudioData(const int8_t* audioBuffer,
size_t bufferLength) {
return _moduleFile->IncomingAudioData(audioBuffer, bufferLength);
}
} // namespace
std::unique_ptr<FileRecorder> FileRecorder::CreateFileRecorder(
uint32_t instanceID,
FileFormats fileFormat) {
return std::unique_ptr<FileRecorder>(
new FileRecorderImpl(instanceID, fileFormat));
}
} // namespace webrtc

View File

@ -1,57 +0,0 @@
/*
* 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.
*/
#ifndef VOICE_ENGINE_FILE_RECORDER_H_
#define VOICE_ENGINE_FILE_RECORDER_H_
#include <memory>
#include "common_types.h" // NOLINT(build/include)
#include "modules/include/module_common_types.h"
#include "modules/media_file/media_file_defines.h"
#include "typedefs.h" // NOLINT(build/include)
namespace webrtc {
class FileRecorder {
public:
// Note: will return NULL for unsupported formats.
static std::unique_ptr<FileRecorder> CreateFileRecorder(
const uint32_t instanceID,
const FileFormats fileFormat);
virtual ~FileRecorder() = default;
virtual int32_t RegisterModuleFileCallback(FileCallback* callback) = 0;
virtual FileFormats RecordingFileFormat() const = 0;
virtual int32_t StartRecordingAudioFile(const char* fileName,
const CodecInst& codecInst,
uint32_t notification) = 0;
virtual int32_t StartRecordingAudioFile(OutStream* destStream,
const CodecInst& codecInst,
uint32_t notification) = 0;
// Stop recording.
virtual int32_t StopRecording() = 0;
// Return true if recording.
virtual bool IsRecording() const = 0;
virtual int32_t codec_info(CodecInst* codecInst) const = 0;
// Write frame to file. Frame should contain 10ms of un-ecoded audio data.
virtual int32_t RecordAudioToFile(const AudioFrame& frame) = 0;
};
} // namespace webrtc
#endif // VOICE_ENGINE_FILE_RECORDER_H_

View File

@ -1,144 +0,0 @@
/*
* Copyright (c) 2011 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.
*/
// This sub-API supports the following functionalities:
//
// - File playback.
// - File recording.
// - File conversion.
//
// Usage example, omitting error checking:
//
// using namespace webrtc;
// VoiceEngine* voe = VoiceEngine::Create();
// VoEBase* base = VoEBase::GetInterface(voe);
// VoEFile* file = VoEFile::GetInterface(voe);
// base->Init();
// int ch = base->CreateChannel();
// ...
// base->StartPlayout(ch);
// file->StartPlayingFileAsMicrophone(ch, "data_file_16kHz.pcm", true);
// ...
// file->StopPlayingFileAsMicrophone(ch);
// base->StopPlayout(ch);
// ...
// base->DeleteChannel(ch);
// base->Terminate();
// base->Release();
// file->Release();
// VoiceEngine::Delete(voe);
//
#ifndef VOICE_ENGINE_VOE_FILE_H_
#define VOICE_ENGINE_VOE_FILE_H_
#include "common_types.h" // NOLINT(build/include)
namespace webrtc {
class VoiceEngine;
class WEBRTC_DLLEXPORT VoEFile {
public:
// Factory for the VoEFile sub-API. Increases an internal
// reference counter if successful. Returns NULL if the API is not
// supported or if construction fails.
static VoEFile* GetInterface(VoiceEngine* voiceEngine);
// Releases the VoEFile sub-API and decreases an internal
// reference counter. Returns the new reference count. This value should
// be zero for all sub-API:s before the VoiceEngine object can be safely
// deleted.
virtual int Release() = 0;
// Starts playing and mixing files with the local speaker signal for
// playout.
virtual int StartPlayingFileLocally(
int channel,
const char fileNameUTF8[1024],
bool loop = false,
FileFormats format = kFileFormatPcm16kHzFile,
float volumeScaling = 1.0,
int startPointMs = 0,
int stopPointMs = 0) = 0;
// Starts playing and mixing streams with the local speaker signal for
// playout.
virtual int StartPlayingFileLocally(
int channel,
InStream* stream,
FileFormats format = kFileFormatPcm16kHzFile,
float volumeScaling = 1.0,
int startPointMs = 0,
int stopPointMs = 0) = 0;
// Stops playback of a file on a specific |channel|.
virtual int StopPlayingFileLocally(int channel) = 0;
// Returns the current file playing state for a specific |channel|.
virtual int IsPlayingFileLocally(int channel) = 0;
// Starts reading data from a file and transmits the data either
// mixed with or instead of the microphone signal.
virtual int StartPlayingFileAsMicrophone(
int channel,
const char fileNameUTF8[1024],
bool loop = false,
bool mixWithMicrophone = false,
FileFormats format = kFileFormatPcm16kHzFile,
float volumeScaling = 1.0) = 0;
// Starts reading data from a stream and transmits the data either
// mixed with or instead of the microphone signal.
virtual int StartPlayingFileAsMicrophone(
int channel,
InStream* stream,
bool mixWithMicrophone = false,
FileFormats format = kFileFormatPcm16kHzFile,
float volumeScaling = 1.0) = 0;
// Stops playing of a file as microphone signal for a specific |channel|.
virtual int StopPlayingFileAsMicrophone(int channel) = 0;
// Returns whether the |channel| is currently playing a file as microphone.
virtual int IsPlayingFileAsMicrophone(int channel) = 0;
// Starts recording the mixed playout audio.
virtual int StartRecordingPlayout(int channel,
const char* fileNameUTF8,
CodecInst* compression = NULL,
int maxSizeBytes = -1) = 0;
// Stops recording the mixed playout audio.
virtual int StopRecordingPlayout(int channel) = 0;
virtual int StartRecordingPlayout(int channel,
OutStream* stream,
CodecInst* compression = NULL) = 0;
// Starts recording the microphone signal to a file.
virtual int StartRecordingMicrophone(const char* fileNameUTF8,
CodecInst* compression = NULL,
int maxSizeBytes = -1) = 0;
// Starts recording the microphone signal to a stream.
virtual int StartRecordingMicrophone(OutStream* stream,
CodecInst* compression = NULL) = 0;
// Stops recording the microphone signal.
virtual int StopRecordingMicrophone() = 0;
protected:
VoEFile() {}
virtual ~VoEFile() {}
};
} // namespace webrtc
#endif // VOICE_ENGINE_VOE_FILE_H_

View File

@ -12,7 +12,6 @@
#include "modules/audio_processing/include/audio_processing.h"
#include "rtc_base/format_macros.h"
#include "system_wrappers/include/file_wrapper.h"
#include "system_wrappers/include/trace.h"
#include "voice_engine/statistics.h"
#include "voice_engine/utility.h"
@ -33,45 +32,6 @@ OutputMixer::NewMixedAudio(int32_t id,
_audioFrame.id_ = id;
}
void OutputMixer::PlayNotification(int32_t id, uint32_t durationMs)
{
WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,-1),
"OutputMixer::PlayNotification(id=%d, durationMs=%d)",
id, durationMs);
// Not implement yet
}
void OutputMixer::RecordNotification(int32_t id,
uint32_t durationMs)
{
WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,-1),
"OutputMixer::RecordNotification(id=%d, durationMs=%d)",
id, durationMs);
// Not implement yet
}
void OutputMixer::PlayFileEnded(int32_t id)
{
WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,-1),
"OutputMixer::PlayFileEnded(id=%d)", id);
// not needed
}
void OutputMixer::RecordFileEnded(int32_t id)
{
WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,-1),
"OutputMixer::RecordFileEnded(id=%d)", id);
assert(id == _instanceId);
rtc::CritScope cs(&_fileCritSect);
_outputFileRecording = false;
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
"OutputMixer::RecordFileEnded() =>"
"output file recorder module is shutdown");
}
int32_t
OutputMixer::Create(OutputMixer*& mixer, uint32_t instanceId)
{
@ -91,8 +51,7 @@ OutputMixer::Create(OutputMixer*& mixer, uint32_t instanceId)
OutputMixer::OutputMixer(uint32_t instanceId) :
_mixerModule(*AudioConferenceMixer::Create(instanceId)),
_instanceId(instanceId),
_mixingFrequencyHz(8000),
_outputFileRecording(false)
_mixingFrequencyHz(8000)
{
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,-1),
"OutputMixer::OutputMixer() - ctor");
@ -119,13 +78,6 @@ OutputMixer::~OutputMixer()
{
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,-1),
"OutputMixer::~OutputMixer() - dtor");
{
rtc::CritScope cs(&_fileCritSect);
if (output_file_recorder_) {
output_file_recorder_->RegisterModuleFileCallback(NULL);
output_file_recorder_->StopRecording();
}
}
_mixerModule.UnRegisterMixedStreamCallback();
delete &_mixerModule;
}
@ -156,13 +108,6 @@ OutputMixer::SetMixabilityStatus(MixerParticipant& participant,
return _mixerModule.SetMixabilityStatus(&participant, mixable);
}
int32_t
OutputMixer::SetAnonymousMixabilityStatus(MixerParticipant& participant,
bool mixable)
{
return _mixerModule.SetAnonymousMixabilityStatus(&participant, mixable);
}
int32_t
OutputMixer::MixActiveChannels()
{
@ -170,179 +115,6 @@ OutputMixer::MixActiveChannels()
return 0;
}
int OutputMixer::StartRecordingPlayout(const char* fileName,
const CodecInst* codecInst)
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1),
"OutputMixer::StartRecordingPlayout(fileName=%s)", fileName);
if (_outputFileRecording)
{
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
"StartRecordingPlayout() is already recording");
return 0;
}
FileFormats format;
const uint32_t notificationTime(0);
CodecInst dummyCodec={100,"L16",16000,320,1,320000};
if ((codecInst != NULL) &&
((codecInst->channels < 1) || (codecInst->channels > 2)))
{
_engineStatisticsPtr->SetLastError(
VE_BAD_ARGUMENT, kTraceError,
"StartRecordingPlayout() invalid compression");
return(-1);
}
if(codecInst == NULL)
{
format = kFileFormatPcm16kHzFile;
codecInst=&dummyCodec;
}
else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
(STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
(STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
{
format = kFileFormatWavFile;
}
else
{
format = kFileFormatCompressedFile;
}
rtc::CritScope cs(&_fileCritSect);
// Destroy the old instance
if (output_file_recorder_) {
output_file_recorder_->RegisterModuleFileCallback(NULL);
output_file_recorder_.reset();
}
output_file_recorder_ = FileRecorder::CreateFileRecorder(
_instanceId, (const FileFormats)format);
if (!output_file_recorder_) {
_engineStatisticsPtr->SetLastError(
VE_INVALID_ARGUMENT, kTraceError,
"StartRecordingPlayout() fileRecorder format isnot correct");
return -1;
}
if (output_file_recorder_->StartRecordingAudioFile(
fileName, (const CodecInst&)*codecInst, notificationTime) != 0) {
_engineStatisticsPtr->SetLastError(
VE_BAD_FILE, kTraceError,
"StartRecordingAudioFile() failed to start file recording");
output_file_recorder_->StopRecording();
output_file_recorder_.reset();
return -1;
}
output_file_recorder_->RegisterModuleFileCallback(this);
_outputFileRecording = true;
return 0;
}
int OutputMixer::StartRecordingPlayout(OutStream* stream,
const CodecInst* codecInst)
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1),
"OutputMixer::StartRecordingPlayout()");
if (_outputFileRecording)
{
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
"StartRecordingPlayout() is already recording");
return 0;
}
FileFormats format;
const uint32_t notificationTime(0);
CodecInst dummyCodec={100,"L16",16000,320,1,320000};
if (codecInst != NULL && codecInst->channels != 1)
{
_engineStatisticsPtr->SetLastError(
VE_BAD_ARGUMENT, kTraceError,
"StartRecordingPlayout() invalid compression");
return(-1);
}
if(codecInst == NULL)
{
format = kFileFormatPcm16kHzFile;
codecInst=&dummyCodec;
}
else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
(STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
(STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
{
format = kFileFormatWavFile;
}
else
{
format = kFileFormatCompressedFile;
}
rtc::CritScope cs(&_fileCritSect);
// Destroy the old instance
if (output_file_recorder_) {
output_file_recorder_->RegisterModuleFileCallback(NULL);
output_file_recorder_.reset();
}
output_file_recorder_ = FileRecorder::CreateFileRecorder(
_instanceId, (const FileFormats)format);
if (!output_file_recorder_) {
_engineStatisticsPtr->SetLastError(
VE_INVALID_ARGUMENT, kTraceError,
"StartRecordingPlayout() fileRecorder format isnot correct");
return -1;
}
if (output_file_recorder_->StartRecordingAudioFile(stream, *codecInst,
notificationTime) != 0) {
_engineStatisticsPtr->SetLastError(
VE_BAD_FILE, kTraceError,
"StartRecordingAudioFile() failed to start file recording");
output_file_recorder_->StopRecording();
output_file_recorder_.reset();
return -1;
}
output_file_recorder_->RegisterModuleFileCallback(this);
_outputFileRecording = true;
return 0;
}
int OutputMixer::StopRecordingPlayout()
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1),
"OutputMixer::StopRecordingPlayout()");
if (!_outputFileRecording)
{
WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1),
"StopRecordingPlayout() file isnot recording");
return -1;
}
rtc::CritScope cs(&_fileCritSect);
if (output_file_recorder_->StopRecording() != 0) {
_engineStatisticsPtr->SetLastError(
VE_STOP_RECORDING_FAILED, kTraceError,
"StopRecording(), could not stop recording");
return -1;
}
output_file_recorder_->RegisterModuleFileCallback(NULL);
output_file_recorder_.reset();
_outputFileRecording = false;
return 0;
}
int OutputMixer::GetMixedAudio(int sample_rate_hz,
size_t num_channels,
AudioFrame* frame) {
@ -351,13 +123,6 @@ int OutputMixer::GetMixedAudio(int sample_rate_hz,
"OutputMixer::GetMixedAudio(sample_rate_hz=%d, num_channels=%" PRIuS ")",
sample_rate_hz, num_channels);
// --- Record playout if enabled
{
rtc::CritScope cs(&_fileCritSect);
if (_outputFileRecording && output_file_recorder_)
output_file_recorder_->RecordAudioToFile(_audioFrame);
}
frame->num_channels_ = num_channels;
frame->sample_rate_hz_ = sample_rate_hz;
// TODO(andrew): Ideally the downmixing would occur much earlier, in

View File

@ -18,7 +18,6 @@
#include "modules/audio_conference_mixer/include/audio_conference_mixer.h"
#include "modules/audio_conference_mixer/include/audio_conference_mixer_defines.h"
#include "rtc_base/criticalsection.h"
#include "voice_engine/file_recorder.h"
namespace webrtc {
@ -29,8 +28,7 @@ namespace voe {
class Statistics;
class OutputMixer : public AudioMixerOutputReceiver,
public FileCallback
class OutputMixer : public AudioMixerOutputReceiver
{
public:
static int32_t Create(OutputMixer*& mixer, uint32_t instanceId);
@ -49,20 +47,9 @@ public:
int32_t SetMixabilityStatus(MixerParticipant& participant,
bool mixable);
int32_t SetAnonymousMixabilityStatus(MixerParticipant& participant,
bool mixable);
int GetMixedAudio(int sample_rate_hz, size_t num_channels,
AudioFrame* audioFrame);
// VoEFile
int StartRecordingPlayout(const char* fileName,
const CodecInst* codecInst);
int StartRecordingPlayout(OutStream* stream,
const CodecInst* codecInst);
int StopRecordingPlayout();
virtual ~OutputMixer();
// from AudioMixerOutputReceiver
@ -72,14 +59,6 @@ public:
const AudioFrame** uniqueAudioFrames,
uint32_t size);
// For file recording
void PlayNotification(int32_t id, uint32_t durationMs);
void RecordNotification(int32_t id, uint32_t durationMs);
void PlayFileEnded(int32_t id);
void RecordFileEnded(int32_t id);
private:
OutputMixer(uint32_t instanceId);
@ -87,8 +66,6 @@ private:
Statistics* _engineStatisticsPtr;
AudioProcessing* _audioProcessingModulePtr;
// Protects output_file_recorder_ and _outputFileRecording.
rtc::CriticalSection _fileCritSect;
AudioConferenceMixer& _mixerModule;
AudioFrame _audioFrame;
// Converts mixed audio to the audio device output rate.
@ -97,8 +74,6 @@ private:
PushResampler<int16_t> audioproc_resampler_;
int _instanceId;
int _mixingFrequencyHz;
std::unique_ptr<FileRecorder> output_file_recorder_;
bool _outputFileRecording;
};
} // namespace voe

View File

@ -67,64 +67,6 @@ void TransmitMixer::OnPeriodicProcess()
}
#endif // WEBRTC_VOICE_ENGINE_TYPING_DETECTION
void TransmitMixer::PlayNotification(int32_t id,
uint32_t durationMs)
{
WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::PlayNotification(id=%d, durationMs=%d)",
id, durationMs);
// Not implement yet
}
void TransmitMixer::RecordNotification(int32_t id,
uint32_t durationMs)
{
WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,-1),
"TransmitMixer::RecordNotification(id=%d, durationMs=%d)",
id, durationMs);
// Not implement yet
}
void TransmitMixer::PlayFileEnded(int32_t id)
{
WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::PlayFileEnded(id=%d)", id);
assert(id == _filePlayerId);
rtc::CritScope cs(&_critSect);
_filePlaying = false;
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::PlayFileEnded() =>"
"file player module is shutdown");
}
void
TransmitMixer::RecordFileEnded(int32_t id)
{
WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::RecordFileEnded(id=%d)", id);
if (id == _fileRecorderId)
{
rtc::CritScope cs(&_critSect);
_fileRecording = false;
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::RecordFileEnded() => fileRecorder module"
"is shutdown");
} else if (id == _fileCallRecorderId)
{
rtc::CritScope cs(&_critSect);
_fileCallRecording = false;
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::RecordFileEnded() => fileCallRecorder"
"module is shutdown");
}
}
int32_t
TransmitMixer::Create(TransmitMixer*& mixer, uint32_t instanceId)
{
@ -152,11 +94,6 @@ TransmitMixer::Destroy(TransmitMixer*& mixer)
}
TransmitMixer::TransmitMixer(uint32_t instanceId) :
// Avoid conflict with other channels by adding 1024 - 1026,
// won't use as much as 1024 channels.
_filePlayerId(instanceId + 1024),
_fileRecorderId(instanceId + 1025),
_fileCallRecorderId(instanceId + 1026),
#if WEBRTC_VOICE_ENGINE_TYPING_DETECTION
_monitorModule(this),
#endif
@ -174,21 +111,6 @@ TransmitMixer::~TransmitMixer()
if (_processThreadPtr)
_processThreadPtr->DeRegisterModule(&_monitorModule);
#endif
{
rtc::CritScope cs(&_critSect);
if (file_recorder_) {
file_recorder_->RegisterModuleFileCallback(NULL);
file_recorder_->StopRecording();
}
if (file_call_recorder_) {
file_call_recorder_->RegisterModuleFileCallback(NULL);
file_call_recorder_->StopRecording();
}
if (file_player_) {
file_player_->RegisterModuleFileCallback(NULL);
file_player_->StopPlayingFile();
}
}
}
int32_t
@ -295,23 +217,6 @@ TransmitMixer::PrepareDemux(const void* audioSamples,
TypingDetection(keyPressed);
#endif
// --- Mix with file (does not affect the mixing frequency)
if (_filePlaying)
{
MixOrReplaceAudioWithFile(_audioFrame.sample_rate_hz_);
}
// --- Record to file
bool file_recording = false;
{
rtc::CritScope cs(&_critSect);
file_recording = _fileRecording;
}
if (file_recording)
{
RecordAudioToFile(_audioFrame.sample_rate_hz_);
}
// --- Measure audio level of speech after all processing.
double sample_duration = static_cast<double>(nSamples) / samplesPerSec;
_audioLevel.ComputeLevel(_audioFrame, sample_duration);
@ -344,509 +249,6 @@ TransmitMixer::StopSend()
return 0;
}
int TransmitMixer::StartPlayingFileAsMicrophone(const char* fileName,
bool loop,
FileFormats format,
int startPosition,
float volumeScaling,
int stopPosition,
const CodecInst* codecInst)
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::StartPlayingFileAsMicrophone("
"fileNameUTF8[]=%s,loop=%d, format=%d, volumeScaling=%5.3f,"
" startPosition=%d, stopPosition=%d)", fileName, loop,
format, volumeScaling, startPosition, stopPosition);
if (_filePlaying)
{
_engineStatisticsPtr->SetLastError(
VE_ALREADY_PLAYING, kTraceWarning,
"StartPlayingFileAsMicrophone() is already playing");
return 0;
}
rtc::CritScope cs(&_critSect);
// Destroy the old instance
if (file_player_) {
file_player_->RegisterModuleFileCallback(NULL);
file_player_.reset();
}
// Dynamically create the instance
file_player_ =
FilePlayer::CreateFilePlayer(_filePlayerId, (const FileFormats)format);
if (!file_player_) {
_engineStatisticsPtr->SetLastError(
VE_INVALID_ARGUMENT, kTraceError,
"StartPlayingFileAsMicrophone() filePlayer format isnot correct");
return -1;
}
const uint32_t notificationTime(0);
if (file_player_->StartPlayingFile(
fileName, loop, startPosition, volumeScaling, notificationTime,
stopPosition, (const CodecInst*)codecInst) != 0) {
_engineStatisticsPtr->SetLastError(
VE_BAD_FILE, kTraceError,
"StartPlayingFile() failed to start file playout");
file_player_->StopPlayingFile();
file_player_.reset();
return -1;
}
file_player_->RegisterModuleFileCallback(this);
_filePlaying = true;
return 0;
}
int TransmitMixer::StartPlayingFileAsMicrophone(InStream* stream,
FileFormats format,
int startPosition,
float volumeScaling,
int stopPosition,
const CodecInst* codecInst)
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1),
"TransmitMixer::StartPlayingFileAsMicrophone(format=%d,"
" volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
format, volumeScaling, startPosition, stopPosition);
if (stream == NULL)
{
_engineStatisticsPtr->SetLastError(
VE_BAD_FILE, kTraceError,
"StartPlayingFileAsMicrophone() NULL as input stream");
return -1;
}
if (_filePlaying)
{
_engineStatisticsPtr->SetLastError(
VE_ALREADY_PLAYING, kTraceWarning,
"StartPlayingFileAsMicrophone() is already playing");
return 0;
}
rtc::CritScope cs(&_critSect);
// Destroy the old instance
if (file_player_) {
file_player_->RegisterModuleFileCallback(NULL);
file_player_.reset();
}
// Dynamically create the instance
file_player_ =
FilePlayer::CreateFilePlayer(_filePlayerId, (const FileFormats)format);
if (!file_player_) {
_engineStatisticsPtr->SetLastError(
VE_INVALID_ARGUMENT, kTraceWarning,
"StartPlayingFileAsMicrophone() filePlayer format isnot correct");
return -1;
}
const uint32_t notificationTime(0);
if (file_player_->StartPlayingFile(stream, startPosition, volumeScaling,
notificationTime, stopPosition,
(const CodecInst*)codecInst) != 0) {
_engineStatisticsPtr->SetLastError(
VE_BAD_FILE, kTraceError,
"StartPlayingFile() failed to start file playout");
file_player_->StopPlayingFile();
file_player_.reset();
return -1;
}
file_player_->RegisterModuleFileCallback(this);
_filePlaying = true;
return 0;
}
int TransmitMixer::StopPlayingFileAsMicrophone()
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1),
"TransmitMixer::StopPlayingFileAsMicrophone()");
if (!_filePlaying)
{
return 0;
}
rtc::CritScope cs(&_critSect);
if (file_player_->StopPlayingFile() != 0) {
_engineStatisticsPtr->SetLastError(
VE_CANNOT_STOP_PLAYOUT, kTraceError,
"StopPlayingFile() couldnot stop playing file");
return -1;
}
file_player_->RegisterModuleFileCallback(NULL);
file_player_.reset();
_filePlaying = false;
return 0;
}
int TransmitMixer::IsPlayingFileAsMicrophone() const
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::IsPlayingFileAsMicrophone()");
return _filePlaying;
}
int TransmitMixer::StartRecordingMicrophone(const char* fileName,
const CodecInst* codecInst)
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::StartRecordingMicrophone(fileName=%s)",
fileName);
rtc::CritScope cs(&_critSect);
if (_fileRecording)
{
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
"StartRecordingMicrophone() is already recording");
return 0;
}
FileFormats format;
const uint32_t notificationTime(0); // Not supported in VoE
CodecInst dummyCodec = { 100, "L16", 16000, 320, 1, 320000 };
if (codecInst != NULL && codecInst->channels > 2)
{
_engineStatisticsPtr->SetLastError(
VE_BAD_ARGUMENT, kTraceError,
"StartRecordingMicrophone() invalid compression");
return (-1);
}
if (codecInst == NULL)
{
format = kFileFormatPcm16kHzFile;
codecInst = &dummyCodec;
} else if ((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
(STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
(STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
{
format = kFileFormatWavFile;
} else
{
format = kFileFormatCompressedFile;
}
// Destroy the old instance
if (file_recorder_) {
file_recorder_->RegisterModuleFileCallback(NULL);
file_recorder_.reset();
}
file_recorder_ = FileRecorder::CreateFileRecorder(
_fileRecorderId, (const FileFormats)format);
if (!file_recorder_) {
_engineStatisticsPtr->SetLastError(
VE_INVALID_ARGUMENT, kTraceError,
"StartRecordingMicrophone() fileRecorder format isnot correct");
return -1;
}
if (file_recorder_->StartRecordingAudioFile(
fileName, (const CodecInst&)*codecInst, notificationTime) != 0) {
_engineStatisticsPtr->SetLastError(
VE_BAD_FILE, kTraceError,
"StartRecordingAudioFile() failed to start file recording");
file_recorder_->StopRecording();
file_recorder_.reset();
return -1;
}
file_recorder_->RegisterModuleFileCallback(this);
_fileRecording = true;
return 0;
}
int TransmitMixer::StartRecordingMicrophone(OutStream* stream,
const CodecInst* codecInst)
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::StartRecordingMicrophone()");
rtc::CritScope cs(&_critSect);
if (_fileRecording)
{
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
"StartRecordingMicrophone() is already recording");
return 0;
}
FileFormats format;
const uint32_t notificationTime(0); // Not supported in VoE
CodecInst dummyCodec = { 100, "L16", 16000, 320, 1, 320000 };
if (codecInst != NULL && codecInst->channels != 1)
{
_engineStatisticsPtr->SetLastError(
VE_BAD_ARGUMENT, kTraceError,
"StartRecordingMicrophone() invalid compression");
return (-1);
}
if (codecInst == NULL)
{
format = kFileFormatPcm16kHzFile;
codecInst = &dummyCodec;
} else if ((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
(STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
(STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
{
format = kFileFormatWavFile;
} else
{
format = kFileFormatCompressedFile;
}
// Destroy the old instance
if (file_recorder_) {
file_recorder_->RegisterModuleFileCallback(NULL);
file_recorder_.reset();
}
file_recorder_ = FileRecorder::CreateFileRecorder(
_fileRecorderId, (const FileFormats)format);
if (!file_recorder_) {
_engineStatisticsPtr->SetLastError(
VE_INVALID_ARGUMENT, kTraceError,
"StartRecordingMicrophone() fileRecorder format isnot correct");
return -1;
}
if (file_recorder_->StartRecordingAudioFile(stream, *codecInst,
notificationTime) != 0) {
_engineStatisticsPtr->SetLastError(
VE_BAD_FILE, kTraceError,
"StartRecordingAudioFile() failed to start file recording");
file_recorder_->StopRecording();
file_recorder_.reset();
return -1;
}
file_recorder_->RegisterModuleFileCallback(this);
_fileRecording = true;
return 0;
}
int TransmitMixer::StopRecordingMicrophone()
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::StopRecordingMicrophone()");
rtc::CritScope cs(&_critSect);
if (!_fileRecording)
{
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
"StopRecordingMicrophone() isnot recording");
return 0;
}
if (file_recorder_->StopRecording() != 0) {
_engineStatisticsPtr->SetLastError(
VE_STOP_RECORDING_FAILED, kTraceError,
"StopRecording(), could not stop recording");
return -1;
}
file_recorder_->RegisterModuleFileCallback(NULL);
file_recorder_.reset();
_fileRecording = false;
return 0;
}
int TransmitMixer::StartRecordingCall(const char* fileName,
const CodecInst* codecInst)
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::StartRecordingCall(fileName=%s)", fileName);
if (_fileCallRecording)
{
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
"StartRecordingCall() is already recording");
return 0;
}
FileFormats format;
const uint32_t notificationTime(0); // Not supported in VoE
CodecInst dummyCodec = { 100, "L16", 16000, 320, 1, 320000 };
if (codecInst != NULL && codecInst->channels != 1)
{
_engineStatisticsPtr->SetLastError(
VE_BAD_ARGUMENT, kTraceError,
"StartRecordingCall() invalid compression");
return (-1);
}
if (codecInst == NULL)
{
format = kFileFormatPcm16kHzFile;
codecInst = &dummyCodec;
} else if ((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
(STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
(STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
{
format = kFileFormatWavFile;
} else
{
format = kFileFormatCompressedFile;
}
rtc::CritScope cs(&_critSect);
// Destroy the old instance
if (file_call_recorder_) {
file_call_recorder_->RegisterModuleFileCallback(NULL);
file_call_recorder_.reset();
}
file_call_recorder_ = FileRecorder::CreateFileRecorder(
_fileCallRecorderId, (const FileFormats)format);
if (!file_call_recorder_) {
_engineStatisticsPtr->SetLastError(
VE_INVALID_ARGUMENT, kTraceError,
"StartRecordingCall() fileRecorder format isnot correct");
return -1;
}
if (file_call_recorder_->StartRecordingAudioFile(
fileName, (const CodecInst&)*codecInst, notificationTime) != 0) {
_engineStatisticsPtr->SetLastError(
VE_BAD_FILE, kTraceError,
"StartRecordingAudioFile() failed to start file recording");
file_call_recorder_->StopRecording();
file_call_recorder_.reset();
return -1;
}
file_call_recorder_->RegisterModuleFileCallback(this);
_fileCallRecording = true;
return 0;
}
int TransmitMixer::StartRecordingCall(OutStream* stream,
const CodecInst* codecInst)
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::StartRecordingCall()");
if (_fileCallRecording)
{
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
"StartRecordingCall() is already recording");
return 0;
}
FileFormats format;
const uint32_t notificationTime(0); // Not supported in VoE
CodecInst dummyCodec = { 100, "L16", 16000, 320, 1, 320000 };
if (codecInst != NULL && codecInst->channels != 1)
{
_engineStatisticsPtr->SetLastError(
VE_BAD_ARGUMENT, kTraceError,
"StartRecordingCall() invalid compression");
return (-1);
}
if (codecInst == NULL)
{
format = kFileFormatPcm16kHzFile;
codecInst = &dummyCodec;
} else if ((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
(STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
(STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
{
format = kFileFormatWavFile;
} else
{
format = kFileFormatCompressedFile;
}
rtc::CritScope cs(&_critSect);
// Destroy the old instance
if (file_call_recorder_) {
file_call_recorder_->RegisterModuleFileCallback(NULL);
file_call_recorder_.reset();
}
file_call_recorder_ = FileRecorder::CreateFileRecorder(
_fileCallRecorderId, (const FileFormats)format);
if (!file_call_recorder_) {
_engineStatisticsPtr->SetLastError(
VE_INVALID_ARGUMENT, kTraceError,
"StartRecordingCall() fileRecorder format isnot correct");
return -1;
}
if (file_call_recorder_->StartRecordingAudioFile(stream, *codecInst,
notificationTime) != 0) {
_engineStatisticsPtr->SetLastError(
VE_BAD_FILE, kTraceError,
"StartRecordingAudioFile() failed to start file recording");
file_call_recorder_->StopRecording();
file_call_recorder_.reset();
return -1;
}
file_call_recorder_->RegisterModuleFileCallback(this);
_fileCallRecording = true;
return 0;
}
int TransmitMixer::StopRecordingCall()
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::StopRecordingCall()");
if (!_fileCallRecording)
{
WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, -1),
"StopRecordingCall() file isnot recording");
return -1;
}
rtc::CritScope cs(&_critSect);
if (file_call_recorder_->StopRecording() != 0) {
_engineStatisticsPtr->SetLastError(
VE_STOP_RECORDING_FAILED, kTraceError,
"StopRecording(), could not stop recording");
return -1;
}
file_call_recorder_->RegisterModuleFileCallback(NULL);
file_call_recorder_.reset();
_fileCallRecording = false;
return 0;
}
void
TransmitMixer::SetMixWithMicStatus(bool mix)
{
_mixFileWithMicrophone = mix;
}
int8_t TransmitMixer::AudioLevel() const
{
// Speech + file level [0,9]
@ -867,17 +269,6 @@ double TransmitMixer::GetTotalInputDuration() const {
return _audioLevel.TotalDuration();
}
bool TransmitMixer::IsRecordingCall()
{
return _fileCallRecording;
}
bool TransmitMixer::IsRecordingMic()
{
rtc::CritScope cs(&_critSect);
return _fileRecording;
}
void TransmitMixer::GenerateAudioFrame(const int16_t* audio,
size_t samples_per_channel,
size_t num_channels,
@ -901,79 +292,6 @@ void TransmitMixer::GenerateAudioFrame(const int16_t* audio,
&resampler_, &_audioFrame);
}
int32_t TransmitMixer::RecordAudioToFile(
uint32_t mixingFrequency)
{
rtc::CritScope cs(&_critSect);
if (!file_recorder_) {
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::RecordAudioToFile() filerecorder doesnot"
"exist");
return -1;
}
if (file_recorder_->RecordAudioToFile(_audioFrame) != 0) {
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::RecordAudioToFile() file recording"
"failed");
return -1;
}
return 0;
}
int32_t TransmitMixer::MixOrReplaceAudioWithFile(
int mixingFrequency)
{
std::unique_ptr<int16_t[]> fileBuffer(new int16_t[640]);
size_t fileSamples(0);
{
rtc::CritScope cs(&_critSect);
if (!file_player_) {
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::MixOrReplaceAudioWithFile()"
"fileplayer doesnot exist");
return -1;
}
if (file_player_->Get10msAudioFromFile(fileBuffer.get(), &fileSamples,
mixingFrequency) == -1) {
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::MixOrReplaceAudioWithFile() file"
" mixing failed");
return -1;
}
}
assert(_audioFrame.samples_per_channel_ == fileSamples);
if (_mixFileWithMicrophone)
{
// Currently file stream is always mono.
// TODO(xians): Change the code when FilePlayer supports real stereo.
MixWithSat(_audioFrame.mutable_data(),
_audioFrame.num_channels_,
fileBuffer.get(),
1,
fileSamples);
} else
{
// Replace ACM audio with file.
// Currently file stream is always mono.
// TODO(xians): Change the code when FilePlayer supports real stereo.
_audioFrame.UpdateFrame(-1,
0xFFFFFFFF,
fileBuffer.get(),
fileSamples,
mixingFrequency,
AudioFrame::kNormalSpeech,
AudioFrame::kVadUnknown,
1);
}
return 0;
}
void TransmitMixer::ProcessAudio(int delay_ms, int clock_drift,
int current_mic_level, bool key_pressed) {
if (audioproc_->set_stream_delay_ms(delay_ms) != 0) {

View File

@ -19,8 +19,6 @@
#include "modules/include/module_common_types.h"
#include "rtc_base/criticalsection.h"
#include "voice_engine/audio_level.h"
#include "voice_engine/file_player.h"
#include "voice_engine/file_recorder.h"
#include "voice_engine/include/voe_base.h"
#include "voice_engine/monitor_module.h"
#include "voice_engine/voice_engine_defines.h"
@ -41,7 +39,7 @@ class ChannelManager;
class MixedAudio;
class Statistics;
class TransmitMixer : public FileCallback {
class TransmitMixer {
public:
static int32_t Create(TransmitMixer*& mixer, uint32_t instanceId);
@ -84,45 +82,6 @@ public:
// 'virtual' to allow mocking.
virtual double GetTotalInputDuration() const;
bool IsRecordingCall();
bool IsRecordingMic();
int StartPlayingFileAsMicrophone(const char* fileName,
bool loop,
FileFormats format,
int startPosition,
float volumeScaling,
int stopPosition,
const CodecInst* codecInst);
int StartPlayingFileAsMicrophone(InStream* stream,
FileFormats format,
int startPosition,
float volumeScaling,
int stopPosition,
const CodecInst* codecInst);
int StopPlayingFileAsMicrophone();
int IsPlayingFileAsMicrophone() const;
int StartRecordingMicrophone(const char* fileName,
const CodecInst* codecInst);
int StartRecordingMicrophone(OutStream* stream,
const CodecInst* codecInst);
int StopRecordingMicrophone();
int StartRecordingCall(const char* fileName, const CodecInst* codecInst);
int StartRecordingCall(OutStream* stream, const CodecInst* codecInst);
int StopRecordingCall();
void SetMixWithMicStatus(bool mix);
int32_t RegisterVoiceEngineObserver(VoiceEngineObserver& observer);
virtual ~TransmitMixer();
@ -132,17 +91,6 @@ public:
void OnPeriodicProcess();
#endif
// FileCallback
void PlayNotification(const int32_t id,
const uint32_t durationMs);
void RecordNotification(const int32_t id,
const uint32_t durationMs);
void PlayFileEnded(const int32_t id);
void RecordFileEnded(const int32_t id);
// Virtual to allow mocking.
virtual void EnableStereoChannelSwapping(bool enable);
bool IsStereoChannelSwappingEnabled();
@ -165,10 +113,6 @@ private:
size_t nSamples,
size_t nChannels,
int samplesPerSec);
int32_t RecordAudioToFile(uint32_t mixingFrequency);
int32_t MixOrReplaceAudioWithFile(
int mixingFrequency);
void ProcessAudio(int delay_ms, int clock_drift, int current_mic_level,
bool key_pressed);
@ -187,15 +131,6 @@ private:
// owns
AudioFrame _audioFrame;
PushResampler<int16_t> resampler_; // ADM sample rate -> mixing rate
std::unique_ptr<FilePlayer> file_player_;
std::unique_ptr<FileRecorder> file_recorder_;
std::unique_ptr<FileRecorder> file_call_recorder_;
int _filePlayerId = 0;
int _fileRecorderId = 0;
int _fileCallRecorderId = 0;
bool _filePlaying = false;
bool _fileRecording = false;
bool _fileCallRecording = false;
voe::AudioLevel _audioLevel;
// protect file instances and their variables in MixedParticipants()
rtc::CriticalSection _critSect;
@ -209,7 +144,6 @@ private:
#endif
int _instanceId = 0;
bool _mixFileWithMicrophone = false;
uint32_t _captureLevel = 0;
bool stereo_codec_ = false;
bool swap_stereo_channels_ = false;

View File

@ -88,41 +88,5 @@ void RemixAndResample(const int16_t* src_data,
}
}
void MixWithSat(int16_t target[],
size_t target_channel,
const int16_t source[],
size_t source_channel,
size_t source_len) {
RTC_DCHECK_GE(target_channel, 1);
RTC_DCHECK_LE(target_channel, 2);
RTC_DCHECK_GE(source_channel, 1);
RTC_DCHECK_LE(source_channel, 2);
if (target_channel == 2 && source_channel == 1) {
// Convert source from mono to stereo.
int32_t left = 0;
int32_t right = 0;
for (size_t i = 0; i < source_len; ++i) {
left = source[i] + target[i * 2];
right = source[i] + target[i * 2 + 1];
target[i * 2] = WebRtcSpl_SatW32ToW16(left);
target[i * 2 + 1] = WebRtcSpl_SatW32ToW16(right);
}
} else if (target_channel == 1 && source_channel == 2) {
// Convert source from stereo to mono.
int32_t temp = 0;
for (size_t i = 0; i < source_len / 2; ++i) {
temp = ((source[i * 2] + source[i * 2 + 1]) >> 1) + target[i];
target[i] = WebRtcSpl_SatW32ToW16(temp);
}
} else {
int32_t temp = 0;
for (size_t i = 0; i < source_len; ++i) {
temp = source[i] + target[i];
target[i] = WebRtcSpl_SatW32ToW16(temp);
}
}
}
} // namespace voe
} // namespace webrtc

View File

@ -45,12 +45,6 @@ void RemixAndResample(const int16_t* src_data,
PushResampler<int16_t>* resampler,
AudioFrame* dst_frame);
void MixWithSat(int16_t target[],
size_t target_channel,
const int16_t source[],
size_t source_channel,
size_t source_len);
} // namespace voe
} // namespace webrtc

View File

@ -597,8 +597,7 @@ int32_t VoEBaseImpl::StartSend() {
}
int32_t VoEBaseImpl::StopSend() {
if (shared_->NumOfSendingChannels() == 0 &&
!shared_->transmit_mixer()->IsRecordingMic()) {
if (shared_->NumOfSendingChannels() == 0) {
// Stop audio-device recording if no channel is recording
if (shared_->audio_device()->StopRecording() != 0) {
shared_->SetLastError(VE_CANNOT_STOP_RECORDING, kTraceError,

View File

@ -1,466 +0,0 @@
/*
* 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 "voice_engine/voe_file_impl.h"
#include "system_wrappers/include/file_wrapper.h"
#include "system_wrappers/include/trace.h"
#include "voice_engine/channel.h"
#include "voice_engine/include/voe_errors.h"
#include "voice_engine/output_mixer.h"
#include "voice_engine/transmit_mixer.h"
#include "voice_engine/voice_engine_impl.h"
namespace webrtc {
VoEFile* VoEFile::GetInterface(VoiceEngine* voiceEngine) {
if (NULL == voiceEngine) {
return NULL;
}
VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
s->AddRef();
return s;
}
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);
static_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) {
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);
static_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);
static_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);
static_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()) {
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()) {
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;
}
} // namespace webrtc

View File

@ -1,95 +0,0 @@
/*
* 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.
*/
#ifndef VOICE_ENGINE_VOE_FILE_IMPL_H_
#define VOICE_ENGINE_VOE_FILE_IMPL_H_
#include "voice_engine/include/voe_file.h"
#include "voice_engine/shared_data.h"
namespace webrtc {
class VoEFileImpl : public VoEFile {
public:
// Playout file locally
int StartPlayingFileLocally(int channel,
const char fileNameUTF8[1024],
bool loop = false,
FileFormats format = kFileFormatPcm16kHzFile,
float volumeScaling = 1.0,
int startPointMs = 0,
int stopPointMs = 0) override;
int StartPlayingFileLocally(int channel,
InStream* stream,
FileFormats format = kFileFormatPcm16kHzFile,
float volumeScaling = 1.0,
int startPointMs = 0,
int stopPointMs = 0) override;
int StopPlayingFileLocally(int channel) override;
int IsPlayingFileLocally(int channel) override;
// Use file as microphone input
int StartPlayingFileAsMicrophone(int channel,
const char fileNameUTF8[1024],
bool loop = false,
bool mixWithMicrophone = false,
FileFormats format = kFileFormatPcm16kHzFile,
float volumeScaling = 1.0) override;
int StartPlayingFileAsMicrophone(int channel,
InStream* stream,
bool mixWithMicrophone = false,
FileFormats format = kFileFormatPcm16kHzFile,
float volumeScaling = 1.0) override;
int StopPlayingFileAsMicrophone(int channel) override;
int IsPlayingFileAsMicrophone(int channel) override;
// Record speaker signal to file
int StartRecordingPlayout(int channel,
const char* fileNameUTF8,
CodecInst* compression = NULL,
int maxSizeBytes = -1) override;
int StartRecordingPlayout(int channel,
OutStream* stream,
CodecInst* compression = NULL) override;
int StopRecordingPlayout(int channel) override;
// Record microphone signal to file
int StartRecordingMicrophone(const char* fileNameUTF8,
CodecInst* compression = NULL,
int maxSizeBytes = -1) override;
int StartRecordingMicrophone(OutStream* stream,
CodecInst* compression = NULL) override;
int StopRecordingMicrophone() override;
protected:
VoEFileImpl(voe::SharedData* shared);
~VoEFileImpl() override;
private:
voe::SharedData* _shared;
};
} // namespace webrtc
#endif // VOICE_ENGINE_VOE_FILE_IMPL_H_

View File

@ -17,7 +17,6 @@
#include "typedefs.h" // NOLINT(build/include)
#include "voice_engine/voe_base_impl.h"
#include "voice_engine/voe_codec_impl.h"
#include "voice_engine/voe_file_impl.h"
#include "voice_engine/voe_network_impl.h"
#include "voice_engine/voe_rtp_rtcp_impl.h"
@ -29,7 +28,6 @@ class ChannelProxy;
class VoiceEngineImpl : public voe::SharedData, // Must be the first base class
public VoiceEngine,
public VoECodecImpl,
public VoEFileImpl,
public VoENetworkImpl,
public VoERTP_RTCPImpl,
public VoEBaseImpl {
@ -37,7 +35,6 @@ class VoiceEngineImpl : public voe::SharedData, // Must be the first base class
VoiceEngineImpl()
: SharedData(),
VoECodecImpl(this),
VoEFileImpl(this),
VoENetworkImpl(this),
VoERTP_RTCPImpl(this),
VoEBaseImpl(this),