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