OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
373 codec->pacsize = (codec->plfreq / 1000) * packet_size_ms; | 373 codec->pacsize = (codec->plfreq / 1000) * packet_size_ms; |
374 return true; | 374 return true; |
375 } | 375 } |
376 } | 376 } |
377 } | 377 } |
378 return false; | 378 return false; |
379 } | 379 } |
380 | 380 |
381 static const AudioCodec* GetPreferredCodec( | 381 static const AudioCodec* GetPreferredCodec( |
382 const std::vector<AudioCodec>& codecs, | 382 const std::vector<AudioCodec>& codecs, |
383 webrtc::CodecInst* voe_codec, | 383 webrtc::CodecInst* out, |
384 int* red_payload_type) { | 384 int* red_payload_type) { |
385 RTC_DCHECK(voe_codec); | 385 RTC_DCHECK(out); |
386 RTC_DCHECK(red_payload_type); | 386 RTC_DCHECK(red_payload_type); |
387 // Select the preferred send codec (the first non-telephone-event/CN codec). | 387 // Select the preferred send codec (the first non-telephone-event/CN codec). |
388 for (const AudioCodec& codec : codecs) { | 388 for (const AudioCodec& codec : codecs) { |
389 *red_payload_type = -1; | 389 *red_payload_type = -1; |
390 if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) { | 390 if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) { |
391 // Skip telephone-event/CN codec, which will be handled later. | 391 // Skip telephone-event/CN codec, which will be handled later. |
392 continue; | 392 continue; |
393 } | 393 } |
394 | 394 |
395 // We'll use the first codec in the list to actually send audio data. | 395 // We'll use the first codec in the list to actually send audio data. |
396 // Be sure to use the payload type requested by the remote side. | 396 // Be sure to use the payload type requested by the remote side. |
397 // "red", for RED audio, is a special case where the actual codec to be | 397 // "red", for RED audio, is a special case where the actual codec to be |
398 // used is specified in params. | 398 // used is specified in params. |
399 const AudioCodec* found_codec = &codec; | 399 const AudioCodec* found_codec = &codec; |
400 if (IsCodec(*found_codec, kRedCodecName)) { | 400 if (IsCodec(*found_codec, kRedCodecName)) { |
401 // Parse out the RED parameters. If we fail, just ignore RED; | 401 // Parse out the RED parameters. If we fail, just ignore RED; |
402 // we don't support all possible params/usage scenarios. | 402 // we don't support all possible params/usage scenarios. |
403 *red_payload_type = codec.id; | 403 *red_payload_type = codec.id; |
404 found_codec = GetRedSendCodec(*found_codec, codecs); | 404 found_codec = GetRedSendCodec(*found_codec, codecs); |
405 if (!found_codec) { | 405 if (!found_codec) { |
406 continue; | 406 continue; |
407 } | 407 } |
408 } | 408 } |
409 // Ignore codecs we don't know about. The negotiation step should prevent | 409 // Ignore codecs we don't know about. The negotiation step should prevent |
410 // this, but double-check to be sure. | 410 // this, but double-check to be sure. |
411 if (!ToCodecInst(*found_codec, voe_codec)) { | 411 webrtc::CodecInst voe_codec; |
ossu
2016/03/04 14:40:22
Cannot CodecInst be default-initialized to somethi
ossu
2016/03/04 15:02:02
To answer my own question: Initializing a struct w
the sun
2016/03/04 15:44:02
Done.
| |
412 memset(&voe_codec, 0, sizeof(voe_codec)); | |
413 if (!ToCodecInst(*found_codec, &voe_codec)) { | |
412 LOG(LS_WARNING) << "Unknown codec " << ToString(*found_codec); | 414 LOG(LS_WARNING) << "Unknown codec " << ToString(*found_codec); |
413 continue; | 415 continue; |
414 } | 416 } |
417 *out = voe_codec; | |
415 return found_codec; | 418 return found_codec; |
416 } | 419 } |
417 return nullptr; | 420 return nullptr; |
418 } | 421 } |
419 | 422 |
420 private: | 423 private: |
421 static const int kMaxNumPacketSize = 6; | 424 static const int kMaxNumPacketSize = 6; |
422 struct CodecPref { | 425 struct CodecPref { |
423 const char* name; | 426 const char* name; |
424 int clockrate; | 427 int clockrate; |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
559 LOG(LS_INFO) << "WebRtcVoiceEngine::Init Done!"; | 562 LOG(LS_INFO) << "WebRtcVoiceEngine::Init Done!"; |
560 } else { | 563 } else { |
561 LOG(LS_ERROR) << "WebRtcVoiceEngine::Init failed"; | 564 LOG(LS_ERROR) << "WebRtcVoiceEngine::Init failed"; |
562 Terminate(); | 565 Terminate(); |
563 } | 566 } |
564 return res; | 567 return res; |
565 } | 568 } |
566 | 569 |
567 bool WebRtcVoiceEngine::InitInternal() { | 570 bool WebRtcVoiceEngine::InitInternal() { |
568 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 571 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
569 // Temporarily turn logging level up for the Init call | 572 // Temporarily turn logging level up for the Init call. |
570 webrtc::Trace::set_level_filter(kElevatedTraceFilter); | 573 webrtc::Trace::set_level_filter(kElevatedTraceFilter); |
571 LOG(LS_INFO) << webrtc::VoiceEngine::GetVersionString(); | 574 LOG(LS_INFO) << webrtc::VoiceEngine::GetVersionString(); |
572 if (voe_wrapper_->base()->Init(adm_) == -1) { | 575 if (voe_wrapper_->base()->Init(adm_) == -1) { |
573 LOG_RTCERR0_EX(Init, voe_wrapper_->error()); | 576 LOG_RTCERR0_EX(Init, voe_wrapper_->error()); |
574 return false; | 577 return false; |
575 } | 578 } |
576 webrtc::Trace::set_level_filter(kDefaultTraceFilter); | 579 webrtc::Trace::set_level_filter(kDefaultTraceFilter); |
577 | 580 |
578 // Save the default AGC configuration settings. This must happen before | 581 // Save the default AGC configuration settings. This must happen before |
579 // calling ApplyOptions or the default will be overwritten. | 582 // calling ApplyOptions or the default will be overwritten. |
(...skipping 16 matching lines...) Expand all Loading... | |
596 options.adjust_agc_delta = rtc::Optional<int>(0); | 599 options.adjust_agc_delta = rtc::Optional<int>(0); |
597 options.experimental_agc = rtc::Optional<bool>(false); | 600 options.experimental_agc = rtc::Optional<bool>(false); |
598 options.extended_filter_aec = rtc::Optional<bool>(false); | 601 options.extended_filter_aec = rtc::Optional<bool>(false); |
599 options.delay_agnostic_aec = rtc::Optional<bool>(false); | 602 options.delay_agnostic_aec = rtc::Optional<bool>(false); |
600 options.experimental_ns = rtc::Optional<bool>(false); | 603 options.experimental_ns = rtc::Optional<bool>(false); |
601 if (!ApplyOptions(options)) { | 604 if (!ApplyOptions(options)) { |
602 return false; | 605 return false; |
603 } | 606 } |
604 } | 607 } |
605 | 608 |
606 // Print our codec list again for the call diagnostic log | 609 // Print our codec list again for the call diagnostic log. |
607 LOG(LS_INFO) << "WebRtc VoiceEngine codecs:"; | 610 LOG(LS_INFO) << "WebRtc VoiceEngine codecs:"; |
608 for (const AudioCodec& codec : codecs_) { | 611 for (const AudioCodec& codec : codecs_) { |
609 LOG(LS_INFO) << ToString(codec); | 612 LOG(LS_INFO) << ToString(codec); |
610 } | 613 } |
611 | 614 |
612 SetDefaultDevices(); | 615 SetDefaultDevices(); |
613 | 616 |
614 initialized_ = true; | 617 initialized_ = true; |
615 return true; | 618 return true; |
616 } | 619 } |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
996 rtc::LoggingSeverity sev = rtc::LS_VERBOSE; | 999 rtc::LoggingSeverity sev = rtc::LS_VERBOSE; |
997 if (level == webrtc::kTraceError || level == webrtc::kTraceCritical) | 1000 if (level == webrtc::kTraceError || level == webrtc::kTraceCritical) |
998 sev = rtc::LS_ERROR; | 1001 sev = rtc::LS_ERROR; |
999 else if (level == webrtc::kTraceWarning) | 1002 else if (level == webrtc::kTraceWarning) |
1000 sev = rtc::LS_WARNING; | 1003 sev = rtc::LS_WARNING; |
1001 else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo) | 1004 else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo) |
1002 sev = rtc::LS_INFO; | 1005 sev = rtc::LS_INFO; |
1003 else if (level == webrtc::kTraceTerseInfo) | 1006 else if (level == webrtc::kTraceTerseInfo) |
1004 sev = rtc::LS_INFO; | 1007 sev = rtc::LS_INFO; |
1005 | 1008 |
1006 // Skip past boilerplate prefix text | 1009 // Skip past boilerplate prefix text. |
1007 if (length < 72) { | 1010 if (length < 72) { |
1008 std::string msg(trace, length); | 1011 std::string msg(trace, length); |
1009 LOG(LS_ERROR) << "Malformed webrtc log message: "; | 1012 LOG(LS_ERROR) << "Malformed webrtc log message: "; |
1010 LOG_V(sev) << msg; | 1013 LOG_V(sev) << msg; |
1011 } else { | 1014 } else { |
1012 std::string msg(trace + 71, length - 72); | 1015 std::string msg(trace + 71, length - 72); |
1013 LOG_V(sev) << "webrtc: " << msg; | 1016 LOG_V(sev) << "webrtc: " << msg; |
1014 } | 1017 } |
1015 } | 1018 } |
1016 | 1019 |
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1511 recv_codecs_ = codecs; | 1514 recv_codecs_ = codecs; |
1512 } | 1515 } |
1513 | 1516 |
1514 if (desired_playout_ && !playout_) { | 1517 if (desired_playout_ && !playout_) { |
1515 ResumePlayout(); | 1518 ResumePlayout(); |
1516 } | 1519 } |
1517 return result; | 1520 return result; |
1518 } | 1521 } |
1519 | 1522 |
1520 bool WebRtcVoiceMediaChannel::SetSendCodecs( | 1523 bool WebRtcVoiceMediaChannel::SetSendCodecs( |
1521 int channel, const std::vector<AudioCodec>& codecs) { | 1524 const std::vector<AudioCodec>& codecs) { |
1525 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | |
1526 // TODO(solenberg): Validate input - that payload types don't overlap, are | |
1527 // within range, filter out codecs we don't support, | |
1528 // redundant codecs etc. | |
1529 | |
1530 // Find the DTMF telephone event "codec" payload type. | |
1531 dtmf_payload_type_ = rtc::Optional<int>(); | |
1532 for (const AudioCodec& codec : codecs) { | |
1533 if (IsCodec(codec, kDtmfCodecName)) { | |
1534 dtmf_payload_type_ = rtc::Optional<int>(codec.id); | |
1535 break; | |
1536 } | |
1537 } | |
1538 | |
1539 // Scan through the list to figure out the codec to use for sending, along | |
1540 // with the proper configuration for VAD, CNG, RED, NACK and Opus-specific | |
1541 // parameters. | |
1542 { | |
1543 SendCodecSpec send_codec_spec; | |
1544 send_codec_spec.nack_enabled = send_codec_spec_.nack_enabled; | |
1545 | |
1546 // Find send codec (the first non-telephone-event/CN codec). | |
1547 const AudioCodec* codec = WebRtcVoiceCodecs::GetPreferredCodec( | |
1548 codecs, &send_codec_spec.codec_inst, &send_codec_spec.red_payload_type); | |
1549 if (!codec) { | |
1550 LOG(LS_WARNING) << "Received empty list of codecs."; | |
1551 return false; | |
1552 } | |
1553 | |
1554 send_codec_spec.transport_cc_enabled = HasTransportCc(*codec); | |
1555 | |
1556 // TODO(solenberg): This is a curious condition - kept for legacy reasons - | |
1557 // why would we only want to figure out these parameters | |
1558 // when RED is disabled? | |
ossu
2016/03/04 14:40:22
Maybe it's not possible to set opus (well, sub-enc
minyue-webrtc
2016/03/08 10:19:47
I think it was because Opus cannot have RED and FE
the sun
2016/03/08 12:04:02
Thanks for clarifying. Added a comment. I think we
| |
1559 if (send_codec_spec.red_payload_type == -1) { | |
1560 send_codec_spec.nack_enabled = HasNack(*codec); | |
1561 // For Opus as the send codec, we are to determine inband FEC, maximum | |
1562 // playback rate, and opus internal dtx. | |
1563 if (IsCodec(*codec, kOpusCodecName)) { | |
1564 GetOpusConfig(*codec, &send_codec_spec.codec_inst, | |
1565 &send_codec_spec.enable_codec_fec, | |
1566 &send_codec_spec.opus_max_playback_rate, | |
1567 &send_codec_spec.enable_opus_dtx); | |
1568 } | |
1569 | |
1570 // Set packet size if the AudioCodec param kCodecParamPTime is set. | |
1571 int ptime_ms = 0; | |
1572 if (codec->GetParam(kCodecParamPTime, &ptime_ms)) { | |
1573 if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize( | |
1574 &send_codec_spec.codec_inst, ptime_ms)) { | |
1575 LOG(LS_WARNING) << "Failed to set packet size for codec " | |
1576 << send_codec_spec.codec_inst.plname; | |
1577 return false; | |
1578 } | |
1579 } | |
1580 } | |
1581 | |
1582 // Loop through the codecs list again to find the CN codec. | |
1583 for (const AudioCodec& codec : codecs) { | |
1584 // Ignore codecs we don't know about. The negotiation step should prevent | |
1585 // this, but double-check to be sure. | |
1586 webrtc::CodecInst voe_codec; | |
1587 if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { | |
1588 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | |
1589 continue; | |
1590 } | |
1591 | |
1592 if (IsCodec(codec, kCnCodecName)) { | |
1593 // Turn voice activity detection/comfort noise on if supported. | |
1594 // Set the wideband CN payload type appropriately. | |
1595 // (narrowband always uses the static payload type 13). | |
1596 int cng_plfreq = -1; | |
1597 switch (codec.clockrate) { | |
1598 case 8000: | |
1599 case 16000: | |
1600 case 32000: | |
1601 cng_plfreq = codec.clockrate; | |
1602 break; | |
1603 default: | |
1604 LOG(LS_WARNING) << "CN frequency " << codec.clockrate | |
1605 << " not supported."; | |
1606 continue; | |
1607 } | |
1608 send_codec_spec.cng_payload_type = codec.id; | |
1609 send_codec_spec.cng_plfreq = cng_plfreq; | |
1610 break; | |
1611 } | |
1612 } | |
1613 | |
1614 send_codec_spec_ = std::move(send_codec_spec); | |
1615 } | |
1616 | |
1617 // Cache the codecs in order to configure the channel created later. | |
1618 for (const auto& ch : send_streams_) { | |
1619 if (!SetSendCodecs(ch.second->channel())) { | |
1620 return false; | |
1621 } | |
1622 } | |
1623 | |
1624 // Set nack status on receive channels and update |nack_enabled_|. | |
1625 if (!send_streams_.empty()) { | |
1626 for (const auto& kv : recv_streams_) { | |
1627 SetNack(kv.second->channel(), send_codec_spec_.nack_enabled); | |
1628 } | |
1629 } | |
1630 | |
1631 // Check if the transport cc feedback has changed on the preferred send codec, | |
1632 // and in that case reconfigure all receive streams. | |
1633 if (recv_transport_cc_enabled_ != send_codec_spec_.transport_cc_enabled) { | |
1634 LOG(LS_INFO) << "Recreate all the receive streams because the send " | |
1635 "codec has changed."; | |
1636 recv_transport_cc_enabled_ = send_codec_spec_.transport_cc_enabled; | |
1637 for (auto& kv : recv_streams_) { | |
1638 kv.second->RecreateAudioReceiveStream(recv_transport_cc_enabled_); | |
1639 } | |
1640 } | |
1641 | |
1642 return true; | |
1643 } | |
1644 | |
1645 bool WebRtcVoiceMediaChannel::SetSendCodecs(int channel) { | |
1522 // Disable VAD, FEC, and RED unless we know the other side wants them. | 1646 // Disable VAD, FEC, and RED unless we know the other side wants them. |
1523 engine()->voe()->codec()->SetVADStatus(channel, false); | 1647 engine()->voe()->codec()->SetVADStatus(channel, false); |
1524 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); | 1648 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); |
1525 engine()->voe()->rtp()->SetREDStatus(channel, false); | 1649 engine()->voe()->rtp()->SetREDStatus(channel, false); |
1526 engine()->voe()->codec()->SetFECStatus(channel, false); | 1650 engine()->voe()->codec()->SetFECStatus(channel, false); |
1527 | 1651 |
1528 // Scan through the list to figure out the codec to use for sending, along | 1652 if (send_codec_spec_.red_payload_type != -1) { |
1529 // with the proper configuration for VAD. | 1653 // Enable redundant encoding of the specified codec. Treat any |
1530 webrtc::CodecInst send_codec; | 1654 // failure as a fatal internal error. |
1531 memset(&send_codec, 0, sizeof(send_codec)); | 1655 LOG(LS_INFO) << "Enabling RED on channel " << channel; |
1532 | 1656 if (engine()->voe()->rtp()->SetREDStatus(channel, true, |
1533 bool nack_enabled = nack_enabled_; | 1657 send_codec_spec_.red_payload_type) == -1) { |
1534 bool enable_codec_fec = false; | 1658 LOG_RTCERR3(SetREDStatus, channel, true, |
1535 bool enable_opus_dtx = false; | 1659 send_codec_spec_.red_payload_type); |
1536 int opus_max_playback_rate = 0; | 1660 return false; |
1537 int red_payload_type = -1; | |
1538 | |
1539 // Set send codec (the first non-telephone-event/CN codec) | |
1540 const AudioCodec* codec = WebRtcVoiceCodecs::GetPreferredCodec( | |
1541 codecs, &send_codec, &red_payload_type); | |
1542 if (codec) { | |
1543 if (red_payload_type != -1) { | |
1544 // Enable redundant encoding of the specified codec. Treat any | |
1545 // failure as a fatal internal error. | |
1546 LOG(LS_INFO) << "Enabling RED on channel " << channel; | |
1547 if (engine()->voe()->rtp()->SetREDStatus(channel, true, | |
1548 red_payload_type) == -1) { | |
1549 LOG_RTCERR3(SetREDStatus, channel, true, red_payload_type); | |
1550 return false; | |
1551 } | |
1552 } else { | |
1553 nack_enabled = HasNack(*codec); | |
1554 // For Opus as the send codec, we are to determine inband FEC, maximum | |
1555 // playback rate, and opus internal dtx. | |
1556 if (IsCodec(*codec, kOpusCodecName)) { | |
1557 GetOpusConfig(*codec, &send_codec, &enable_codec_fec, | |
1558 &opus_max_playback_rate, &enable_opus_dtx); | |
1559 } | |
1560 | |
1561 // Set packet size if the AudioCodec param kCodecParamPTime is set. | |
1562 int ptime_ms = 0; | |
1563 if (codec->GetParam(kCodecParamPTime, &ptime_ms)) { | |
1564 if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(&send_codec, ptime_ms)) { | |
1565 LOG(LS_WARNING) << "Failed to set packet size for codec " | |
1566 << send_codec.plname; | |
1567 return false; | |
1568 } | |
1569 } | |
1570 } | 1661 } |
1571 } | 1662 } |
1572 | 1663 |
1573 if (nack_enabled_ != nack_enabled) { | 1664 SetNack(channel, send_codec_spec_.nack_enabled); |
1574 SetNack(channel, nack_enabled); | 1665 |
1575 nack_enabled_ = nack_enabled; | 1666 // Set the codec immediately, since SetVADStatus() depends on whether |
1576 } | 1667 // the current codec is mono or stereo. |
1577 if (!codec) { | 1668 if (!SetSendCodec(channel, send_codec_spec_.codec_inst)) { |
1578 LOG(LS_WARNING) << "Received empty list of codecs."; | |
1579 return false; | 1669 return false; |
1580 } | 1670 } |
1581 | 1671 |
1582 // Set the codec immediately, since SetVADStatus() depends on whether | |
1583 // the current codec is mono or stereo. | |
1584 if (!SetSendCodec(channel, send_codec)) | |
1585 return false; | |
1586 | |
1587 // FEC should be enabled after SetSendCodec. | 1672 // FEC should be enabled after SetSendCodec. |
1588 if (enable_codec_fec) { | 1673 if (send_codec_spec_.enable_codec_fec) { |
1589 LOG(LS_INFO) << "Attempt to enable codec internal FEC on channel " | 1674 LOG(LS_INFO) << "Attempt to enable codec internal FEC on channel " |
1590 << channel; | 1675 << channel; |
1591 if (engine()->voe()->codec()->SetFECStatus(channel, true) == -1) { | 1676 if (engine()->voe()->codec()->SetFECStatus(channel, true) == -1) { |
1592 // Enable codec internal FEC. Treat any failure as fatal internal error. | 1677 // Enable codec internal FEC. Treat any failure as fatal internal error. |
1593 LOG_RTCERR2(SetFECStatus, channel, true); | 1678 LOG_RTCERR2(SetFECStatus, channel, true); |
1594 return false; | 1679 return false; |
1595 } | 1680 } |
1596 } | 1681 } |
1597 | 1682 |
1598 if (IsCodec(send_codec, kOpusCodecName)) { | 1683 if (IsCodec(send_codec_spec_.codec_inst, kOpusCodecName)) { |
1599 // DTX and maxplaybackrate should be set after SetSendCodec. Because current | 1684 // DTX and maxplaybackrate should be set after SetSendCodec. Because current |
1600 // send codec has to be Opus. | 1685 // send codec has to be Opus. |
1601 | 1686 |
1602 // Set Opus internal DTX. | 1687 // Set Opus internal DTX. |
1603 LOG(LS_INFO) << "Attempt to " | 1688 LOG(LS_INFO) << "Attempt to " |
1604 << (enable_opus_dtx ? "enable" : "disable") | 1689 << (send_codec_spec_.enable_opus_dtx ? "enable" : "disable") |
1605 << " Opus DTX on channel " | 1690 << " Opus DTX on channel " |
1606 << channel; | 1691 << channel; |
1607 if (engine()->voe()->codec()->SetOpusDtx(channel, enable_opus_dtx)) { | 1692 if (engine()->voe()->codec()->SetOpusDtx(channel, |
1608 LOG_RTCERR2(SetOpusDtx, channel, enable_opus_dtx); | 1693 send_codec_spec_.enable_opus_dtx)) { |
1694 LOG_RTCERR2(SetOpusDtx, channel, send_codec_spec_.enable_opus_dtx); | |
1609 return false; | 1695 return false; |
1610 } | 1696 } |
1611 | 1697 |
1612 // If opus_max_playback_rate <= 0, the default maximum playback rate | 1698 // If opus_max_playback_rate <= 0, the default maximum playback rate |
1613 // (48 kHz) will be used. | 1699 // (48 kHz) will be used. |
1614 if (opus_max_playback_rate > 0) { | 1700 if (send_codec_spec_.opus_max_playback_rate > 0) { |
1615 LOG(LS_INFO) << "Attempt to set maximum playback rate to " | 1701 LOG(LS_INFO) << "Attempt to set maximum playback rate to " |
1616 << opus_max_playback_rate | 1702 << send_codec_spec_.opus_max_playback_rate |
1617 << " Hz on channel " | 1703 << " Hz on channel " |
1618 << channel; | 1704 << channel; |
1619 if (engine()->voe()->codec()->SetOpusMaxPlaybackRate( | 1705 if (engine()->voe()->codec()->SetOpusMaxPlaybackRate( |
1620 channel, opus_max_playback_rate) == -1) { | 1706 channel, send_codec_spec_.opus_max_playback_rate) == -1) { |
1621 LOG_RTCERR2(SetOpusMaxPlaybackRate, channel, opus_max_playback_rate); | 1707 LOG_RTCERR2(SetOpusMaxPlaybackRate, channel, |
1708 send_codec_spec_.opus_max_playback_rate); | |
1622 return false; | 1709 return false; |
1623 } | 1710 } |
1624 } | 1711 } |
1625 } | 1712 } |
1626 | 1713 |
1627 // Always update the |send_codec_| to the currently set send codec. | |
1628 send_codec_.reset(new webrtc::CodecInst(send_codec)); | |
1629 | |
1630 if (send_bitrate_setting_) { | 1714 if (send_bitrate_setting_) { |
1631 SetSendBitrateInternal(send_bitrate_bps_); | 1715 SetSendBitrateInternal(send_bitrate_bps_); |
1632 } | 1716 } |
1633 | 1717 |
1634 // Loop through the codecs list again to config the CN codec. | 1718 // Set the CN payloadtype and the VAD status. |
1635 for (const AudioCodec& codec : codecs) { | 1719 if (send_codec_spec_.cng_payload_type != -1) { |
1636 // Ignore codecs we don't know about. The negotiation step should prevent | 1720 // The CN payload type for 8000 Hz clockrate is fixed at 13. |
1637 // this, but double-check to be sure. | 1721 if (send_codec_spec_.cng_plfreq != 8000) { |
1638 webrtc::CodecInst voe_codec; | 1722 webrtc::PayloadFrequencies cn_freq = webrtc::kFreq8000Hz; |
ossu
2016/03/04 14:40:22
This seems ... odd. Why is cn_freq defaulted to 80
the sun
2016/03/04 15:44:03
Done.
| |
1639 if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { | 1723 switch (send_codec_spec_.cng_plfreq) { |
1640 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | |
1641 continue; | |
1642 } | |
1643 | |
1644 if (IsCodec(codec, kCnCodecName)) { | |
1645 // Turn voice activity detection/comfort noise on if supported. | |
1646 // Set the wideband CN payload type appropriately. | |
1647 // (narrowband always uses the static payload type 13). | |
1648 webrtc::PayloadFrequencies cn_freq; | |
1649 switch (codec.clockrate) { | |
1650 case 8000: | |
1651 cn_freq = webrtc::kFreq8000Hz; | |
1652 break; | |
1653 case 16000: | 1724 case 16000: |
1654 cn_freq = webrtc::kFreq16000Hz; | 1725 cn_freq = webrtc::kFreq16000Hz; |
1655 break; | 1726 break; |
1656 case 32000: | 1727 case 32000: |
1657 cn_freq = webrtc::kFreq32000Hz; | 1728 cn_freq = webrtc::kFreq32000Hz; |
1658 break; | 1729 break; |
1659 default: | 1730 default: |
1660 LOG(LS_WARNING) << "CN frequency " << codec.clockrate | 1731 RTC_NOTREACHED(); |
1661 << " not supported."; | 1732 break; |
1662 continue; | |
1663 } | 1733 } |
1664 // Set the CN payloadtype and the VAD status. | 1734 if (engine()->voe()->codec()->SetSendCNPayloadType( |
1665 // The CN payload type for 8000 Hz clockrate is fixed at 13. | 1735 channel, send_codec_spec_.cng_payload_type, cn_freq) == -1) { |
1666 if (cn_freq != webrtc::kFreq8000Hz) { | 1736 LOG_RTCERR3(SetSendCNPayloadType, channel, |
1667 if (engine()->voe()->codec()->SetSendCNPayloadType( | 1737 send_codec_spec_.cng_payload_type, cn_freq); |
1668 channel, codec.id, cn_freq) == -1) { | 1738 // TODO(ajm): This failure condition will be removed from VoE. |
1669 LOG_RTCERR3(SetSendCNPayloadType, channel, codec.id, cn_freq); | 1739 // Restore the return here when we update to a new enough webrtc. |
1670 // TODO(ajm): This failure condition will be removed from VoE. | 1740 // |
1671 // Restore the return here when we update to a new enough webrtc. | 1741 // Not returning false because the SetSendCNPayloadType will fail if |
1672 // | 1742 // the channel is already sending. |
1673 // Not returning false because the SetSendCNPayloadType will fail if | 1743 // This can happen if the remote description is applied twice, for |
1674 // the channel is already sending. | 1744 // example in the case of ROAP on top of JSEP, where both side will |
1675 // This can happen if the remote description is applied twice, for | 1745 // send the offer. |
1676 // example in the case of ROAP on top of JSEP, where both side will | |
1677 // send the offer. | |
1678 } | |
1679 } | 1746 } |
1680 // Only turn on VAD if we have a CN payload type that matches the | 1747 } |
1681 // clockrate for the codec we are going to use. | 1748 |
1682 if (codec.clockrate == send_codec.plfreq && send_codec.channels != 2) { | 1749 // Only turn on VAD if we have a CN payload type that matches the |
1683 // TODO(minyue): If CN frequency == 48000 Hz is allowed, consider the | 1750 // clockrate for the codec we are going to use. |
1684 // interaction between VAD and Opus FEC. | 1751 if (send_codec_spec_.cng_plfreq == send_codec_spec_.codec_inst.plfreq && |
1685 LOG(LS_INFO) << "Enabling VAD"; | 1752 send_codec_spec_.codec_inst.channels != 2) { |
ossu
2016/03/04 14:40:22
Probably never going to happen, and not your code
the sun
2016/03/04 15:44:03
I would assume not. :)
| |
1686 if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) { | 1753 // TODO(minyue): If CN frequency == 48000 Hz is allowed, consider the |
1687 LOG_RTCERR2(SetVADStatus, channel, true); | 1754 // interaction between VAD and Opus FEC. |
1688 return false; | 1755 LOG(LS_INFO) << "Enabling VAD"; |
1689 } | 1756 if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) { |
1757 LOG_RTCERR2(SetVADStatus, channel, true); | |
1758 return false; | |
1690 } | 1759 } |
1691 } | 1760 } |
1692 } | 1761 } |
1693 return true; | 1762 return true; |
1694 } | 1763 } |
1695 | 1764 |
1696 bool WebRtcVoiceMediaChannel::SetSendCodecs( | |
1697 const std::vector<AudioCodec>& codecs) { | |
1698 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | |
1699 // TODO(solenberg): Validate input - that payload types don't overlap, are | |
1700 // within range, filter out codecs we don't support, | |
1701 // redundant codecs etc. | |
1702 | |
1703 // Find the DTMF telephone event "codec" payload type. | |
1704 dtmf_payload_type_ = rtc::Optional<int>(); | |
1705 for (const AudioCodec& codec : codecs) { | |
1706 if (IsCodec(codec, kDtmfCodecName)) { | |
1707 dtmf_payload_type_ = rtc::Optional<int>(codec.id); | |
1708 break; | |
1709 } | |
1710 } | |
1711 | |
1712 // Cache the codecs in order to configure the channel created later. | |
1713 send_codecs_ = codecs; | |
1714 for (const auto& ch : send_streams_) { | |
1715 if (!SetSendCodecs(ch.second->channel(), codecs)) { | |
1716 return false; | |
1717 } | |
1718 } | |
1719 | |
1720 // Set nack status on receive channels and update |nack_enabled_|. | |
1721 for (const auto& ch : recv_streams_) { | |
1722 SetNack(ch.second->channel(), nack_enabled_); | |
1723 } | |
1724 | |
1725 // Check if the transport cc feedback has changed on the preferred send codec, | |
1726 // and in that case reconfigure all receive streams. | |
1727 webrtc::CodecInst voe_codec; | |
1728 int red_payload_type; | |
1729 const AudioCodec* send_codec = WebRtcVoiceCodecs::GetPreferredCodec( | |
1730 send_codecs_, &voe_codec, &red_payload_type); | |
1731 if (send_codec) { | |
1732 bool transport_cc = HasTransportCc(*send_codec); | |
1733 if (transport_cc_enabled_ != transport_cc) { | |
1734 LOG(LS_INFO) << "Recreate all the receive streams because the send " | |
1735 "codec has changed."; | |
1736 transport_cc_enabled_ = transport_cc; | |
1737 for (auto& kv : recv_streams_) { | |
1738 RTC_DCHECK(kv.second != nullptr); | |
1739 kv.second->RecreateAudioReceiveStream(transport_cc_enabled_); | |
1740 } | |
1741 } | |
1742 } | |
1743 | |
1744 return true; | |
1745 } | |
1746 | |
1747 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) { | 1765 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) { |
1748 if (nack_enabled) { | 1766 if (nack_enabled) { |
1749 LOG(LS_INFO) << "Enabling NACK for channel " << channel; | 1767 LOG(LS_INFO) << "Enabling NACK for channel " << channel; |
1750 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets); | 1768 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets); |
1751 } else { | 1769 } else { |
1752 LOG(LS_INFO) << "Disabling NACK for channel " << channel; | 1770 LOG(LS_INFO) << "Disabling NACK for channel " << channel; |
1753 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); | 1771 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); |
1754 } | 1772 } |
1755 } | 1773 } |
1756 | 1774 |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1922 // Save the channel to send_streams_, so that RemoveSendStream() can still | 1940 // Save the channel to send_streams_, so that RemoveSendStream() can still |
1923 // delete the channel in case failure happens below. | 1941 // delete the channel in case failure happens below. |
1924 webrtc::AudioTransport* audio_transport = | 1942 webrtc::AudioTransport* audio_transport = |
1925 engine()->voe()->base()->audio_transport(); | 1943 engine()->voe()->base()->audio_transport(); |
1926 send_streams_.insert(std::make_pair(ssrc, new WebRtcAudioSendStream( | 1944 send_streams_.insert(std::make_pair(ssrc, new WebRtcAudioSendStream( |
1927 channel, audio_transport, ssrc, sp.cname, send_rtp_extensions_, call_))); | 1945 channel, audio_transport, ssrc, sp.cname, send_rtp_extensions_, call_))); |
1928 | 1946 |
1929 // Set the current codecs to be used for the new channel. We need to do this | 1947 // Set the current codecs to be used for the new channel. We need to do this |
1930 // after adding the channel to send_channels_, because of how max bitrate is | 1948 // after adding the channel to send_channels_, because of how max bitrate is |
1931 // currently being configured by SetSendCodec(). | 1949 // currently being configured by SetSendCodec(). |
1932 if (!send_codecs_.empty() && !SetSendCodecs(channel, send_codecs_)) { | 1950 if (HasSendCodec() && !SetSendCodecs(channel)) { |
1933 RemoveSendStream(ssrc); | 1951 RemoveSendStream(ssrc); |
1934 return false; | 1952 return false; |
1935 } | 1953 } |
1936 | 1954 |
1937 // At this point the channel's local SSRC has been updated. If the channel is | 1955 // At this point the channel's local SSRC has been updated. If the channel is |
1938 // the first send channel make sure that all the receive channels are updated | 1956 // the first send channel make sure that all the receive channels are updated |
1939 // with the same SSRC in order to send receiver reports. | 1957 // with the same SSRC in order to send receiver reports. |
1940 if (send_streams_.size() == 1) { | 1958 if (send_streams_.size() == 1) { |
1941 receiver_reports_ssrc_ = ssrc; | 1959 receiver_reports_ssrc_ = ssrc; |
1942 for (const auto& stream : recv_streams_) { | 1960 for (const auto& stream : recv_streams_) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2040 | 2058 |
2041 const int send_channel = GetSendChannelId(receiver_reports_ssrc_); | 2059 const int send_channel = GetSendChannelId(receiver_reports_ssrc_); |
2042 if (send_channel != -1) { | 2060 if (send_channel != -1) { |
2043 // Associate receive channel with first send channel (so the receive channel | 2061 // Associate receive channel with first send channel (so the receive channel |
2044 // can obtain RTT from the send channel) | 2062 // can obtain RTT from the send channel) |
2045 engine()->voe()->base()->AssociateSendChannel(channel, send_channel); | 2063 engine()->voe()->base()->AssociateSendChannel(channel, send_channel); |
2046 LOG(LS_INFO) << "VoiceEngine channel #" << channel | 2064 LOG(LS_INFO) << "VoiceEngine channel #" << channel |
2047 << " is associated with channel #" << send_channel << "."; | 2065 << " is associated with channel #" << send_channel << "."; |
2048 } | 2066 } |
2049 | 2067 |
2050 transport_cc_enabled_ = | |
2051 !send_codecs_.empty() ? HasTransportCc(send_codecs_[0]) : false; | |
2052 | |
2053 recv_streams_.insert(std::make_pair( | 2068 recv_streams_.insert(std::make_pair( |
2054 ssrc, new WebRtcAudioReceiveStream(channel, ssrc, receiver_reports_ssrc_, | 2069 ssrc, new WebRtcAudioReceiveStream(channel, ssrc, receiver_reports_ssrc_, |
2055 transport_cc_enabled_, sp.sync_label, | 2070 recv_transport_cc_enabled_, |
2056 recv_rtp_extensions_, call_))); | 2071 sp.sync_label, recv_rtp_extensions_, |
2072 call_))); | |
2057 | 2073 |
2058 SetNack(channel, nack_enabled_); | 2074 SetNack(channel, send_codec_spec_.nack_enabled); |
2059 SetPlayout(channel, playout_); | 2075 SetPlayout(channel, playout_); |
2060 | 2076 |
2061 return true; | 2077 return true; |
2062 } | 2078 } |
2063 | 2079 |
2064 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { | 2080 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { |
2065 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 2081 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
2066 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; | 2082 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; |
2067 | 2083 |
2068 const auto it = recv_streams_.find(ssrc); | 2084 const auto it = recv_streams_.find(ssrc); |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2352 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBandwidth."; | 2368 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBandwidth."; |
2353 return SetSendBitrateInternal(bps); | 2369 return SetSendBitrateInternal(bps); |
2354 } | 2370 } |
2355 | 2371 |
2356 bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) { | 2372 bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) { |
2357 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendBitrateInternal."; | 2373 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendBitrateInternal."; |
2358 | 2374 |
2359 send_bitrate_setting_ = true; | 2375 send_bitrate_setting_ = true; |
2360 send_bitrate_bps_ = bps; | 2376 send_bitrate_bps_ = bps; |
2361 | 2377 |
2362 if (!send_codec_) { | 2378 if (!HasSendCodec()) { |
2363 LOG(LS_INFO) << "The send codec has not been set up yet. " | 2379 LOG(LS_INFO) << "The send codec has not been set up yet. " |
2364 << "The send bitrate setting will be applied later."; | 2380 << "The send bitrate setting will be applied later."; |
2365 return true; | 2381 return true; |
2366 } | 2382 } |
2367 | 2383 |
2368 // Bitrate is auto by default. | 2384 // Bitrate is auto by default. |
2369 // TODO(bemasc): Fix this so that if SetMaxSendBandwidth(50) is followed by | 2385 // TODO(bemasc): Fix this so that if SetMaxSendBandwidth(50) is followed by |
2370 // SetMaxSendBandwith(0), the second call removes the previous limit. | 2386 // SetMaxSendBandwith(0), the second call removes the previous limit. |
2371 if (bps <= 0) | 2387 if (bps <= 0) |
2372 return true; | 2388 return true; |
2373 | 2389 |
2374 webrtc::CodecInst codec = *send_codec_; | 2390 webrtc::CodecInst codec = send_codec_spec_.codec_inst; |
2375 bool is_multi_rate = WebRtcVoiceCodecs::IsCodecMultiRate(codec); | 2391 bool is_multi_rate = WebRtcVoiceCodecs::IsCodecMultiRate(codec); |
2376 | 2392 |
2377 if (is_multi_rate) { | 2393 if (is_multi_rate) { |
2378 // If codec is multi-rate then just set the bitrate. | 2394 // If codec is multi-rate then just set the bitrate. |
2379 codec.rate = bps; | 2395 codec.rate = bps; |
2380 for (const auto& ch : send_streams_) { | 2396 for (const auto& ch : send_streams_) { |
2381 if (!SetSendCodec(ch.second->channel(), codec)) { | 2397 if (!SetSendCodec(ch.second->channel(), codec)) { |
2382 LOG(LS_INFO) << "Failed to set codec " << codec.plname | 2398 LOG(LS_INFO) << "Failed to set codec " << codec.plname |
2383 << " to bitrate " << bps << " bps."; | 2399 << " to bitrate " << bps << " bps."; |
2384 return false; | 2400 return false; |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2520 } | 2536 } |
2521 } else { | 2537 } else { |
2522 LOG(LS_INFO) << "Stopping playout for channel #" << channel; | 2538 LOG(LS_INFO) << "Stopping playout for channel #" << channel; |
2523 engine()->voe()->base()->StopPlayout(channel); | 2539 engine()->voe()->base()->StopPlayout(channel); |
2524 } | 2540 } |
2525 return true; | 2541 return true; |
2526 } | 2542 } |
2527 } // namespace cricket | 2543 } // namespace cricket |
2528 | 2544 |
2529 #endif // HAVE_WEBRTC_VOICE | 2545 #endif // HAVE_WEBRTC_VOICE |
OLD | NEW |