Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: webrtc/media/engine/webrtcvoiceengine.cc

Issue 1765873002: On WVoMC::SetSendParameters(), figure out send codec settings ONCE, not for each send stream. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Added docs Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/media/engine/webrtcvoiceengine.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 // TODO(solenberg): This is a curious condition - kept for legacy reasons -
1559 // why would we only want to figure out these parameters
1560 // when RED is disabled?
1561 if (send_codec_spec.red_payload_type == -1) {
1562 send_codec_spec.nack_enabled = HasNack(*codec);
1563 // For Opus as the send codec, we are to determine inband FEC, maximum
1564 // playback rate, and opus internal dtx.
1565 if (IsCodec(*codec, kOpusCodecName)) {
1566 GetOpusConfig(*codec, &send_codec_spec.codec_inst,
1567 &send_codec_spec.enable_codec_fec,
1568 &send_codec_spec.opus_max_playback_rate,
1569 &send_codec_spec.enable_opus_dtx);
1570 }
1571
1572 // Set packet size if the AudioCodec param kCodecParamPTime is set.
1573 int ptime_ms = 0;
1574 if (codec->GetParam(kCodecParamPTime, &ptime_ms)) {
1575 if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(
1576 &send_codec_spec.codec_inst, ptime_ms)) {
1577 LOG(LS_WARNING) << "Failed to set packet size for codec "
1578 << send_codec_spec.codec_inst.plname;
1579 return false;
1580 }
1581 }
1582 }
1583
1584 // Loop through the codecs list again to find the CN codec.
stefan-webrtc 2016/03/07 09:27:50 It would be nice to break the code below out to a
the sun 2016/03/07 13:56:04 Yes. This code is due to go through a lot of chang
1585 for (const AudioCodec& codec : codecs) {
1586 // Ignore codecs we don't know about. The negotiation step should prevent
1587 // this, but double-check to be sure.
1588 webrtc::CodecInst voe_codec = {0};
1589 if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
1590 LOG(LS_WARNING) << "Unknown codec " << ToString(codec);
1591 continue;
1592 }
1593
1594 if (IsCodec(codec, kCnCodecName)) {
1595 // Turn voice activity detection/comfort noise on if supported.
1596 // Set the wideband CN payload type appropriately.
1597 // (narrowband always uses the static payload type 13).
1598 int cng_plfreq = -1;
1599 switch (codec.clockrate) {
1600 case 8000:
1601 case 16000:
1602 case 32000:
1603 cng_plfreq = codec.clockrate;
1604 break;
1605 default:
1606 LOG(LS_WARNING) << "CN frequency " << codec.clockrate
1607 << " not supported.";
1608 continue;
1609 }
1610 send_codec_spec.cng_payload_type = codec.id;
1611 send_codec_spec.cng_plfreq = cng_plfreq;
1612 break;
1613 }
1614 }
1615
1616 send_codec_spec_ = std::move(send_codec_spec);
1617 }
1618
1619 // Cache the codecs in order to configure the channel created later.
1620 for (const auto& ch : send_streams_) {
1621 if (!SetSendCodecs(ch.second->channel())) {
stefan-webrtc 2016/03/07 09:27:50 Should this method have a different name? It doesn
the sun 2016/03/07 13:56:04 Well, it is the name that has been used so far and
1622 return false;
1623 }
1624 }
1625
1626 // Set nack status on receive channels and update |nack_enabled_|.
1627 if (!send_streams_.empty()) {
1628 for (const auto& kv : recv_streams_) {
1629 SetNack(kv.second->channel(), send_codec_spec_.nack_enabled);
1630 }
1631 }
1632
1633 // Check if the transport cc feedback has changed on the preferred send codec,
1634 // and in that case reconfigure all receive streams.
1635 if (recv_transport_cc_enabled_ != send_codec_spec_.transport_cc_enabled) {
1636 LOG(LS_INFO) << "Recreate all the receive streams because the send "
1637 "codec has changed.";
1638 recv_transport_cc_enabled_ = send_codec_spec_.transport_cc_enabled;
1639 for (auto& kv : recv_streams_) {
1640 kv.second->RecreateAudioReceiveStream(recv_transport_cc_enabled_);
1641 }
1642 }
1643
1644 return true;
1645 }
1646
1647 // Apply current codec settings to a single voe::Channel used for sending.
1648 bool WebRtcVoiceMediaChannel::SetSendCodecs(int channel) {
1522 // Disable VAD, FEC, and RED unless we know the other side wants them. 1649 // Disable VAD, FEC, and RED unless we know the other side wants them.
1523 engine()->voe()->codec()->SetVADStatus(channel, false); 1650 engine()->voe()->codec()->SetVADStatus(channel, false);
1524 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); 1651 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
1525 engine()->voe()->rtp()->SetREDStatus(channel, false); 1652 engine()->voe()->rtp()->SetREDStatus(channel, false);
1526 engine()->voe()->codec()->SetFECStatus(channel, false); 1653 engine()->voe()->codec()->SetFECStatus(channel, false);
1527 1654
1528 // Scan through the list to figure out the codec to use for sending, along 1655 if (send_codec_spec_.red_payload_type != -1) {
1529 // with the proper configuration for VAD. 1656 // Enable redundant encoding of the specified codec. Treat any
1530 webrtc::CodecInst send_codec; 1657 // failure as a fatal internal error.
1531 memset(&send_codec, 0, sizeof(send_codec)); 1658 LOG(LS_INFO) << "Enabling RED on channel " << channel;
1532 1659 if (engine()->voe()->rtp()->SetREDStatus(channel, true,
1533 bool nack_enabled = nack_enabled_; 1660 send_codec_spec_.red_payload_type) == -1) {
1534 bool enable_codec_fec = false; 1661 LOG_RTCERR3(SetREDStatus, channel, true,
1535 bool enable_opus_dtx = false; 1662 send_codec_spec_.red_payload_type);
1536 int opus_max_playback_rate = 0; 1663 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 } 1664 }
1571 } 1665 }
1572 1666
1573 if (nack_enabled_ != nack_enabled) { 1667 SetNack(channel, send_codec_spec_.nack_enabled);
1574 SetNack(channel, nack_enabled); 1668
1575 nack_enabled_ = nack_enabled; 1669 // Set the codec immediately, since SetVADStatus() depends on whether
1576 } 1670 // the current codec is mono or stereo.
1577 if (!codec) { 1671 if (!SetSendCodec(channel, send_codec_spec_.codec_inst)) {
1578 LOG(LS_WARNING) << "Received empty list of codecs.";
1579 return false; 1672 return false;
1580 } 1673 }
1581 1674
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. 1675 // FEC should be enabled after SetSendCodec.
1588 if (enable_codec_fec) { 1676 if (send_codec_spec_.enable_codec_fec) {
1589 LOG(LS_INFO) << "Attempt to enable codec internal FEC on channel " 1677 LOG(LS_INFO) << "Attempt to enable codec internal FEC on channel "
1590 << channel; 1678 << channel;
1591 if (engine()->voe()->codec()->SetFECStatus(channel, true) == -1) { 1679 if (engine()->voe()->codec()->SetFECStatus(channel, true) == -1) {
1592 // Enable codec internal FEC. Treat any failure as fatal internal error. 1680 // Enable codec internal FEC. Treat any failure as fatal internal error.
1593 LOG_RTCERR2(SetFECStatus, channel, true); 1681 LOG_RTCERR2(SetFECStatus, channel, true);
1594 return false; 1682 return false;
1595 } 1683 }
1596 } 1684 }
1597 1685
1598 if (IsCodec(send_codec, kOpusCodecName)) { 1686 if (IsCodec(send_codec_spec_.codec_inst, kOpusCodecName)) {
1599 // DTX and maxplaybackrate should be set after SetSendCodec. Because current 1687 // DTX and maxplaybackrate should be set after SetSendCodec. Because current
1600 // send codec has to be Opus. 1688 // send codec has to be Opus.
1601 1689
1602 // Set Opus internal DTX. 1690 // Set Opus internal DTX.
1603 LOG(LS_INFO) << "Attempt to " 1691 LOG(LS_INFO) << "Attempt to "
1604 << (enable_opus_dtx ? "enable" : "disable") 1692 << (send_codec_spec_.enable_opus_dtx ? "enable" : "disable")
1605 << " Opus DTX on channel " 1693 << " Opus DTX on channel "
1606 << channel; 1694 << channel;
1607 if (engine()->voe()->codec()->SetOpusDtx(channel, enable_opus_dtx)) { 1695 if (engine()->voe()->codec()->SetOpusDtx(channel,
1608 LOG_RTCERR2(SetOpusDtx, channel, enable_opus_dtx); 1696 send_codec_spec_.enable_opus_dtx)) {
1697 LOG_RTCERR2(SetOpusDtx, channel, send_codec_spec_.enable_opus_dtx);
1609 return false; 1698 return false;
1610 } 1699 }
1611 1700
1612 // If opus_max_playback_rate <= 0, the default maximum playback rate 1701 // If opus_max_playback_rate <= 0, the default maximum playback rate
1613 // (48 kHz) will be used. 1702 // (48 kHz) will be used.
1614 if (opus_max_playback_rate > 0) { 1703 if (send_codec_spec_.opus_max_playback_rate > 0) {
1615 LOG(LS_INFO) << "Attempt to set maximum playback rate to " 1704 LOG(LS_INFO) << "Attempt to set maximum playback rate to "
1616 << opus_max_playback_rate 1705 << send_codec_spec_.opus_max_playback_rate
1617 << " Hz on channel " 1706 << " Hz on channel "
1618 << channel; 1707 << channel;
1619 if (engine()->voe()->codec()->SetOpusMaxPlaybackRate( 1708 if (engine()->voe()->codec()->SetOpusMaxPlaybackRate(
1620 channel, opus_max_playback_rate) == -1) { 1709 channel, send_codec_spec_.opus_max_playback_rate) == -1) {
1621 LOG_RTCERR2(SetOpusMaxPlaybackRate, channel, opus_max_playback_rate); 1710 LOG_RTCERR2(SetOpusMaxPlaybackRate, channel,
1711 send_codec_spec_.opus_max_playback_rate);
1622 return false; 1712 return false;
1623 } 1713 }
1624 } 1714 }
1625 } 1715 }
1626 1716
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_) { 1717 if (send_bitrate_setting_) {
1631 SetSendBitrateInternal(send_bitrate_bps_); 1718 SetSendBitrateInternal(send_bitrate_bps_);
1632 } 1719 }
1633 1720
1634 // Loop through the codecs list again to config the CN codec. 1721 // Set the CN payloadtype and the VAD status.
1635 for (const AudioCodec& codec : codecs) { 1722 if (send_codec_spec_.cng_payload_type != -1) {
1636 // Ignore codecs we don't know about. The negotiation step should prevent 1723 // The CN payload type for 8000 Hz clockrate is fixed at 13.
1637 // this, but double-check to be sure. 1724 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; 1725 webrtc::PayloadFrequencies cn_freq;
1649 switch (codec.clockrate) { 1726 switch (send_codec_spec_.cng_plfreq) {
1650 case 8000:
1651 cn_freq = webrtc::kFreq8000Hz;
stefan-webrtc 2016/03/07 09:27:50 Have we removed support for this?
the sun 2016/03/07 13:56:04 I hope not! It should just be the order of the con
1652 break;
1653 case 16000: 1727 case 16000:
1654 cn_freq = webrtc::kFreq16000Hz; 1728 cn_freq = webrtc::kFreq16000Hz;
1655 break; 1729 break;
1656 case 32000: 1730 case 32000:
1657 cn_freq = webrtc::kFreq32000Hz; 1731 cn_freq = webrtc::kFreq32000Hz;
1658 break; 1732 break;
1659 default: 1733 default:
1660 LOG(LS_WARNING) << "CN frequency " << codec.clockrate 1734 RTC_NOTREACHED();
1661 << " not supported."; 1735 return false;
1662 continue;
1663 } 1736 }
1664 // Set the CN payloadtype and the VAD status. 1737 if (engine()->voe()->codec()->SetSendCNPayloadType(
1665 // The CN payload type for 8000 Hz clockrate is fixed at 13. 1738 channel, send_codec_spec_.cng_payload_type, cn_freq) == -1) {
1666 if (cn_freq != webrtc::kFreq8000Hz) { 1739 LOG_RTCERR3(SetSendCNPayloadType, channel,
1667 if (engine()->voe()->codec()->SetSendCNPayloadType( 1740 send_codec_spec_.cng_payload_type, cn_freq);
1668 channel, codec.id, cn_freq) == -1) { 1741 // TODO(ajm): This failure condition will be removed from VoE.
1669 LOG_RTCERR3(SetSendCNPayloadType, channel, codec.id, cn_freq); 1742 // Restore the return here when we update to a new enough webrtc.
1670 // TODO(ajm): This failure condition will be removed from VoE. 1743 //
1671 // Restore the return here when we update to a new enough webrtc. 1744 // Not returning false because the SetSendCNPayloadType will fail if
1672 // 1745 // the channel is already sending.
1673 // Not returning false because the SetSendCNPayloadType will fail if 1746 // This can happen if the remote description is applied twice, for
1674 // the channel is already sending. 1747 // 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 1748 // send the offer.
1676 // example in the case of ROAP on top of JSEP, where both side will
1677 // send the offer.
1678 }
1679 } 1749 }
1680 // Only turn on VAD if we have a CN payload type that matches the 1750 }
1681 // clockrate for the codec we are going to use. 1751
1682 if (codec.clockrate == send_codec.plfreq && send_codec.channels != 2) { 1752 // 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 1753 // clockrate for the codec we are going to use.
1684 // interaction between VAD and Opus FEC. 1754 if (send_codec_spec_.cng_plfreq == send_codec_spec_.codec_inst.plfreq &&
1685 LOG(LS_INFO) << "Enabling VAD"; 1755 send_codec_spec_.codec_inst.channels == 1) {
1686 if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) { 1756 // TODO(minyue): If CN frequency == 48000 Hz is allowed, consider the
1687 LOG_RTCERR2(SetVADStatus, channel, true); 1757 // interaction between VAD and Opus FEC.
1688 return false; 1758 LOG(LS_INFO) << "Enabling VAD";
1689 } 1759 if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) {
1760 LOG_RTCERR2(SetVADStatus, channel, true);
1761 return false;
1690 } 1762 }
1691 } 1763 }
1692 } 1764 }
1693 return true; 1765 return true;
1694 } 1766 }
1695 1767
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) { 1768 void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) {
1748 if (nack_enabled) { 1769 if (nack_enabled) {
1749 LOG(LS_INFO) << "Enabling NACK for channel " << channel; 1770 LOG(LS_INFO) << "Enabling NACK for channel " << channel;
1750 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets); 1771 engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets);
1751 } else { 1772 } else {
1752 LOG(LS_INFO) << "Disabling NACK for channel " << channel; 1773 LOG(LS_INFO) << "Disabling NACK for channel " << channel;
1753 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0); 1774 engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
1754 } 1775 }
1755 } 1776 }
1756 1777
1757 bool WebRtcVoiceMediaChannel::SetSendCodec( 1778 bool WebRtcVoiceMediaChannel::SetSendCodec(
1758 int channel, const webrtc::CodecInst& send_codec) { 1779 int channel, const webrtc::CodecInst& send_codec) {
1759 LOG(LS_INFO) << "Send channel " << channel << " selected voice codec " 1780 LOG(LS_INFO) << "Send channel " << channel << " selected voice codec "
1760 << ToString(send_codec) << ", bitrate=" << send_codec.rate; 1781 << ToString(send_codec) << ", bitrate=" << send_codec.rate;
1761 1782
1762 webrtc::CodecInst current_codec; 1783 webrtc::CodecInst current_codec = {0};
1763 if (engine()->voe()->codec()->GetSendCodec(channel, current_codec) == 0 && 1784 if (engine()->voe()->codec()->GetSendCodec(channel, current_codec) == 0 &&
1764 (send_codec == current_codec)) { 1785 (send_codec == current_codec)) {
1765 // Codec is already configured, we can return without setting it again. 1786 // Codec is already configured, we can return without setting it again.
1766 return true; 1787 return true;
1767 } 1788 }
1768 1789
1769 if (engine()->voe()->codec()->SetSendCodec(channel, send_codec) == -1) { 1790 if (engine()->voe()->codec()->SetSendCodec(channel, send_codec) == -1) {
1770 LOG_RTCERR2(SetSendCodec, channel, ToString(send_codec)); 1791 LOG_RTCERR2(SetSendCodec, channel, ToString(send_codec));
1771 return false; 1792 return false;
1772 } 1793 }
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
1922 // Save the channel to send_streams_, so that RemoveSendStream() can still 1943 // Save the channel to send_streams_, so that RemoveSendStream() can still
1923 // delete the channel in case failure happens below. 1944 // delete the channel in case failure happens below.
1924 webrtc::AudioTransport* audio_transport = 1945 webrtc::AudioTransport* audio_transport =
1925 engine()->voe()->base()->audio_transport(); 1946 engine()->voe()->base()->audio_transport();
1926 send_streams_.insert(std::make_pair(ssrc, new WebRtcAudioSendStream( 1947 send_streams_.insert(std::make_pair(ssrc, new WebRtcAudioSendStream(
1927 channel, audio_transport, ssrc, sp.cname, send_rtp_extensions_, call_))); 1948 channel, audio_transport, ssrc, sp.cname, send_rtp_extensions_, call_)));
1928 1949
1929 // Set the current codecs to be used for the new channel. We need to do this 1950 // 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 1951 // after adding the channel to send_channels_, because of how max bitrate is
1931 // currently being configured by SetSendCodec(). 1952 // currently being configured by SetSendCodec().
1932 if (!send_codecs_.empty() && !SetSendCodecs(channel, send_codecs_)) { 1953 if (HasSendCodec() && !SetSendCodecs(channel)) {
1933 RemoveSendStream(ssrc); 1954 RemoveSendStream(ssrc);
1934 return false; 1955 return false;
1935 } 1956 }
1936 1957
1937 // At this point the channel's local SSRC has been updated. If the channel is 1958 // 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 1959 // the first send channel make sure that all the receive channels are updated
1939 // with the same SSRC in order to send receiver reports. 1960 // with the same SSRC in order to send receiver reports.
1940 if (send_streams_.size() == 1) { 1961 if (send_streams_.size() == 1) {
1941 receiver_reports_ssrc_ = ssrc; 1962 receiver_reports_ssrc_ = ssrc;
1942 for (const auto& stream : recv_streams_) { 1963 for (const auto& stream : recv_streams_) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2019 voe_codec.pltype = -1; 2040 voe_codec.pltype = -1;
2020 if (engine()->voe()->codec()->SetRecPayloadType(channel, voe_codec) == -1) { 2041 if (engine()->voe()->codec()->SetRecPayloadType(channel, voe_codec) == -1) {
2021 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); 2042 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec));
2022 DeleteVoEChannel(channel); 2043 DeleteVoEChannel(channel);
2023 return false; 2044 return false;
2024 } 2045 }
2025 } 2046 }
2026 2047
2027 // Only enable those configured for this channel. 2048 // Only enable those configured for this channel.
2028 for (const auto& codec : recv_codecs_) { 2049 for (const auto& codec : recv_codecs_) {
2029 webrtc::CodecInst voe_codec; 2050 webrtc::CodecInst voe_codec = {0};
2030 if (WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { 2051 if (WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
2031 voe_codec.pltype = codec.id; 2052 voe_codec.pltype = codec.id;
2032 if (engine()->voe()->codec()->SetRecPayloadType( 2053 if (engine()->voe()->codec()->SetRecPayloadType(
2033 channel, voe_codec) == -1) { 2054 channel, voe_codec) == -1) {
2034 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec)); 2055 LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec));
2035 DeleteVoEChannel(channel); 2056 DeleteVoEChannel(channel);
2036 return false; 2057 return false;
2037 } 2058 }
2038 } 2059 }
2039 } 2060 }
2040 2061
2041 const int send_channel = GetSendChannelId(receiver_reports_ssrc_); 2062 const int send_channel = GetSendChannelId(receiver_reports_ssrc_);
2042 if (send_channel != -1) { 2063 if (send_channel != -1) {
2043 // Associate receive channel with first send channel (so the receive channel 2064 // Associate receive channel with first send channel (so the receive channel
2044 // can obtain RTT from the send channel) 2065 // can obtain RTT from the send channel)
2045 engine()->voe()->base()->AssociateSendChannel(channel, send_channel); 2066 engine()->voe()->base()->AssociateSendChannel(channel, send_channel);
2046 LOG(LS_INFO) << "VoiceEngine channel #" << channel 2067 LOG(LS_INFO) << "VoiceEngine channel #" << channel
2047 << " is associated with channel #" << send_channel << "."; 2068 << " is associated with channel #" << send_channel << ".";
2048 } 2069 }
2049 2070
2050 transport_cc_enabled_ =
2051 !send_codecs_.empty() ? HasTransportCc(send_codecs_[0]) : false;
2052
2053 recv_streams_.insert(std::make_pair( 2071 recv_streams_.insert(std::make_pair(
2054 ssrc, new WebRtcAudioReceiveStream(channel, ssrc, receiver_reports_ssrc_, 2072 ssrc, new WebRtcAudioReceiveStream(channel, ssrc, receiver_reports_ssrc_,
2055 transport_cc_enabled_, sp.sync_label, 2073 recv_transport_cc_enabled_,
2056 recv_rtp_extensions_, call_))); 2074 sp.sync_label, recv_rtp_extensions_,
2075 call_)));
2057 2076
2058 SetNack(channel, nack_enabled_); 2077 SetNack(channel, send_codec_spec_.nack_enabled);
2059 SetPlayout(channel, playout_); 2078 SetPlayout(channel, playout_);
2060 2079
2061 return true; 2080 return true;
2062 } 2081 }
2063 2082
2064 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) { 2083 bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
2065 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2084 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2066 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; 2085 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
2067 2086
2068 const auto it = recv_streams_.find(ssrc); 2087 const auto it = recv_streams_.find(ssrc);
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
2352 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBandwidth."; 2371 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBandwidth.";
2353 return SetSendBitrateInternal(bps); 2372 return SetSendBitrateInternal(bps);
2354 } 2373 }
2355 2374
2356 bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) { 2375 bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) {
2357 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendBitrateInternal."; 2376 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendBitrateInternal.";
2358 2377
2359 send_bitrate_setting_ = true; 2378 send_bitrate_setting_ = true;
2360 send_bitrate_bps_ = bps; 2379 send_bitrate_bps_ = bps;
2361 2380
2362 if (!send_codec_) { 2381 if (!HasSendCodec()) {
2363 LOG(LS_INFO) << "The send codec has not been set up yet. " 2382 LOG(LS_INFO) << "The send codec has not been set up yet. "
2364 << "The send bitrate setting will be applied later."; 2383 << "The send bitrate setting will be applied later.";
2365 return true; 2384 return true;
2366 } 2385 }
2367 2386
2368 // Bitrate is auto by default. 2387 // Bitrate is auto by default.
2369 // TODO(bemasc): Fix this so that if SetMaxSendBandwidth(50) is followed by 2388 // TODO(bemasc): Fix this so that if SetMaxSendBandwidth(50) is followed by
2370 // SetMaxSendBandwith(0), the second call removes the previous limit. 2389 // SetMaxSendBandwith(0), the second call removes the previous limit.
2371 if (bps <= 0) 2390 if (bps <= 0)
2372 return true; 2391 return true;
2373 2392
2374 webrtc::CodecInst codec = *send_codec_; 2393 webrtc::CodecInst codec = send_codec_spec_.codec_inst;
2375 bool is_multi_rate = WebRtcVoiceCodecs::IsCodecMultiRate(codec); 2394 bool is_multi_rate = WebRtcVoiceCodecs::IsCodecMultiRate(codec);
2376 2395
2377 if (is_multi_rate) { 2396 if (is_multi_rate) {
2378 // If codec is multi-rate then just set the bitrate. 2397 // If codec is multi-rate then just set the bitrate.
2379 codec.rate = bps; 2398 codec.rate = bps;
2380 for (const auto& ch : send_streams_) { 2399 for (const auto& ch : send_streams_) {
2381 if (!SetSendCodec(ch.second->channel(), codec)) { 2400 if (!SetSendCodec(ch.second->channel(), codec)) {
2382 LOG(LS_INFO) << "Failed to set codec " << codec.plname 2401 LOG(LS_INFO) << "Failed to set codec " << codec.plname
2383 << " to bitrate " << bps << " bps."; 2402 << " to bitrate " << bps << " bps.";
2384 return false; 2403 return false;
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
2520 } 2539 }
2521 } else { 2540 } else {
2522 LOG(LS_INFO) << "Stopping playout for channel #" << channel; 2541 LOG(LS_INFO) << "Stopping playout for channel #" << channel;
2523 engine()->voe()->base()->StopPlayout(channel); 2542 engine()->voe()->base()->StopPlayout(channel);
2524 } 2543 }
2525 return true; 2544 return true;
2526 } 2545 }
2527 } // namespace cricket 2546 } // namespace cricket
2528 2547
2529 #endif // HAVE_WEBRTC_VOICE 2548 #endif // HAVE_WEBRTC_VOICE
OLDNEW
« no previous file with comments | « webrtc/media/engine/webrtcvoiceengine.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698