| 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 = {0}; |
| 412 if (!ToCodecInst(*found_codec, &voe_codec)) { |
| 412 LOG(LS_WARNING) << "Unknown codec " << ToString(*found_codec); | 413 LOG(LS_WARNING) << "Unknown codec " << ToString(*found_codec); |
| 413 continue; | 414 continue; |
| 414 } | 415 } |
| 416 *out = voe_codec; |
| 415 return found_codec; | 417 return found_codec; |
| 416 } | 418 } |
| 417 return nullptr; | 419 return nullptr; |
| 418 } | 420 } |
| 419 | 421 |
| 420 private: | 422 private: |
| 421 static const int kMaxNumPacketSize = 6; | 423 static const int kMaxNumPacketSize = 6; |
| 422 struct CodecPref { | 424 struct CodecPref { |
| 423 const char* name; | 425 const char* name; |
| 424 int clockrate; | 426 int clockrate; |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 LOG(LS_INFO) << "WebRtcVoiceEngine::Init Done!"; | 561 LOG(LS_INFO) << "WebRtcVoiceEngine::Init Done!"; |
| 560 } else { | 562 } else { |
| 561 LOG(LS_ERROR) << "WebRtcVoiceEngine::Init failed"; | 563 LOG(LS_ERROR) << "WebRtcVoiceEngine::Init failed"; |
| 562 Terminate(); | 564 Terminate(); |
| 563 } | 565 } |
| 564 return res; | 566 return res; |
| 565 } | 567 } |
| 566 | 568 |
| 567 bool WebRtcVoiceEngine::InitInternal() { | 569 bool WebRtcVoiceEngine::InitInternal() { |
| 568 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 570 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| 569 // Temporarily turn logging level up for the Init call | 571 // Temporarily turn logging level up for the Init call. |
| 570 webrtc::Trace::set_level_filter(kElevatedTraceFilter); | 572 webrtc::Trace::set_level_filter(kElevatedTraceFilter); |
| 571 LOG(LS_INFO) << webrtc::VoiceEngine::GetVersionString(); | 573 LOG(LS_INFO) << webrtc::VoiceEngine::GetVersionString(); |
| 572 if (voe_wrapper_->base()->Init(adm_) == -1) { | 574 if (voe_wrapper_->base()->Init(adm_) == -1) { |
| 573 LOG_RTCERR0_EX(Init, voe_wrapper_->error()); | 575 LOG_RTCERR0_EX(Init, voe_wrapper_->error()); |
| 574 return false; | 576 return false; |
| 575 } | 577 } |
| 576 webrtc::Trace::set_level_filter(kDefaultTraceFilter); | 578 webrtc::Trace::set_level_filter(kDefaultTraceFilter); |
| 577 | 579 |
| 578 // Save the default AGC configuration settings. This must happen before | 580 // Save the default AGC configuration settings. This must happen before |
| 579 // calling ApplyOptions or the default will be overwritten. | 581 // calling ApplyOptions or the default will be overwritten. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 596 options.adjust_agc_delta = rtc::Optional<int>(0); | 598 options.adjust_agc_delta = rtc::Optional<int>(0); |
| 597 options.experimental_agc = rtc::Optional<bool>(false); | 599 options.experimental_agc = rtc::Optional<bool>(false); |
| 598 options.extended_filter_aec = rtc::Optional<bool>(false); | 600 options.extended_filter_aec = rtc::Optional<bool>(false); |
| 599 options.delay_agnostic_aec = rtc::Optional<bool>(false); | 601 options.delay_agnostic_aec = rtc::Optional<bool>(false); |
| 600 options.experimental_ns = rtc::Optional<bool>(false); | 602 options.experimental_ns = rtc::Optional<bool>(false); |
| 601 if (!ApplyOptions(options)) { | 603 if (!ApplyOptions(options)) { |
| 602 return false; | 604 return false; |
| 603 } | 605 } |
| 604 } | 606 } |
| 605 | 607 |
| 606 // Print our codec list again for the call diagnostic log | 608 // Print our codec list again for the call diagnostic log. |
| 607 LOG(LS_INFO) << "WebRtc VoiceEngine codecs:"; | 609 LOG(LS_INFO) << "WebRtc VoiceEngine codecs:"; |
| 608 for (const AudioCodec& codec : codecs_) { | 610 for (const AudioCodec& codec : codecs_) { |
| 609 LOG(LS_INFO) << ToString(codec); | 611 LOG(LS_INFO) << ToString(codec); |
| 610 } | 612 } |
| 611 | 613 |
| 612 SetDefaultDevices(); | 614 SetDefaultDevices(); |
| 613 | 615 |
| 614 initialized_ = true; | 616 initialized_ = true; |
| 615 return true; | 617 return true; |
| 616 } | 618 } |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 996 rtc::LoggingSeverity sev = rtc::LS_VERBOSE; | 998 rtc::LoggingSeverity sev = rtc::LS_VERBOSE; |
| 997 if (level == webrtc::kTraceError || level == webrtc::kTraceCritical) | 999 if (level == webrtc::kTraceError || level == webrtc::kTraceCritical) |
| 998 sev = rtc::LS_ERROR; | 1000 sev = rtc::LS_ERROR; |
| 999 else if (level == webrtc::kTraceWarning) | 1001 else if (level == webrtc::kTraceWarning) |
| 1000 sev = rtc::LS_WARNING; | 1002 sev = rtc::LS_WARNING; |
| 1001 else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo) | 1003 else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo) |
| 1002 sev = rtc::LS_INFO; | 1004 sev = rtc::LS_INFO; |
| 1003 else if (level == webrtc::kTraceTerseInfo) | 1005 else if (level == webrtc::kTraceTerseInfo) |
| 1004 sev = rtc::LS_INFO; | 1006 sev = rtc::LS_INFO; |
| 1005 | 1007 |
| 1006 // Skip past boilerplate prefix text | 1008 // Skip past boilerplate prefix text. |
| 1007 if (length < 72) { | 1009 if (length < 72) { |
| 1008 std::string msg(trace, length); | 1010 std::string msg(trace, length); |
| 1009 LOG(LS_ERROR) << "Malformed webrtc log message: "; | 1011 LOG(LS_ERROR) << "Malformed webrtc log message: "; |
| 1010 LOG_V(sev) << msg; | 1012 LOG_V(sev) << msg; |
| 1011 } else { | 1013 } else { |
| 1012 std::string msg(trace + 71, length - 72); | 1014 std::string msg(trace + 71, length - 72); |
| 1013 LOG_V(sev) << "webrtc: " << msg; | 1015 LOG_V(sev) << "webrtc: " << msg; |
| 1014 } | 1016 } |
| 1015 } | 1017 } |
| 1016 | 1018 |
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1482 } | 1484 } |
| 1483 | 1485 |
| 1484 if (playout_) { | 1486 if (playout_) { |
| 1485 // Receive codecs can not be changed while playing. So we temporarily | 1487 // Receive codecs can not be changed while playing. So we temporarily |
| 1486 // pause playout. | 1488 // pause playout. |
| 1487 PausePlayout(); | 1489 PausePlayout(); |
| 1488 } | 1490 } |
| 1489 | 1491 |
| 1490 bool result = true; | 1492 bool result = true; |
| 1491 for (const AudioCodec& codec : new_codecs) { | 1493 for (const AudioCodec& codec : new_codecs) { |
| 1492 webrtc::CodecInst voe_codec; | 1494 webrtc::CodecInst voe_codec = {0}; |
| 1493 if (WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { | 1495 if (WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { |
| 1494 LOG(LS_INFO) << ToString(codec); | 1496 LOG(LS_INFO) << ToString(codec); |
| 1495 voe_codec.pltype = codec.id; | 1497 voe_codec.pltype = codec.id; |
| 1496 for (const auto& ch : recv_streams_) { | 1498 for (const auto& ch : recv_streams_) { |
| 1497 if (engine()->voe()->codec()->SetRecPayloadType( | 1499 if (engine()->voe()->codec()->SetRecPayloadType( |
| 1498 ch.second->channel(), voe_codec) == -1) { | 1500 ch.second->channel(), voe_codec) == -1) { |
| 1499 LOG_RTCERR2(SetRecPayloadType, ch.second->channel(), | 1501 LOG_RTCERR2(SetRecPayloadType, ch.second->channel(), |
| 1500 ToString(voe_codec)); | 1502 ToString(voe_codec)); |
| 1501 result = false; | 1503 result = false; |
| 1502 } | 1504 } |
| 1503 } | 1505 } |
| 1504 } else { | 1506 } else { |
| 1505 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); | 1507 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); |
| 1506 result = false; | 1508 result = false; |
| 1507 break; | 1509 break; |
| 1508 } | 1510 } |
| 1509 } | 1511 } |
| 1510 if (result) { | 1512 if (result) { |
| 1511 recv_codecs_ = codecs; | 1513 recv_codecs_ = codecs; |
| 1512 } | 1514 } |
| 1513 | 1515 |
| 1514 if (desired_playout_ && !playout_) { | 1516 if (desired_playout_ && !playout_) { |
| 1515 ResumePlayout(); | 1517 ResumePlayout(); |
| 1516 } | 1518 } |
| 1517 return result; | 1519 return result; |
| 1518 } | 1520 } |
| 1519 | 1521 |
| 1522 // Utility function called from SetSendParameters() to extract current send |
| 1523 // codec settings from the given list of codecs (originally from SDP). Both send |
| 1524 // and receive streams may be reconfigured based on the new settings. |
| 1520 bool WebRtcVoiceMediaChannel::SetSendCodecs( | 1525 bool WebRtcVoiceMediaChannel::SetSendCodecs( |
| 1521 int channel, const std::vector<AudioCodec>& codecs) { | 1526 const std::vector<AudioCodec>& codecs) { |
| 1527 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| 1528 // TODO(solenberg): Validate input - that payload types don't overlap, are |
| 1529 // within range, filter out codecs we don't support, |
| 1530 // redundant codecs etc. |
| 1531 |
| 1532 // Find the DTMF telephone event "codec" payload type. |
| 1533 dtmf_payload_type_ = rtc::Optional<int>(); |
| 1534 for (const AudioCodec& codec : codecs) { |
| 1535 if (IsCodec(codec, kDtmfCodecName)) { |
| 1536 dtmf_payload_type_ = rtc::Optional<int>(codec.id); |
| 1537 break; |
| 1538 } |
| 1539 } |
| 1540 |
| 1541 // Scan through the list to figure out the codec to use for sending, along |
| 1542 // with the proper configuration for VAD, CNG, RED, NACK and Opus-specific |
| 1543 // parameters. |
| 1544 { |
| 1545 SendCodecSpec send_codec_spec; |
| 1546 send_codec_spec.nack_enabled = send_codec_spec_.nack_enabled; |
| 1547 |
| 1548 // Find send codec (the first non-telephone-event/CN codec). |
| 1549 const AudioCodec* codec = WebRtcVoiceCodecs::GetPreferredCodec( |
| 1550 codecs, &send_codec_spec.codec_inst, &send_codec_spec.red_payload_type); |
| 1551 if (!codec) { |
| 1552 LOG(LS_WARNING) << "Received empty list of codecs."; |
| 1553 return false; |
| 1554 } |
| 1555 |
| 1556 send_codec_spec.transport_cc_enabled = HasTransportCc(*codec); |
| 1557 |
| 1558 // This condition is apparently here because Opus does not support RED and |
| 1559 // FEC simultaneously. However, DTX and max playback rate shouldn't have |
| 1560 // such limitations. |
| 1561 // TODO(solenberg): Refactor this logic once we create AudioEncoders here. |
| 1562 if (send_codec_spec.red_payload_type == -1) { |
| 1563 send_codec_spec.nack_enabled = HasNack(*codec); |
| 1564 // For Opus as the send codec, we are to determine inband FEC, maximum |
| 1565 // playback rate, and opus internal dtx. |
| 1566 if (IsCodec(*codec, kOpusCodecName)) { |
| 1567 GetOpusConfig(*codec, &send_codec_spec.codec_inst, |
| 1568 &send_codec_spec.enable_codec_fec, |
| 1569 &send_codec_spec.opus_max_playback_rate, |
| 1570 &send_codec_spec.enable_opus_dtx); |
| 1571 } |
| 1572 |
| 1573 // Set packet size if the AudioCodec param kCodecParamPTime is set. |
| 1574 int ptime_ms = 0; |
| 1575 if (codec->GetParam(kCodecParamPTime, &ptime_ms)) { |
| 1576 if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize( |
| 1577 &send_codec_spec.codec_inst, ptime_ms)) { |
| 1578 LOG(LS_WARNING) << "Failed to set packet size for codec " |
| 1579 << send_codec_spec.codec_inst.plname; |
| 1580 return false; |
| 1581 } |
| 1582 } |
| 1583 } |
| 1584 |
| 1585 // Loop through the codecs list again to find the CN codec. |
| 1586 // TODO(solenberg): Break out into a separate function? |
| 1587 for (const AudioCodec& codec : codecs) { |
| 1588 // Ignore codecs we don't know about. The negotiation step should prevent |
| 1589 // this, but double-check to be sure. |
| 1590 webrtc::CodecInst voe_codec = {0}; |
| 1591 if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { |
| 1592 LOG(LS_WARNING) << "Unknown codec " << ToString(codec); |
| 1593 continue; |
| 1594 } |
| 1595 |
| 1596 if (IsCodec(codec, kCnCodecName)) { |
| 1597 // Turn voice activity detection/comfort noise on if supported. |
| 1598 // Set the wideband CN payload type appropriately. |
| 1599 // (narrowband always uses the static payload type 13). |
| 1600 int cng_plfreq = -1; |
| 1601 switch (codec.clockrate) { |
| 1602 case 8000: |
| 1603 case 16000: |
| 1604 case 32000: |
| 1605 cng_plfreq = codec.clockrate; |
| 1606 break; |
| 1607 default: |
| 1608 LOG(LS_WARNING) << "CN frequency " << codec.clockrate |
| 1609 << " not supported."; |
| 1610 continue; |
| 1611 } |
| 1612 send_codec_spec.cng_payload_type = codec.id; |
| 1613 send_codec_spec.cng_plfreq = cng_plfreq; |
| 1614 break; |
| 1615 } |
| 1616 } |
| 1617 |
| 1618 // Latch in the new state. |
| 1619 send_codec_spec_ = std::move(send_codec_spec); |
| 1620 } |
| 1621 |
| 1622 // Cache the codecs in order to configure the channel created later. |
| 1623 for (const auto& ch : send_streams_) { |
| 1624 if (!SetSendCodecs(ch.second->channel())) { |
| 1625 return false; |
| 1626 } |
| 1627 } |
| 1628 |
| 1629 // Set nack status on receive channels. |
| 1630 if (!send_streams_.empty()) { |
| 1631 for (const auto& kv : recv_streams_) { |
| 1632 SetNack(kv.second->channel(), send_codec_spec_.nack_enabled); |
| 1633 } |
| 1634 } |
| 1635 |
| 1636 // Check if the transport cc feedback has changed on the preferred send codec, |
| 1637 // and in that case reconfigure all receive streams. |
| 1638 if (recv_transport_cc_enabled_ != send_codec_spec_.transport_cc_enabled) { |
| 1639 LOG(LS_INFO) << "Recreate all the receive streams because the send " |
| 1640 "codec has changed."; |
| 1641 recv_transport_cc_enabled_ = send_codec_spec_.transport_cc_enabled; |
| 1642 for (auto& kv : recv_streams_) { |
| 1643 kv.second->RecreateAudioReceiveStream(recv_transport_cc_enabled_); |
| 1644 } |
| 1645 } |
| 1646 |
| 1647 return true; |
| 1648 } |
| 1649 |
| 1650 // Apply current codec settings to a single voe::Channel used for sending. |
| 1651 bool WebRtcVoiceMediaChannel::SetSendCodecs(int channel) { |
| 1522 // Disable VAD, FEC, and RED unless we know the other side wants them. | 1652 // Disable VAD, FEC, and RED unless we know the other side wants them. |
| 1523 engine()->voe()->codec()->SetVADStatus(channel, false); | 1653 engine()->voe()->codec()->SetVADStatus(channel, false); |
| 1524 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); | 1654 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); |
| 1525 engine()->voe()->rtp()->SetREDStatus(channel, false); | 1655 engine()->voe()->rtp()->SetREDStatus(channel, false); |
| 1526 engine()->voe()->codec()->SetFECStatus(channel, false); | 1656 engine()->voe()->codec()->SetFECStatus(channel, false); |
| 1527 | 1657 |
| 1528 // Scan through the list to figure out the codec to use for sending, along | 1658 if (send_codec_spec_.red_payload_type != -1) { |
| 1529 // with the proper configuration for VAD. | 1659 // Enable redundant encoding of the specified codec. Treat any |
| 1530 webrtc::CodecInst send_codec; | 1660 // failure as a fatal internal error. |
| 1531 memset(&send_codec, 0, sizeof(send_codec)); | 1661 LOG(LS_INFO) << "Enabling RED on channel " << channel; |
| 1532 | 1662 if (engine()->voe()->rtp()->SetREDStatus(channel, true, |
| 1533 bool nack_enabled = nack_enabled_; | 1663 send_codec_spec_.red_payload_type) == -1) { |
| 1534 bool enable_codec_fec = false; | 1664 LOG_RTCERR3(SetREDStatus, channel, true, |
| 1535 bool enable_opus_dtx = false; | 1665 send_codec_spec_.red_payload_type); |
| 1536 int opus_max_playback_rate = 0; | 1666 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 } | 1667 } |
| 1571 } | 1668 } |
| 1572 | 1669 |
| 1573 if (nack_enabled_ != nack_enabled) { | 1670 SetNack(channel, send_codec_spec_.nack_enabled); |
| 1574 SetNack(channel, nack_enabled); | 1671 |
| 1575 nack_enabled_ = nack_enabled; | 1672 // Set the codec immediately, since SetVADStatus() depends on whether |
| 1576 } | 1673 // the current codec is mono or stereo. |
| 1577 if (!codec) { | 1674 if (!SetSendCodec(channel, send_codec_spec_.codec_inst)) { |
| 1578 LOG(LS_WARNING) << "Received empty list of codecs."; | |
| 1579 return false; | 1675 return false; |
| 1580 } | 1676 } |
| 1581 | 1677 |
| 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. | 1678 // FEC should be enabled after SetSendCodec. |
| 1588 if (enable_codec_fec) { | 1679 if (send_codec_spec_.enable_codec_fec) { |
| 1589 LOG(LS_INFO) << "Attempt to enable codec internal FEC on channel " | 1680 LOG(LS_INFO) << "Attempt to enable codec internal FEC on channel " |
| 1590 << channel; | 1681 << channel; |
| 1591 if (engine()->voe()->codec()->SetFECStatus(channel, true) == -1) { | 1682 if (engine()->voe()->codec()->SetFECStatus(channel, true) == -1) { |
| 1592 // Enable codec internal FEC. Treat any failure as fatal internal error. | 1683 // Enable codec internal FEC. Treat any failure as fatal internal error. |
| 1593 LOG_RTCERR2(SetFECStatus, channel, true); | 1684 LOG_RTCERR2(SetFECStatus, channel, true); |
| 1594 return false; | 1685 return false; |
| 1595 } | 1686 } |
| 1596 } | 1687 } |
| 1597 | 1688 |
| 1598 if (IsCodec(send_codec, kOpusCodecName)) { | 1689 if (IsCodec(send_codec_spec_.codec_inst, kOpusCodecName)) { |
| 1599 // DTX and maxplaybackrate should be set after SetSendCodec. Because current | 1690 // DTX and maxplaybackrate should be set after SetSendCodec. Because current |
| 1600 // send codec has to be Opus. | 1691 // send codec has to be Opus. |
| 1601 | 1692 |
| 1602 // Set Opus internal DTX. | 1693 // Set Opus internal DTX. |
| 1603 LOG(LS_INFO) << "Attempt to " | 1694 LOG(LS_INFO) << "Attempt to " |
| 1604 << (enable_opus_dtx ? "enable" : "disable") | 1695 << (send_codec_spec_.enable_opus_dtx ? "enable" : "disable") |
| 1605 << " Opus DTX on channel " | 1696 << " Opus DTX on channel " |
| 1606 << channel; | 1697 << channel; |
| 1607 if (engine()->voe()->codec()->SetOpusDtx(channel, enable_opus_dtx)) { | 1698 if (engine()->voe()->codec()->SetOpusDtx(channel, |
| 1608 LOG_RTCERR2(SetOpusDtx, channel, enable_opus_dtx); | 1699 send_codec_spec_.enable_opus_dtx)) { |
| 1700 LOG_RTCERR2(SetOpusDtx, channel, send_codec_spec_.enable_opus_dtx); |
| 1609 return false; | 1701 return false; |
| 1610 } | 1702 } |
| 1611 | 1703 |
| 1612 // If opus_max_playback_rate <= 0, the default maximum playback rate | 1704 // If opus_max_playback_rate <= 0, the default maximum playback rate |
| 1613 // (48 kHz) will be used. | 1705 // (48 kHz) will be used. |
| 1614 if (opus_max_playback_rate > 0) { | 1706 if (send_codec_spec_.opus_max_playback_rate > 0) { |
| 1615 LOG(LS_INFO) << "Attempt to set maximum playback rate to " | 1707 LOG(LS_INFO) << "Attempt to set maximum playback rate to " |
| 1616 << opus_max_playback_rate | 1708 << send_codec_spec_.opus_max_playback_rate |
| 1617 << " Hz on channel " | 1709 << " Hz on channel " |
| 1618 << channel; | 1710 << channel; |
| 1619 if (engine()->voe()->codec()->SetOpusMaxPlaybackRate( | 1711 if (engine()->voe()->codec()->SetOpusMaxPlaybackRate( |
| 1620 channel, opus_max_playback_rate) == -1) { | 1712 channel, send_codec_spec_.opus_max_playback_rate) == -1) { |
| 1621 LOG_RTCERR2(SetOpusMaxPlaybackRate, channel, opus_max_playback_rate); | 1713 LOG_RTCERR2(SetOpusMaxPlaybackRate, channel, |
| 1714 send_codec_spec_.opus_max_playback_rate); |
| 1622 return false; | 1715 return false; |
| 1623 } | 1716 } |
| 1624 } | 1717 } |
| 1625 } | 1718 } |
| 1626 | 1719 |
| 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_) { | 1720 if (send_bitrate_setting_) { |
| 1631 SetSendBitrateInternal(send_bitrate_bps_); | 1721 SetSendBitrateInternal(send_bitrate_bps_); |
| 1632 } | 1722 } |
| 1633 | 1723 |
| 1634 // Loop through the codecs list again to config the CN codec. | 1724 // Set the CN payloadtype and the VAD status. |
| 1635 for (const AudioCodec& codec : codecs) { | 1725 if (send_codec_spec_.cng_payload_type != -1) { |
| 1636 // Ignore codecs we don't know about. The negotiation step should prevent | 1726 // The CN payload type for 8000 Hz clockrate is fixed at 13. |
| 1637 // this, but double-check to be sure. | 1727 if (send_codec_spec_.cng_plfreq != 8000) { |
| 1638 webrtc::CodecInst voe_codec; | |
| 1639 if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { | |
| 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; | 1728 webrtc::PayloadFrequencies cn_freq; |
| 1649 switch (codec.clockrate) { | 1729 switch (send_codec_spec_.cng_plfreq) { |
| 1650 case 8000: | |
| 1651 cn_freq = webrtc::kFreq8000Hz; | |
| 1652 break; | |
| 1653 case 16000: | 1730 case 16000: |
| 1654 cn_freq = webrtc::kFreq16000Hz; | 1731 cn_freq = webrtc::kFreq16000Hz; |
| 1655 break; | 1732 break; |
| 1656 case 32000: | 1733 case 32000: |
| 1657 cn_freq = webrtc::kFreq32000Hz; | 1734 cn_freq = webrtc::kFreq32000Hz; |
| 1658 break; | 1735 break; |
| 1659 default: | 1736 default: |
| 1660 LOG(LS_WARNING) << "CN frequency " << codec.clockrate | 1737 RTC_NOTREACHED(); |
| 1661 << " not supported."; | 1738 return false; |
| 1662 continue; | |
| 1663 } | 1739 } |
| 1664 // Set the CN payloadtype and the VAD status. | 1740 if (engine()->voe()->codec()->SetSendCNPayloadType( |
| 1665 // The CN payload type for 8000 Hz clockrate is fixed at 13. | 1741 channel, send_codec_spec_.cng_payload_type, cn_freq) == -1) { |
| 1666 if (cn_freq != webrtc::kFreq8000Hz) { | 1742 LOG_RTCERR3(SetSendCNPayloadType, channel, |
| 1667 if (engine()->voe()->codec()->SetSendCNPayloadType( | 1743 send_codec_spec_.cng_payload_type, cn_freq); |
| 1668 channel, codec.id, cn_freq) == -1) { | 1744 // TODO(ajm): This failure condition will be removed from VoE. |
| 1669 LOG_RTCERR3(SetSendCNPayloadType, channel, codec.id, cn_freq); | 1745 // Restore the return here when we update to a new enough webrtc. |
| 1670 // TODO(ajm): This failure condition will be removed from VoE. | 1746 // |
| 1671 // Restore the return here when we update to a new enough webrtc. | 1747 // Not returning false because the SetSendCNPayloadType will fail if |
| 1672 // | 1748 // the channel is already sending. |
| 1673 // Not returning false because the SetSendCNPayloadType will fail if | 1749 // This can happen if the remote description is applied twice, for |
| 1674 // the channel is already sending. | 1750 // 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 | 1751 // send the offer. |
| 1676 // example in the case of ROAP on top of JSEP, where both side will | |
| 1677 // send the offer. | |
| 1678 } | |
| 1679 } | 1752 } |
| 1680 // Only turn on VAD if we have a CN payload type that matches the | 1753 } |
| 1681 // clockrate for the codec we are going to use. | 1754 |
| 1682 if (codec.clockrate == send_codec.plfreq && send_codec.channels != 2) { | 1755 // 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 | 1756 // clockrate for the codec we are going to use. |
| 1684 // interaction between VAD and Opus FEC. | 1757 if (send_codec_spec_.cng_plfreq == send_codec_spec_.codec_inst.plfreq && |
| 1685 LOG(LS_INFO) << "Enabling VAD"; | 1758 send_codec_spec_.codec_inst.channels == 1) { |
| 1686 if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) { | 1759 // TODO(minyue): If CN frequency == 48000 Hz is allowed, consider the |
| 1687 LOG_RTCERR2(SetVADStatus, channel, true); | 1760 // interaction between VAD and Opus FEC. |
| 1688 return false; | 1761 LOG(LS_INFO) << "Enabling VAD"; |
| 1689 } | 1762 if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) { |
| 1763 LOG_RTCERR2(SetVADStatus, channel, true); |
| 1764 return false; |
| 1690 } | 1765 } |
| 1691 } | 1766 } |
| 1692 } | 1767 } |
| 1693 return true; | 1768 return true; |
| 1694 } | 1769 } |
| 1695 | 1770 |
| 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) { | 1771 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) { |
| 1748 if (nack_enabled) { | 1772 if (nack_enabled) { |
| 1749 LOG(LS_INFO) << "Enabling NACK for channel " << channel; | 1773 LOG(LS_INFO) << "Enabling NACK for channel " << channel; |
| 1750 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets); | 1774 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets); |
| 1751 } else { | 1775 } else { |
| 1752 LOG(LS_INFO) << "Disabling NACK for channel " << channel; | 1776 LOG(LS_INFO) << "Disabling NACK for channel " << channel; |
| 1753 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); | 1777 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); |
| 1754 } | 1778 } |
| 1755 } | 1779 } |
| 1756 | 1780 |
| 1757 bool WebRtcVoiceMediaChannel::SetSendCodec( | 1781 bool WebRtcVoiceMediaChannel::SetSendCodec( |
| 1758 int channel, const webrtc::CodecInst& send_codec) { | 1782 int channel, const webrtc::CodecInst& send_codec) { |
| 1759 LOG(LS_INFO) << "Send channel " << channel << " selected voice codec " | 1783 LOG(LS_INFO) << "Send channel " << channel << " selected voice codec " |
| 1760 << ToString(send_codec) << ", bitrate=" << send_codec.rate; | 1784 << ToString(send_codec) << ", bitrate=" << send_codec.rate; |
| 1761 | 1785 |
| 1762 webrtc::CodecInst current_codec; | 1786 webrtc::CodecInst current_codec = {0}; |
| 1763 if (engine()->voe()->codec()->GetSendCodec(channel, current_codec) == 0 && | 1787 if (engine()->voe()->codec()->GetSendCodec(channel, current_codec) == 0 && |
| 1764 (send_codec == current_codec)) { | 1788 (send_codec == current_codec)) { |
| 1765 // Codec is already configured, we can return without setting it again. | 1789 // Codec is already configured, we can return without setting it again. |
| 1766 return true; | 1790 return true; |
| 1767 } | 1791 } |
| 1768 | 1792 |
| 1769 if (engine()->voe()->codec()->SetSendCodec(channel, send_codec) == -1) { | 1793 if (engine()->voe()->codec()->SetSendCodec(channel, send_codec) == -1) { |
| 1770 LOG_RTCERR2(SetSendCodec, channel, ToString(send_codec)); | 1794 LOG_RTCERR2(SetSendCodec, channel, ToString(send_codec)); |
| 1771 return false; | 1795 return false; |
| 1772 } | 1796 } |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1922 // Save the channel to send_streams_, so that RemoveSendStream() can still | 1946 // Save the channel to send_streams_, so that RemoveSendStream() can still |
| 1923 // delete the channel in case failure happens below. | 1947 // delete the channel in case failure happens below. |
| 1924 webrtc::AudioTransport* audio_transport = | 1948 webrtc::AudioTransport* audio_transport = |
| 1925 engine()->voe()->base()->audio_transport(); | 1949 engine()->voe()->base()->audio_transport(); |
| 1926 send_streams_.insert(std::make_pair(ssrc, new WebRtcAudioSendStream( | 1950 send_streams_.insert(std::make_pair(ssrc, new WebRtcAudioSendStream( |
| 1927 channel, audio_transport, ssrc, sp.cname, send_rtp_extensions_, call_))); | 1951 channel, audio_transport, ssrc, sp.cname, send_rtp_extensions_, call_))); |
| 1928 | 1952 |
| 1929 // Set the current codecs to be used for the new channel. We need to do this | 1953 // 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 | 1954 // after adding the channel to send_channels_, because of how max bitrate is |
| 1931 // currently being configured by SetSendCodec(). | 1955 // currently being configured by SetSendCodec(). |
| 1932 if (!send_codecs_.empty() && !SetSendCodecs(channel, send_codecs_)) { | 1956 if (HasSendCodec() && !SetSendCodecs(channel)) { |
| 1933 RemoveSendStream(ssrc); | 1957 RemoveSendStream(ssrc); |
| 1934 return false; | 1958 return false; |
| 1935 } | 1959 } |
| 1936 | 1960 |
| 1937 // At this point the channel's local SSRC has been updated. If the channel is | 1961 // 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 | 1962 // the first send channel make sure that all the receive channels are updated |
| 1939 // with the same SSRC in order to send receiver reports. | 1963 // with the same SSRC in order to send receiver reports. |
| 1940 if (send_streams_.size() == 1) { | 1964 if (send_streams_.size() == 1) { |
| 1941 receiver_reports_ssrc_ = ssrc; | 1965 receiver_reports_ssrc_ = ssrc; |
| 1942 for (const auto& stream : recv_streams_) { | 1966 for (const auto& stream : recv_streams_) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2019 voe_codec.pltype = -1; | 2043 voe_codec.pltype = -1; |
| 2020 if (engine()->voe()->codec()->SetRecPayloadType(channel, voe_codec) == -1) { | 2044 if (engine()->voe()->codec()->SetRecPayloadType(channel, voe_codec) == -1) { |
| 2021 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); | 2045 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); |
| 2022 DeleteVoEChannel(channel); | 2046 DeleteVoEChannel(channel); |
| 2023 return false; | 2047 return false; |
| 2024 } | 2048 } |
| 2025 } | 2049 } |
| 2026 | 2050 |
| 2027 // Only enable those configured for this channel. | 2051 // Only enable those configured for this channel. |
| 2028 for (const auto& codec : recv_codecs_) { | 2052 for (const auto& codec : recv_codecs_) { |
| 2029 webrtc::CodecInst voe_codec; | 2053 webrtc::CodecInst voe_codec = {0}; |
| 2030 if (WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { | 2054 if (WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { |
| 2031 voe_codec.pltype = codec.id; | 2055 voe_codec.pltype = codec.id; |
| 2032 if (engine()->voe()->codec()->SetRecPayloadType( | 2056 if (engine()->voe()->codec()->SetRecPayloadType( |
| 2033 channel, voe_codec) == -1) { | 2057 channel, voe_codec) == -1) { |
| 2034 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); | 2058 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); |
| 2035 DeleteVoEChannel(channel); | 2059 DeleteVoEChannel(channel); |
| 2036 return false; | 2060 return false; |
| 2037 } | 2061 } |
| 2038 } | 2062 } |
| 2039 } | 2063 } |
| 2040 | 2064 |
| 2041 const int send_channel = GetSendChannelId(receiver_reports_ssrc_); | 2065 const int send_channel = GetSendChannelId(receiver_reports_ssrc_); |
| 2042 if (send_channel != -1) { | 2066 if (send_channel != -1) { |
| 2043 // Associate receive channel with first send channel (so the receive channel | 2067 // Associate receive channel with first send channel (so the receive channel |
| 2044 // can obtain RTT from the send channel) | 2068 // can obtain RTT from the send channel) |
| 2045 engine()->voe()->base()->AssociateSendChannel(channel, send_channel); | 2069 engine()->voe()->base()->AssociateSendChannel(channel, send_channel); |
| 2046 LOG(LS_INFO) << "VoiceEngine channel #" << channel | 2070 LOG(LS_INFO) << "VoiceEngine channel #" << channel |
| 2047 << " is associated with channel #" << send_channel << "."; | 2071 << " is associated with channel #" << send_channel << "."; |
| 2048 } | 2072 } |
| 2049 | 2073 |
| 2050 transport_cc_enabled_ = | |
| 2051 !send_codecs_.empty() ? HasTransportCc(send_codecs_[0]) : false; | |
| 2052 | |
| 2053 recv_streams_.insert(std::make_pair( | 2074 recv_streams_.insert(std::make_pair( |
| 2054 ssrc, new WebRtcAudioReceiveStream(channel, ssrc, receiver_reports_ssrc_, | 2075 ssrc, new WebRtcAudioReceiveStream(channel, ssrc, receiver_reports_ssrc_, |
| 2055 transport_cc_enabled_, sp.sync_label, | 2076 recv_transport_cc_enabled_, |
| 2056 recv_rtp_extensions_, call_))); | 2077 sp.sync_label, recv_rtp_extensions_, |
| 2078 call_))); |
| 2057 | 2079 |
| 2058 SetNack(channel, nack_enabled_); | 2080 SetNack(channel, send_codec_spec_.nack_enabled); |
| 2059 SetPlayout(channel, playout_); | 2081 SetPlayout(channel, playout_); |
| 2060 | 2082 |
| 2061 return true; | 2083 return true; |
| 2062 } | 2084 } |
| 2063 | 2085 |
| 2064 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { | 2086 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { |
| 2065 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 2087 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
| 2066 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; | 2088 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; |
| 2067 | 2089 |
| 2068 const auto it = recv_streams_.find(ssrc); | 2090 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."; | 2374 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBandwidth."; |
| 2353 return SetSendBitrateInternal(bps); | 2375 return SetSendBitrateInternal(bps); |
| 2354 } | 2376 } |
| 2355 | 2377 |
| 2356 bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) { | 2378 bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) { |
| 2357 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendBitrateInternal."; | 2379 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendBitrateInternal."; |
| 2358 | 2380 |
| 2359 send_bitrate_setting_ = true; | 2381 send_bitrate_setting_ = true; |
| 2360 send_bitrate_bps_ = bps; | 2382 send_bitrate_bps_ = bps; |
| 2361 | 2383 |
| 2362 if (!send_codec_) { | 2384 if (!HasSendCodec()) { |
| 2363 LOG(LS_INFO) << "The send codec has not been set up yet. " | 2385 LOG(LS_INFO) << "The send codec has not been set up yet. " |
| 2364 << "The send bitrate setting will be applied later."; | 2386 << "The send bitrate setting will be applied later."; |
| 2365 return true; | 2387 return true; |
| 2366 } | 2388 } |
| 2367 | 2389 |
| 2368 // Bitrate is auto by default. | 2390 // Bitrate is auto by default. |
| 2369 // TODO(bemasc): Fix this so that if SetMaxSendBandwidth(50) is followed by | 2391 // TODO(bemasc): Fix this so that if SetMaxSendBandwidth(50) is followed by |
| 2370 // SetMaxSendBandwith(0), the second call removes the previous limit. | 2392 // SetMaxSendBandwith(0), the second call removes the previous limit. |
| 2371 if (bps <= 0) | 2393 if (bps <= 0) |
| 2372 return true; | 2394 return true; |
| 2373 | 2395 |
| 2374 webrtc::CodecInst codec = *send_codec_; | 2396 webrtc::CodecInst codec = send_codec_spec_.codec_inst; |
| 2375 bool is_multi_rate = WebRtcVoiceCodecs::IsCodecMultiRate(codec); | 2397 bool is_multi_rate = WebRtcVoiceCodecs::IsCodecMultiRate(codec); |
| 2376 | 2398 |
| 2377 if (is_multi_rate) { | 2399 if (is_multi_rate) { |
| 2378 // If codec is multi-rate then just set the bitrate. | 2400 // If codec is multi-rate then just set the bitrate. |
| 2379 codec.rate = bps; | 2401 codec.rate = bps; |
| 2380 for (const auto& ch : send_streams_) { | 2402 for (const auto& ch : send_streams_) { |
| 2381 if (!SetSendCodec(ch.second->channel(), codec)) { | 2403 if (!SetSendCodec(ch.second->channel(), codec)) { |
| 2382 LOG(LS_INFO) << "Failed to set codec " << codec.plname | 2404 LOG(LS_INFO) << "Failed to set codec " << codec.plname |
| 2383 << " to bitrate " << bps << " bps."; | 2405 << " to bitrate " << bps << " bps."; |
| 2384 return false; | 2406 return false; |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2520 } | 2542 } |
| 2521 } else { | 2543 } else { |
| 2522 LOG(LS_INFO) << "Stopping playout for channel #" << channel; | 2544 LOG(LS_INFO) << "Stopping playout for channel #" << channel; |
| 2523 engine()->voe()->base()->StopPlayout(channel); | 2545 engine()->voe()->base()->StopPlayout(channel); |
| 2524 } | 2546 } |
| 2525 return true; | 2547 return true; |
| 2526 } | 2548 } |
| 2527 } // namespace cricket | 2549 } // namespace cricket |
| 2528 | 2550 |
| 2529 #endif // HAVE_WEBRTC_VOICE | 2551 #endif // HAVE_WEBRTC_VOICE |
| OLD | NEW |