diff --git a/samples/js/apprtc/apprtc.py b/samples/js/apprtc/apprtc.py index 9df12a0975..6bb65c8da9 100644 --- a/samples/js/apprtc/apprtc.py +++ b/samples/js/apprtc/apprtc.py @@ -45,6 +45,17 @@ def get_default_stun_server(user_agent): default_stun_server = 'stun.services.mozilla.com' return default_stun_server +def get_preferred_audio_receive_codec(): + return 'opus/48000' + +def get_preferred_audio_send_codec(user_agent): + # Empty string means no preference. + preferred_audio_send_codec = '' + # Prefer to send ISAC on Chrome for Android. + if 'Android' in user_agent and 'Chrome' in user_agent: + preferred_audio_send_codec = 'ISAC/16000' + return preferred_audio_send_codec + def make_pc_config(stun_server, turn_server, ts_pwd): servers = [] if turn_server: @@ -300,6 +311,12 @@ class MainPage(webapp2.RequestHandler): turn_server = self.request.get('ts') min_re = self.request.get('minre') max_re = self.request.get('maxre') + audio_send_codec = self.request.get('asc') + if not audio_send_codec: + audio_send_codec = get_preferred_audio_send_codec(user_agent) + audio_receive_codec = self.request.get('arc') + if not audio_receive_codec: + audio_receive_codec = get_preferred_audio_receive_codec() hd_video = self.request.get('hd') turn_url = 'https://computeengineondemand.appspot.com/' if hd_video.lower() == 'true': @@ -382,7 +399,9 @@ class MainPage(webapp2.RequestHandler): 'offer_constraints': json.dumps(offer_constraints), 'media_constraints': json.dumps(media_constraints), 'turn_url': turn_url, - 'stereo': stereo + 'stereo': stereo, + 'audio_send_codec': audio_send_codec, + 'audio_receive_codec': audio_receive_codec } if unittest: target_page = 'test/test_' + unittest + '.html' diff --git a/samples/js/apprtc/index.html b/samples/js/apprtc/index.html index efbdfe8562..71d3cd78e7 100644 --- a/samples/js/apprtc/index.html +++ b/samples/js/apprtc/index.html @@ -27,7 +27,8 @@ var mediaConstraints = {{ media_constraints | safe }}; var turnUrl = '{{ turn_url }}'; var stereo = {{ stereo }}; - + var audio_send_codec = '{{ audio_send_codec }}'; + var audio_receive_codec = '{{ audio_receive_codec }}'; setTimeout(initialize, 1);
diff --git a/samples/js/apprtc/js/main.js b/samples/js/apprtc/js/main.js index 6a9396bd83..b704f8cf59 100644 --- a/samples/js/apprtc/js/main.js +++ b/samples/js/apprtc/js/main.js @@ -14,8 +14,8 @@ var signalingReady = false; var msgQueue = []; // Set up audio and video regardless of what devices are present. var sdpConstraints = {'mandatory': { - 'OfferToReceiveAudio': true, - 'OfferToReceiveVideo': true }}; + 'OfferToReceiveAudio': true, + 'OfferToReceiveVideo': true }}; var isVideoMuted = false; var isAudioMuted = false; // Types of gathered ICE Candidates. @@ -199,13 +199,21 @@ function mergeConstraints(cons1, cons2) { } function setLocalAndSendMessage(sessionDescription) { - // Set Opus as the preferred codec in SDP if Opus is present. - sessionDescription.sdp = preferOpus(sessionDescription.sdp); + sessionDescription.sdp = maybePreferAudioReceiveCodec(sessionDescription.sdp); pc.setLocalDescription(sessionDescription, onSetSessionDescriptionSuccess, onSetSessionDescriptionError); sendMessage(sessionDescription); } +function setRemote(message) { + // Set Opus in Stereo, if stereo enabled. + if (stereo) + message.sdp = addStereo(message.sdp); + message.sdp = maybePreferAudioSendCodec(message.sdp); + pc.setRemoteDescription(new RTCSessionDescription(message), + onSetSessionDescriptionSuccess, onSetSessionDescriptionError); +} + function sendMessage(message) { var msgString = JSON.stringify(message); console.log('C->S: ' + msgString); @@ -224,18 +232,10 @@ function processSignalingMessage(message) { } if (message.type === 'offer') { - // Set Opus in Stereo, if stereo enabled. - if (stereo) - message.sdp = addStereo(message.sdp); - pc.setRemoteDescription(new RTCSessionDescription(message), - onSetSessionDescriptionSuccess, onSetSessionDescriptionError); + setRemote(message); doAnswer(); } else if (message.type === 'answer') { - // Set Opus in Stereo, if stereo enabled. - if (stereo) - message.sdp = addStereo(message.sdp); - pc.setRemoteDescription(new RTCSessionDescription(message), - onSetSessionDescriptionSuccess, onSetSessionDescriptionError); + setRemote(message); } else if (message.type === 'candidate') { var candidate = new RTCIceCandidate({sdpMLineIndex: message.label, candidate: message.candidate}); @@ -297,7 +297,7 @@ function onUserMediaError(error) { } function onCreateSessionDescriptionError(error) { - console.log('Failed to create session description: ' + error.name); + console.log('Failed to create session description: ' + error.toString()); } function onSetSessionDescriptionSuccess() { @@ -305,7 +305,7 @@ function onSetSessionDescriptionSuccess() { } function onSetSessionDescriptionError(error) { - console.log('Failed to set session description: ' + error.name); + console.log('Failed to set session description: ' + error.toString()); } function iceCandidateType(candidateSDP) { @@ -533,8 +533,34 @@ document.onkeydown = function(event) { } } -// Set Opus as the default audio codec if it's present. -function preferOpus(sdp) { +function maybePreferAudioSendCodec(sdp) { + if (audio_send_codec == '') { + console.log('No preference on audio send codec.'); + return sdp; + } + console.log('Prefer audio send codec: ' + audio_send_codec); + return preferAudioCodec(sdp, audio_send_codec); +} + +function maybePreferAudioReceiveCodec(sdp) { + if (audio_receive_codec == '') { + console.log('No preference on audio receive codec.'); + return sdp; + } + console.log('Prefer audio receive codec: ' + audio_receive_codec); + return preferAudioCodec(sdp, audio_receive_codec); +} + +// Set |codec| as the default audio codec if it's present. +// The format of |codec| is 'NAME/RATE', e.g. 'opus/48000'. +function preferAudioCodec(sdp, codec) { + var fields = codec.split('/'); + if (fields.length != 2) { + console.log('Invalid codec setting: ' + codec); + return sdp; + } + var name = fields[0]; + var rate = fields[1]; var sdpLines = sdp.split('\r\n'); // Search for m line. @@ -547,13 +573,14 @@ function preferOpus(sdp) { if (mLineIndex === null) return sdp; - // If Opus is available, set it as the default in m line. + // If the codec is available, set it as the default in m line. for (var i = 0; i < sdpLines.length; i++) { - if (sdpLines[i].search('opus/48000') !== -1) { - var opusPayload = extractSdp(sdpLines[i], /:(\d+) opus\/48000/i); - if (opusPayload) + if (sdpLines[i].search(name + '/' + rate) !== -1) { + var regexp = new RegExp(':(\\d+) ' + name + '\\/' + rate, 'i'); + var payload = extractSdp(sdpLines[i], regexp); + if (payload) sdpLines[mLineIndex] = setDefaultCodec(sdpLines[mLineIndex], - opusPayload); + payload); break; } }