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

Unified Diff: webrtc/audio/audio_send_stream.cc

Issue 2405183002: Moving WebRtcVoiceMediaChannel::SendSetCodec to AudioSendStream. (Closed)
Patch Set: final change Created 4 years, 2 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/audio/audio_send_stream.h ('k') | webrtc/audio/audio_send_stream_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/audio/audio_send_stream.cc
diff --git a/webrtc/audio/audio_send_stream.cc b/webrtc/audio/audio_send_stream.cc
index ee84b96aaa3700a8e7d937e0cf3d4ec1dfd0990d..fbed0f12af09281f57adc8620a3de708d1bb5a63 100644
--- a/webrtc/audio/audio_send_stream.cc
+++ b/webrtc/audio/audio_send_stream.cc
@@ -30,6 +30,34 @@
#include "webrtc/voice_engine/voice_engine_impl.h"
namespace webrtc {
+
+namespace {
+
+constexpr char kOpusCodecName[] = "opus";
+
+// TODO(minyue): Remove |LOG_RTCERR2|.
+#define LOG_RTCERR2(func, a1, a2, err) \
+ LOG(LS_WARNING) << "" << #func << "(" << a1 << ", " << a2 \
+ << ") failed, err=" << err
+
+// TODO(minyue): Remove |LOG_RTCERR3|.
+#define LOG_RTCERR3(func, a1, a2, a3, err) \
+ LOG(LS_WARNING) << "" << #func << "(" << a1 << ", " << a2 << ", " << a3 \
+ << ") failed, err=" << err
+
+std::string ToString(const webrtc::CodecInst& codec) {
+ std::stringstream ss;
+ ss << codec.plname << "/" << codec.plfreq << "/" << codec.channels << " ("
+ << codec.pltype << ")";
+ return ss.str();
+}
+
+bool IsCodec(const webrtc::CodecInst& codec, const char* ref_name) {
+ return (_stricmp(codec.plname, ref_name) == 0);
+}
+
+} // namespace
+
std::string AudioSendStream::Config::Rtp::ToString() const {
std::stringstream ss;
ss << "{ssrc: " << ssrc;
@@ -52,7 +80,7 @@ std::string AudioSendStream::Config::ToString() const {
ss << "{rtp: " << rtp.ToString();
ss << ", voe_channel_id: " << voe_channel_id;
// TODO(solenberg): Encoder config.
- ss << ", cng_payload_type: " << cng_payload_type;
+ ss << ", cng_payload_type: " << send_codec_spec.cng_payload_type;
ss << '}';
return ss.str();
}
@@ -102,6 +130,9 @@ AudioSendStream::AudioSendStream(
RTC_NOTREACHED() << "Registering unsupported RTP extension.";
}
}
+ if (!SetupSendCodec()) {
+ LOG(LS_ERROR) << "Failed to set up send codec state.";
+ }
}
AudioSendStream::~AudioSendStream() {
@@ -285,5 +316,127 @@ VoiceEngine* AudioSendStream::voice_engine() const {
RTC_DCHECK(voice_engine);
return voice_engine;
}
+
+// Apply current codec settings to a single voe::Channel used for sending.
+bool AudioSendStream::SetupSendCodec() {
+ ScopedVoEInterface<VoEBase> base(voice_engine());
+ ScopedVoEInterface<VoECodec> codec(voice_engine());
+
+ const int channel = config_.voe_channel_id;
+
+ // Disable VAD and FEC unless we know the other side wants them.
+ codec->SetVADStatus(channel, false);
+ codec->SetFECStatus(channel, false);
+
+ const auto& send_codec_spec = config_.send_codec_spec;
+
+ // Set the codec immediately, since SetVADStatus() depends on whether
+ // the current codec is mono or stereo.
+ LOG(LS_INFO) << "Send channel " << channel << " selected voice codec "
+ << ToString(send_codec_spec.codec_inst)
+ << ", bitrate=" << send_codec_spec.codec_inst.rate;
+
+ // If codec is already configured, we do not it again.
+ // TODO(minyue): check if this check is really needed, or can we move it into
+ // |codec->SetSendCodec|.
+ webrtc::CodecInst current_codec = {0};
+ if (codec->GetSendCodec(channel, current_codec) != 0 ||
+ (send_codec_spec.codec_inst != current_codec)) {
+ if (codec->SetSendCodec(channel, send_codec_spec.codec_inst) == -1) {
+ LOG_RTCERR2(SetSendCodec, channel, ToString(send_codec_spec.codec_inst),
+ base->LastError());
+ return false;
+ }
+ }
+
+ // FEC should be enabled after SetSendCodec.
+ if (send_codec_spec.enable_codec_fec) {
+ LOG(LS_INFO) << "Attempt to enable codec internal FEC on channel "
+ << channel;
+ if (codec->SetFECStatus(channel, true) == -1) {
+ // Enable codec internal FEC. Treat any failure as fatal internal error.
+ LOG_RTCERR2(SetFECStatus, channel, true, base->LastError());
+ return false;
+ }
+ }
+
+ if (IsCodec(send_codec_spec.codec_inst, kOpusCodecName)) {
+ // DTX and maxplaybackrate should be set after SetSendCodec. Because current
+ // send codec has to be Opus.
+
+ // Set Opus internal DTX.
+ LOG(LS_INFO) << "Attempt to "
+ << (send_codec_spec.enable_opus_dtx ? "enable" : "disable")
+ << " Opus DTX on channel " << channel;
+ if (codec->SetOpusDtx(channel, send_codec_spec.enable_opus_dtx)) {
+ LOG_RTCERR2(SetOpusDtx, channel, send_codec_spec.enable_opus_dtx,
+ base->LastError());
+ return false;
+ }
+
+ // If opus_max_playback_rate <= 0, the default maximum playback rate
+ // (48 kHz) will be used.
+ if (send_codec_spec.opus_max_playback_rate > 0) {
+ LOG(LS_INFO) << "Attempt to set maximum playback rate to "
+ << send_codec_spec.opus_max_playback_rate
+ << " Hz on channel " << channel;
+ if (codec->SetOpusMaxPlaybackRate(
+ channel, send_codec_spec.opus_max_playback_rate) == -1) {
+ LOG_RTCERR2(SetOpusMaxPlaybackRate, channel,
+ send_codec_spec.opus_max_playback_rate, base->LastError());
+ return false;
+ }
+ }
+ }
+
+ // Set the CN payloadtype and the VAD status.
+ if (send_codec_spec.cng_payload_type != -1) {
+ // The CN payload type for 8000 Hz clockrate is fixed at 13.
+ if (send_codec_spec.cng_plfreq != 8000) {
+ webrtc::PayloadFrequencies cn_freq;
+ switch (send_codec_spec.cng_plfreq) {
+ case 16000:
+ cn_freq = webrtc::kFreq16000Hz;
+ break;
+ case 32000:
+ cn_freq = webrtc::kFreq32000Hz;
+ break;
+ default:
+ RTC_NOTREACHED();
+ return false;
+ }
+ if (codec->SetSendCNPayloadType(channel, send_codec_spec.cng_payload_type,
+ cn_freq) == -1) {
+ LOG_RTCERR3(SetSendCNPayloadType, channel,
+ send_codec_spec.cng_payload_type, cn_freq,
+ base->LastError());
+
+ // TODO(ajm): This failure condition will be removed from VoE.
+ // Restore the return here when we update to a new enough webrtc.
+ //
+ // Not returning false because the SetSendCNPayloadType will fail if
+ // the channel is already sending.
+ // This can happen if the remote description is applied twice, for
+ // example in the case of ROAP on top of JSEP, where both side will
+ // send the offer.
+ }
+ }
+
+ // Only turn on VAD if we have a CN payload type that matches the
+ // clockrate for the codec we are going to use.
+ if (send_codec_spec.cng_plfreq == send_codec_spec.codec_inst.plfreq &&
+ send_codec_spec.codec_inst.channels == 1) {
+ // TODO(minyue): If CN frequency == 48000 Hz is allowed, consider the
+ // interaction between VAD and Opus FEC.
+ LOG(LS_INFO) << "Enabling VAD";
+ if (codec->SetVADStatus(channel, true) == -1) {
+ LOG_RTCERR2(SetVADStatus, channel, true, base->LastError());
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
} // namespace internal
} // namespace webrtc
« no previous file with comments | « webrtc/audio/audio_send_stream.h ('k') | webrtc/audio/audio_send_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698