| OLD | NEW |
| 1 /* | 1 /* |
| 2 * libjingle | 2 * libjingle |
| 3 * Copyright 2004 Google Inc. | 3 * Copyright 2004 Google Inc. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
| 9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 | 35 |
| 36 #include <algorithm> | 36 #include <algorithm> |
| 37 #include <cstdio> | 37 #include <cstdio> |
| 38 #include <string> | 38 #include <string> |
| 39 #include <vector> | 39 #include <vector> |
| 40 | 40 |
| 41 #include "talk/media/base/audioframe.h" | 41 #include "talk/media/base/audioframe.h" |
| 42 #include "talk/media/base/audiorenderer.h" | 42 #include "talk/media/base/audiorenderer.h" |
| 43 #include "talk/media/base/constants.h" | 43 #include "talk/media/base/constants.h" |
| 44 #include "talk/media/base/streamparams.h" | 44 #include "talk/media/base/streamparams.h" |
| 45 #include "talk/media/base/voiceprocessor.h" | |
| 46 #include "talk/media/webrtc/webrtcvoe.h" | 45 #include "talk/media/webrtc/webrtcvoe.h" |
| 47 #include "webrtc/base/base64.h" | 46 #include "webrtc/base/base64.h" |
| 48 #include "webrtc/base/byteorder.h" | 47 #include "webrtc/base/byteorder.h" |
| 49 #include "webrtc/base/common.h" | 48 #include "webrtc/base/common.h" |
| 50 #include "webrtc/base/helpers.h" | 49 #include "webrtc/base/helpers.h" |
| 51 #include "webrtc/base/logging.h" | 50 #include "webrtc/base/logging.h" |
| 52 #include "webrtc/base/stringencode.h" | 51 #include "webrtc/base/stringencode.h" |
| 53 #include "webrtc/base/stringutils.h" | 52 #include "webrtc/base/stringutils.h" |
| 54 #include "webrtc/common.h" | 53 #include "webrtc/common.h" |
| 55 #include "webrtc/modules/audio_processing/include/audio_processing.h" | 54 #include "webrtc/modules/audio_processing/include/audio_processing.h" |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 | 360 |
| 362 static std::string GetEnableString(bool enable) { | 361 static std::string GetEnableString(bool enable) { |
| 363 return enable ? "enable" : "disable"; | 362 return enable ? "enable" : "disable"; |
| 364 } | 363 } |
| 365 | 364 |
| 366 WebRtcVoiceEngine::WebRtcVoiceEngine() | 365 WebRtcVoiceEngine::WebRtcVoiceEngine() |
| 367 : voe_wrapper_(new VoEWrapper()), | 366 : voe_wrapper_(new VoEWrapper()), |
| 368 tracing_(new VoETraceWrapper()), | 367 tracing_(new VoETraceWrapper()), |
| 369 adm_(NULL), | 368 adm_(NULL), |
| 370 log_filter_(SeverityToFilter(kDefaultLogSeverity)), | 369 log_filter_(SeverityToFilter(kDefaultLogSeverity)), |
| 371 is_dumping_aec_(false), | 370 is_dumping_aec_(false) { |
| 372 tx_processor_ssrc_(0), | |
| 373 rx_processor_ssrc_(0) { | |
| 374 Construct(); | 371 Construct(); |
| 375 } | 372 } |
| 376 | 373 |
| 377 WebRtcVoiceEngine::WebRtcVoiceEngine(VoEWrapper* voe_wrapper, | 374 WebRtcVoiceEngine::WebRtcVoiceEngine(VoEWrapper* voe_wrapper, |
| 378 VoETraceWrapper* tracing) | 375 VoETraceWrapper* tracing) |
| 379 : voe_wrapper_(voe_wrapper), | 376 : voe_wrapper_(voe_wrapper), |
| 380 tracing_(tracing), | 377 tracing_(tracing), |
| 381 adm_(NULL), | 378 adm_(NULL), |
| 382 log_filter_(SeverityToFilter(kDefaultLogSeverity)), | 379 log_filter_(SeverityToFilter(kDefaultLogSeverity)), |
| 383 is_dumping_aec_(false), | 380 is_dumping_aec_(false) { |
| 384 tx_processor_ssrc_(0), | |
| 385 rx_processor_ssrc_(0) { | |
| 386 Construct(); | 381 Construct(); |
| 387 } | 382 } |
| 388 | 383 |
| 389 void WebRtcVoiceEngine::Construct() { | 384 void WebRtcVoiceEngine::Construct() { |
| 390 SetTraceFilter(log_filter_); | 385 SetTraceFilter(log_filter_); |
| 391 initialized_ = false; | 386 initialized_ = false; |
| 392 LOG(LS_VERBOSE) << "WebRtcVoiceEngine::WebRtcVoiceEngine"; | 387 LOG(LS_VERBOSE) << "WebRtcVoiceEngine::WebRtcVoiceEngine"; |
| 393 SetTraceOptions(""); | 388 SetTraceOptions(""); |
| 394 if (tracing_->SetTraceCallback(this) == -1) { | 389 if (tracing_->SetTraceCallback(this) == -1) { |
| 395 LOG_RTCERR0(SetTraceCallback); | 390 LOG_RTCERR0(SetTraceCallback); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 LOG(LS_VERBOSE) << "WebRtcVoiceEngine::~WebRtcVoiceEngine"; | 478 LOG(LS_VERBOSE) << "WebRtcVoiceEngine::~WebRtcVoiceEngine"; |
| 484 if (voe_wrapper_->base()->DeRegisterVoiceEngineObserver() == -1) { | 479 if (voe_wrapper_->base()->DeRegisterVoiceEngineObserver() == -1) { |
| 485 LOG_RTCERR0(DeRegisterVoiceEngineObserver); | 480 LOG_RTCERR0(DeRegisterVoiceEngineObserver); |
| 486 } | 481 } |
| 487 if (adm_) { | 482 if (adm_) { |
| 488 voe_wrapper_.reset(); | 483 voe_wrapper_.reset(); |
| 489 adm_->Release(); | 484 adm_->Release(); |
| 490 adm_ = NULL; | 485 adm_ = NULL; |
| 491 } | 486 } |
| 492 | 487 |
| 493 // Test to see if the media processor was deregistered properly | |
| 494 RTC_DCHECK(SignalRxMediaFrame.is_empty()); | |
| 495 RTC_DCHECK(SignalTxMediaFrame.is_empty()); | |
| 496 | |
| 497 tracing_->SetTraceCallback(NULL); | 488 tracing_->SetTraceCallback(NULL); |
| 498 } | 489 } |
| 499 | 490 |
| 500 bool WebRtcVoiceEngine::Init(rtc::Thread* worker_thread) { | 491 bool WebRtcVoiceEngine::Init(rtc::Thread* worker_thread) { |
| 501 RTC_DCHECK(worker_thread == rtc::Thread::Current()); | 492 RTC_DCHECK(worker_thread == rtc::Thread::Current()); |
| 502 LOG(LS_INFO) << "WebRtcVoiceEngine::Init"; | 493 LOG(LS_INFO) << "WebRtcVoiceEngine::Init"; |
| 503 bool res = InitInternal(); | 494 bool res = InitInternal(); |
| 504 if (res) { | 495 if (res) { |
| 505 LOG(LS_INFO) << "WebRtcVoiceEngine::Init Done!"; | 496 LOG(LS_INFO) << "WebRtcVoiceEngine::Init Done!"; |
| 506 } else { | 497 } else { |
| (...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1270 RTC_DCHECK(ch != NULL); | 1261 RTC_DCHECK(ch != NULL); |
| 1271 if (ch->FindSsrc(channel_num, ssrc)) { | 1262 if (ch->FindSsrc(channel_num, ssrc)) { |
| 1272 *channel = ch; | 1263 *channel = ch; |
| 1273 return true; | 1264 return true; |
| 1274 } | 1265 } |
| 1275 } | 1266 } |
| 1276 | 1267 |
| 1277 return false; | 1268 return false; |
| 1278 } | 1269 } |
| 1279 | 1270 |
| 1280 // This method will search through the WebRtcVoiceMediaChannels and | |
| 1281 // obtain the voice engine's channel number. | |
| 1282 bool WebRtcVoiceEngine::FindChannelNumFromSsrc( | |
| 1283 uint32 ssrc, MediaProcessorDirection direction, int* channel_num) { | |
| 1284 RTC_DCHECK(channel_num != NULL); | |
| 1285 RTC_DCHECK(direction == MPD_RX || direction == MPD_TX); | |
| 1286 | |
| 1287 *channel_num = -1; | |
| 1288 // Find corresponding channel for ssrc. | |
| 1289 for (const WebRtcVoiceMediaChannel* ch : channels_) { | |
| 1290 RTC_DCHECK(ch != NULL); | |
| 1291 if (direction & MPD_RX) { | |
| 1292 *channel_num = ch->GetReceiveChannelNum(ssrc); | |
| 1293 } | |
| 1294 if (*channel_num == -1 && (direction & MPD_TX)) { | |
| 1295 *channel_num = ch->GetSendChannelNum(ssrc); | |
| 1296 } | |
| 1297 if (*channel_num != -1) { | |
| 1298 return true; | |
| 1299 } | |
| 1300 } | |
| 1301 LOG(LS_WARNING) << "FindChannelFromSsrc. No Channel Found for Ssrc: " << ssrc; | |
| 1302 return false; | |
| 1303 } | |
| 1304 | |
| 1305 void WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel *channel) { | 1271 void WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel *channel) { |
| 1306 rtc::CritScope lock(&channels_cs_); | 1272 rtc::CritScope lock(&channels_cs_); |
| 1307 channels_.push_back(channel); | 1273 channels_.push_back(channel); |
| 1308 } | 1274 } |
| 1309 | 1275 |
| 1310 void WebRtcVoiceEngine::UnregisterChannel(WebRtcVoiceMediaChannel *channel) { | 1276 void WebRtcVoiceEngine::UnregisterChannel(WebRtcVoiceMediaChannel *channel) { |
| 1311 rtc::CritScope lock(&channels_cs_); | 1277 rtc::CritScope lock(&channels_cs_); |
| 1312 ChannelList::iterator i = std::find(channels_.begin(), | 1278 ChannelList::iterator i = std::find(channels_.begin(), |
| 1313 channels_.end(), | 1279 channels_.end(), |
| 1314 channel); | 1280 channel); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1363 if (voe_wrapper_->processing()->StartDebugRecording(aec_dump_file_stream) != | 1329 if (voe_wrapper_->processing()->StartDebugRecording(aec_dump_file_stream) != |
| 1364 webrtc::AudioProcessing::kNoError) { | 1330 webrtc::AudioProcessing::kNoError) { |
| 1365 LOG_RTCERR0(StartDebugRecording); | 1331 LOG_RTCERR0(StartDebugRecording); |
| 1366 fclose(aec_dump_file_stream); | 1332 fclose(aec_dump_file_stream); |
| 1367 return false; | 1333 return false; |
| 1368 } | 1334 } |
| 1369 is_dumping_aec_ = true; | 1335 is_dumping_aec_ = true; |
| 1370 return true; | 1336 return true; |
| 1371 } | 1337 } |
| 1372 | 1338 |
| 1373 bool WebRtcVoiceEngine::RegisterProcessor( | |
| 1374 uint32 ssrc, | |
| 1375 VoiceProcessor* voice_processor, | |
| 1376 MediaProcessorDirection direction) { | |
| 1377 bool register_with_webrtc = false; | |
| 1378 int channel_id = -1; | |
| 1379 bool success = false; | |
| 1380 uint32* processor_ssrc = NULL; | |
| 1381 bool found_channel = FindChannelNumFromSsrc(ssrc, direction, &channel_id); | |
| 1382 if (voice_processor == NULL || !found_channel) { | |
| 1383 LOG(LS_WARNING) << "Media Processing Registration Failed. ssrc: " << ssrc | |
| 1384 << " foundChannel: " << found_channel; | |
| 1385 return false; | |
| 1386 } | |
| 1387 | |
| 1388 webrtc::ProcessingTypes processing_type; | |
| 1389 { | |
| 1390 rtc::CritScope cs(&signal_media_critical_); | |
| 1391 if (direction == MPD_RX) { | |
| 1392 processing_type = webrtc::kPlaybackAllChannelsMixed; | |
| 1393 if (SignalRxMediaFrame.is_empty()) { | |
| 1394 register_with_webrtc = true; | |
| 1395 processor_ssrc = &rx_processor_ssrc_; | |
| 1396 } | |
| 1397 SignalRxMediaFrame.connect(voice_processor, | |
| 1398 &VoiceProcessor::OnFrame); | |
| 1399 } else { | |
| 1400 processing_type = webrtc::kRecordingPerChannel; | |
| 1401 if (SignalTxMediaFrame.is_empty()) { | |
| 1402 register_with_webrtc = true; | |
| 1403 processor_ssrc = &tx_processor_ssrc_; | |
| 1404 } | |
| 1405 SignalTxMediaFrame.connect(voice_processor, | |
| 1406 &VoiceProcessor::OnFrame); | |
| 1407 } | |
| 1408 } | |
| 1409 if (register_with_webrtc) { | |
| 1410 // TODO(janahan): when registering consider instantiating a | |
| 1411 // a VoeMediaProcess object and not make the engine extend the interface. | |
| 1412 if (voe()->media() && voe()->media()-> | |
| 1413 RegisterExternalMediaProcessing(channel_id, | |
| 1414 processing_type, | |
| 1415 *this) != -1) { | |
| 1416 LOG(LS_INFO) << "Media Processing Registration Succeeded. channel:" | |
| 1417 << channel_id; | |
| 1418 *processor_ssrc = ssrc; | |
| 1419 success = true; | |
| 1420 } else { | |
| 1421 LOG_RTCERR2(RegisterExternalMediaProcessing, | |
| 1422 channel_id, | |
| 1423 processing_type); | |
| 1424 success = false; | |
| 1425 } | |
| 1426 } else { | |
| 1427 // If we don't have to register with the engine, we just needed to | |
| 1428 // connect a new processor, set success to true; | |
| 1429 success = true; | |
| 1430 } | |
| 1431 return success; | |
| 1432 } | |
| 1433 | |
| 1434 bool WebRtcVoiceEngine::UnregisterProcessorChannel( | |
| 1435 MediaProcessorDirection channel_direction, | |
| 1436 uint32 ssrc, | |
| 1437 VoiceProcessor* voice_processor, | |
| 1438 MediaProcessorDirection processor_direction) { | |
| 1439 bool success = true; | |
| 1440 FrameSignal* signal; | |
| 1441 webrtc::ProcessingTypes processing_type; | |
| 1442 uint32* processor_ssrc = NULL; | |
| 1443 if (channel_direction == MPD_RX) { | |
| 1444 signal = &SignalRxMediaFrame; | |
| 1445 processing_type = webrtc::kPlaybackAllChannelsMixed; | |
| 1446 processor_ssrc = &rx_processor_ssrc_; | |
| 1447 } else { | |
| 1448 signal = &SignalTxMediaFrame; | |
| 1449 processing_type = webrtc::kRecordingPerChannel; | |
| 1450 processor_ssrc = &tx_processor_ssrc_; | |
| 1451 } | |
| 1452 | |
| 1453 int deregister_id = -1; | |
| 1454 { | |
| 1455 rtc::CritScope cs(&signal_media_critical_); | |
| 1456 if ((processor_direction & channel_direction) != 0 && !signal->is_empty()) { | |
| 1457 signal->disconnect(voice_processor); | |
| 1458 int channel_id = -1; | |
| 1459 bool found_channel = FindChannelNumFromSsrc(ssrc, | |
| 1460 channel_direction, | |
| 1461 &channel_id); | |
| 1462 if (signal->is_empty() && found_channel) { | |
| 1463 deregister_id = channel_id; | |
| 1464 } | |
| 1465 } | |
| 1466 } | |
| 1467 if (deregister_id != -1) { | |
| 1468 if (voe()->media() && | |
| 1469 voe()->media()->DeRegisterExternalMediaProcessing(deregister_id, | |
| 1470 processing_type) != -1) { | |
| 1471 *processor_ssrc = 0; | |
| 1472 LOG(LS_INFO) << "Media Processing DeRegistration Succeeded. channel:" | |
| 1473 << deregister_id; | |
| 1474 } else { | |
| 1475 LOG_RTCERR2(DeRegisterExternalMediaProcessing, | |
| 1476 deregister_id, | |
| 1477 processing_type); | |
| 1478 success = false; | |
| 1479 } | |
| 1480 } | |
| 1481 return success; | |
| 1482 } | |
| 1483 | |
| 1484 bool WebRtcVoiceEngine::UnregisterProcessor( | |
| 1485 uint32 ssrc, | |
| 1486 VoiceProcessor* voice_processor, | |
| 1487 MediaProcessorDirection direction) { | |
| 1488 bool success = true; | |
| 1489 if (voice_processor == NULL) { | |
| 1490 LOG(LS_WARNING) << "Media Processing Deregistration Failed. ssrc: " | |
| 1491 << ssrc; | |
| 1492 return false; | |
| 1493 } | |
| 1494 if (!UnregisterProcessorChannel(MPD_RX, ssrc, voice_processor, direction)) { | |
| 1495 success = false; | |
| 1496 } | |
| 1497 if (!UnregisterProcessorChannel(MPD_TX, ssrc, voice_processor, direction)) { | |
| 1498 success = false; | |
| 1499 } | |
| 1500 return success; | |
| 1501 } | |
| 1502 | |
| 1503 // Implementing method from WebRtc VoEMediaProcess interface | |
| 1504 // Do not lock mux_channel_cs_ in this callback. | |
| 1505 void WebRtcVoiceEngine::Process(int channel, | |
| 1506 webrtc::ProcessingTypes type, | |
| 1507 int16_t audio10ms[], | |
| 1508 size_t length, | |
| 1509 int sampling_freq, | |
| 1510 bool is_stereo) { | |
| 1511 rtc::CritScope cs(&signal_media_critical_); | |
| 1512 AudioFrame frame(audio10ms, length, sampling_freq, is_stereo); | |
| 1513 if (type == webrtc::kPlaybackAllChannelsMixed) { | |
| 1514 SignalRxMediaFrame(rx_processor_ssrc_, MPD_RX, &frame); | |
| 1515 } else if (type == webrtc::kRecordingPerChannel) { | |
| 1516 SignalTxMediaFrame(tx_processor_ssrc_, MPD_TX, &frame); | |
| 1517 } else { | |
| 1518 LOG(LS_WARNING) << "Media Processing invoked unexpectedly." | |
| 1519 << " channel: " << channel << " type: " << type | |
| 1520 << " tx_ssrc: " << tx_processor_ssrc_ | |
| 1521 << " rx_ssrc: " << rx_processor_ssrc_; | |
| 1522 } | |
| 1523 } | |
| 1524 | |
| 1525 void WebRtcVoiceEngine::StartAecDump(const std::string& filename) { | 1339 void WebRtcVoiceEngine::StartAecDump(const std::string& filename) { |
| 1526 if (!is_dumping_aec_) { | 1340 if (!is_dumping_aec_) { |
| 1527 // Start dumping AEC when we are not dumping. | 1341 // Start dumping AEC when we are not dumping. |
| 1528 if (voe_wrapper_->processing()->StartDebugRecording( | 1342 if (voe_wrapper_->processing()->StartDebugRecording( |
| 1529 filename.c_str()) != webrtc::AudioProcessing::kNoError) { | 1343 filename.c_str()) != webrtc::AudioProcessing::kNoError) { |
| 1530 LOG_RTCERR1(StartDebugRecording, filename.c_str()); | 1344 LOG_RTCERR1(StartDebugRecording, filename.c_str()); |
| 1531 } else { | 1345 } else { |
| 1532 is_dumping_aec_ = true; | 1346 is_dumping_aec_ = true; |
| 1533 } | 1347 } |
| 1534 } | 1348 } |
| (...skipping 1959 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3494 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | 3308 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); |
| 3495 return false; | 3309 return false; |
| 3496 } | 3310 } |
| 3497 } | 3311 } |
| 3498 return true; | 3312 return true; |
| 3499 } | 3313 } |
| 3500 | 3314 |
| 3501 } // namespace cricket | 3315 } // namespace cricket |
| 3502 | 3316 |
| 3503 #endif // HAVE_WEBRTC_VOICE | 3317 #endif // HAVE_WEBRTC_VOICE |
| OLD | NEW |