diff --git a/samples/js/OWNERS b/samples/js/OWNERS deleted file mode 100644 index 79b28349a..000000000 --- a/samples/js/OWNERS +++ /dev/null @@ -1,9 +0,0 @@ -braveyao@webrtc.org -dutton@google.com -henrika@webrtc.org -hta@webrtc.org -juberti@webrtc.org -kjellander@webrtc.org -phoglund@webrtc.org -vikasmarwaha@webrtc.org -wu@webrtc.org diff --git a/samples/js/apprtc/app.yaml b/samples/js/apprtc/app.yaml deleted file mode 100644 index 6ef5e7505..000000000 --- a/samples/js/apprtc/app.yaml +++ /dev/null @@ -1,29 +0,0 @@ -application: apprtc -version: 6 -runtime: python27 -threadsafe: true -api_version: 1 - -handlers: -- url: /html - static_dir: html - -- url: /images - static_dir: images - -- url: /js - static_dir: js - -- url: /css - static_dir: css - -- url: /.* - script: apprtc.app - secure: always - -inbound_services: -- channel_presence - -libraries: -- name: jinja2 - version: latest diff --git a/samples/js/apprtc/apprtc.py b/samples/js/apprtc/apprtc.py deleted file mode 100644 index 3652c8efd..000000000 --- a/samples/js/apprtc/apprtc.py +++ /dev/null @@ -1,482 +0,0 @@ -#!/usr/bin/python2.4 -# -# Copyright 2011 Google Inc. All Rights Reserved. - -"""WebRTC Demo - -This module demonstrates the WebRTC API by implementing a simple video chat app. -""" - -import cgi -import logging -import os -import random -import re -import json -import jinja2 -import webapp2 -import threading -from google.appengine.api import channel -from google.appengine.ext import db - -jinja_environment = jinja2.Environment( - loader=jinja2.FileSystemLoader(os.path.dirname(__file__))) - -# Lock for syncing DB operation in concurrent requests handling. -# TODO(brave): keeping working on improving performance with thread syncing. -# One possible method for near future is to reduce the message caching. -LOCK = threading.RLock() - -def generate_random(length): - word = '' - for _ in range(length): - word += random.choice('0123456789') - return word - -def sanitize(key): - return re.sub('[^a-zA-Z0-9\-]', '-', key) - -def make_client_id(room, user): - return room.key().id_or_name() + '/' + user - -def get_default_stun_server(user_agent): - default_stun_server = 'stun.l.google.com:19302' - if 'Firefox' in 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: - turn_config = 'turn:{}'.format(turn_server) - servers.append({'urls':turn_config, 'credential':ts_pwd}) - if stun_server: - stun_config = 'stun:{}'.format(stun_server) - servers.append({'urls':stun_config}) - return {'iceServers':servers} - -def create_channel(room, user, duration_minutes): - client_id = make_client_id(room, user) - return channel.create_channel(client_id, duration_minutes) - -def make_loopback_answer(message): - message = message.replace("\"offer\"", "\"answer\"") - message = message.replace("a=ice-options:google-ice\\r\\n", "") - return message - -def handle_message(room, user, message): - message_obj = json.loads(message) - other_user = room.get_other_user(user) - room_key = room.key().id_or_name() - if message_obj['type'] == 'bye': - # This would remove the other_user in loopback test too. - # So check its availability before forwarding Bye message. - room.remove_user(user) - logging.info('User ' + user + ' quit from room ' + room_key) - logging.info('Room ' + room_key + ' has state ' + str(room)) - if other_user and room.has_user(other_user): - if message_obj['type'] == 'offer': - # Special case the loopback scenario. - if other_user == user: - message = make_loopback_answer(message) - on_message(room, other_user, message) - else: - # For unittest - on_message(room, user, message) - -def get_saved_messages(client_id): - return Message.gql("WHERE client_id = :id", id=client_id) - -def delete_saved_messages(client_id): - messages = get_saved_messages(client_id) - for message in messages: - message.delete() - logging.info('Deleted the saved message for ' + client_id) - -def send_saved_messages(client_id): - messages = get_saved_messages(client_id) - for message in messages: - channel.send_message(client_id, message.msg) - logging.info('Delivered saved message to ' + client_id) - message.delete() - -def on_message(room, user, message): - client_id = make_client_id(room, user) - if room.is_connected(user): - channel.send_message(client_id, message) - logging.info('Delivered message to user ' + user) - else: - new_message = Message(client_id = client_id, msg = message) - new_message.put() - logging.info('Saved message for user ' + user) - -def make_media_track_constraints(constraints_string): - if not constraints_string or constraints_string.lower() == 'true': - track_constraints = True - elif constraints_string.lower() == 'false': - track_constraints = False - else: - track_constraints = {'mandatory': {}, 'optional': []} - for constraint_string in constraints_string.split(','): - constraint = constraint_string.split('=') - if len(constraint) != 2: - logging.error('Ignoring malformed constraint: ' + constraint_string) - continue - if constraint[0].startswith('goog'): - track_constraints['optional'].append({constraint[0]: constraint[1]}) - else: - track_constraints['mandatory'][constraint[0]] = constraint[1] - - return track_constraints - -def make_media_stream_constraints(audio, video): - stream_constraints = ( - {'audio': make_media_track_constraints(audio), - 'video': make_media_track_constraints(video)}) - logging.info('Applying media constraints: ' + str(stream_constraints)) - return stream_constraints - -def maybe_add_constraint(constraints, param, constraint): - if (param.lower() == 'true'): - constraints['optional'].append({constraint: True}) - elif (param.lower() == 'false'): - constraints['optional'].append({constraint: False}) - - return constraints - -def make_pc_constraints(dtls, dscp, ipv6): - constraints = { 'optional': [] } - maybe_add_constraint(constraints, dtls, 'DtlsSrtpKeyAgreement') - maybe_add_constraint(constraints, dscp, 'googDscp') - maybe_add_constraint(constraints, ipv6, 'googIPv6') - - return constraints - -def make_offer_constraints(): - constraints = { 'mandatory': {}, 'optional': [] } - return constraints - -def append_url_arguments(request, link): - for argument in request.arguments(): - if argument != 'r': - link += ('&' + cgi.escape(argument, True) + '=' + - cgi.escape(request.get(argument), True)) - return link - -# This database is to store the messages from the sender client when the -# receiver client is not ready to receive the messages. -# Use TextProperty instead of StringProperty for msg because -# the session description can be more than 500 characters. -class Message(db.Model): - client_id = db.StringProperty() - msg = db.TextProperty() - -class Room(db.Model): - """All the data we store for a room""" - user1 = db.StringProperty() - user2 = db.StringProperty() - user1_connected = db.BooleanProperty(default=False) - user2_connected = db.BooleanProperty(default=False) - - def __str__(self): - result = '[' - if self.user1: - result += "%s-%r" % (self.user1, self.user1_connected) - if self.user2: - result += ", %s-%r" % (self.user2, self.user2_connected) - result += ']' - return result - - def get_occupancy(self): - occupancy = 0 - if self.user1: - occupancy += 1 - if self.user2: - occupancy += 1 - return occupancy - - def get_other_user(self, user): - if user == self.user1: - return self.user2 - elif user == self.user2: - return self.user1 - else: - return None - - def has_user(self, user): - return (user and (user == self.user1 or user == self.user2)) - - def add_user(self, user): - if not self.user1: - self.user1 = user - elif not self.user2: - self.user2 = user - else: - raise RuntimeError('room is full') - self.put() - - def remove_user(self, user): - delete_saved_messages(make_client_id(self, user)) - if user == self.user2: - self.user2 = None - self.user2_connected = False - if user == self.user1: - if self.user2: - self.user1 = self.user2 - self.user1_connected = self.user2_connected - self.user2 = None - self.user2_connected = False - else: - self.user1 = None - self.user1_connected = False - if self.get_occupancy() > 0: - self.put() - else: - self.delete() - - def set_connected(self, user): - if user == self.user1: - self.user1_connected = True - if user == self.user2: - self.user2_connected = True - self.put() - - def is_connected(self, user): - if user == self.user1: - return self.user1_connected - if user == self.user2: - return self.user2_connected - -@db.transactional -def connect_user_to_room(room_key, user): - room = Room.get_by_key_name(room_key) - # Check if room has user in case that disconnect message comes before - # connect message with unknown reason, observed with local AppEngine SDK. - if room and room.has_user(user): - room.set_connected(user) - logging.info('User ' + user + ' connected to room ' + room_key) - logging.info('Room ' + room_key + ' has state ' + str(room)) - else: - logging.warning('Unexpected Connect Message to room ' + room_key) - return room - -class ConnectPage(webapp2.RequestHandler): - def post(self): - key = self.request.get('from') - room_key, user = key.split('/') - with LOCK: - room = connect_user_to_room(room_key, user) - if room and room.has_user(user): - send_saved_messages(make_client_id(room, user)) - -class DisconnectPage(webapp2.RequestHandler): - def post(self): - key = self.request.get('from') - room_key, user = key.split('/') - with LOCK: - room = Room.get_by_key_name(room_key) - if room and room.has_user(user): - other_user = room.get_other_user(user) - room.remove_user(user) - logging.info('User ' + user + ' removed from room ' + room_key) - logging.info('Room ' + room_key + ' has state ' + str(room)) - if other_user and other_user != user: - channel.send_message(make_client_id(room, other_user), - '{"type":"bye"}') - logging.info('Sent BYE to ' + other_user) - logging.warning('User ' + user + ' disconnected from room ' + room_key) - - -class MessagePage(webapp2.RequestHandler): - def post(self): - message = self.request.body - room_key = self.request.get('r') - user = self.request.get('u') - with LOCK: - room = Room.get_by_key_name(room_key) - if room: - handle_message(room, user, message) - else: - logging.warning('Unknown room ' + room_key) - -class MainPage(webapp2.RequestHandler): - """The main UI page, renders the 'index.html' template.""" - def get(self): - """Renders the main page. When this page is shown, we create a new - channel to push asynchronous updates to the client.""" - - # Append strings to this list to have them thrown up in message boxes. This - # will also cause the app to fail. - error_messages = [] - # Get the base url without arguments. - base_url = self.request.path_url - user_agent = self.request.headers['User-Agent'] - room_key = sanitize(self.request.get('r')) - stun_server = self.request.get('ss') - if not stun_server: - stun_server = get_default_stun_server(user_agent) - turn_server = self.request.get('ts') - ts_pwd = self.request.get('tp') - - # Use "audio" and "video" to set the media stream constraints. Defined here: - # http://goo.gl/V7cZg - # - # "true" and "false" are recognized and interpreted as bools, for example: - # "?audio=true&video=false" (Start an audio-only call.) - # "?audio=false" (Start a video-only call.) - # If unspecified, the stream constraint defaults to True. - # - # To specify media track constraints, pass in a comma-separated list of - # key/value pairs, separated by a "=". Examples: - # "?audio=googEchoCancellation=false,googAutoGainControl=true" - # (Disable echo cancellation and enable gain control.) - # - # "?video=minWidth=1280,minHeight=720,googNoiseReduction=true" - # (Set the minimum resolution to 1280x720 and enable noise reduction.) - # - # Keys starting with "goog" will be added to the "optional" key; all others - # will be added to the "mandatory" key. - # - # The audio keys are defined here: talk/app/webrtc/localaudiosource.cc - # The video keys are defined here: talk/app/webrtc/videosource.cc - audio = self.request.get('audio') - video = self.request.get('video') - - if self.request.get('hd').lower() == 'true': - if video: - message = 'The "hd" parameter has overridden video=' + str(video) - logging.error(message) - error_messages.append(message) - video = 'minWidth=1280,minHeight=720' - - if self.request.get('minre') or self.request.get('maxre'): - message = ('The "minre" and "maxre" parameters are no longer supported. ' - 'Use "video" instead.') - logging.error(message) - error_messages.append(message) - - 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() - - # Set stereo to false by default. - stereo = 'false' - if self.request.get('stereo'): - stereo = self.request.get('stereo') - - # Options for making pcConstraints - dtls = self.request.get('dtls') - dscp = self.request.get('dscp') - ipv6 = self.request.get('ipv6') - - debug = self.request.get('debug') - if debug == 'loopback': - # Set dtls to false as DTLS does not work for loopback. - dtls = 'false' - - # token_timeout for channel creation, default 30min, max 1 days, min 3min. - token_timeout = self.request.get_range('tt', - min_value = 3, - max_value = 1440, - default = 30) - - unittest = self.request.get('unittest') - if unittest: - # Always create a new room for the unit tests. - room_key = generate_random(8) - - if not room_key: - room_key = generate_random(8) - redirect = '/?r=' + room_key - redirect = append_url_arguments(self.request, redirect) - self.redirect(redirect) - logging.info('Redirecting visitor to base URL to ' + redirect) - return - - user = None - initiator = 0 - with LOCK: - room = Room.get_by_key_name(room_key) - if not room and debug != "full": - # New room. - user = generate_random(8) - room = Room(key_name = room_key) - room.add_user(user) - if debug != 'loopback': - initiator = 0 - else: - room.add_user(user) - initiator = 1 - elif room and room.get_occupancy() == 1 and debug != 'full': - # 1 occupant. - user = generate_random(8) - room.add_user(user) - initiator = 1 - else: - # 2 occupants (full). - template = jinja_environment.get_template('full.html') - self.response.out.write(template.render({ 'room_key': room_key })) - logging.info('Room ' + room_key + ' is full') - return - - if turn_server == 'false': - turn_server = None - turn_url = '' - else: - turn_url = 'https://computeengineondemand.appspot.com/' - turn_url = turn_url + 'turn?' + 'username=' + user + '&key=4080218913' - - room_link = base_url + '?r=' + room_key - room_link = append_url_arguments(self.request, room_link) - token = create_channel(room, user, token_timeout) - pc_config = make_pc_config(stun_server, turn_server, ts_pwd) - pc_constraints = make_pc_constraints(dtls, dscp, ipv6) - offer_constraints = make_offer_constraints() - media_constraints = make_media_stream_constraints(audio, video) - template_values = {'error_messages': error_messages, - 'token': token, - 'me': user, - 'room_key': room_key, - 'room_link': room_link, - 'initiator': initiator, - 'pc_config': json.dumps(pc_config), - 'pc_constraints': json.dumps(pc_constraints), - 'offer_constraints': json.dumps(offer_constraints), - 'media_constraints': json.dumps(media_constraints), - 'turn_url': turn_url, - 'stereo': stereo, - 'audio_send_codec': audio_send_codec, - 'audio_receive_codec': audio_receive_codec - } - if unittest: - target_page = 'test/test_' + unittest + '.html' - else: - target_page = 'index.html' - - template = jinja_environment.get_template(target_page) - self.response.out.write(template.render(template_values)) - logging.info('User ' + user + ' added to room ' + room_key) - logging.info('Room ' + room_key + ' has state ' + str(room)) - - -app = webapp2.WSGIApplication([ - ('/', MainPage), - ('/message', MessagePage), - ('/_ah/channel/connected/', ConnectPage), - ('/_ah/channel/disconnected/', DisconnectPage) - ], debug=True) diff --git a/samples/js/apprtc/css/main.css b/samples/js/apprtc/css/main.css deleted file mode 100644 index 15d9eee2b..000000000 --- a/samples/js/apprtc/css/main.css +++ /dev/null @@ -1,95 +0,0 @@ -a:link { color: #FFFFFF; } -a:visited {color: #FFFFFF; } -html, body { - background-color: #000000; - height: 100%; - font-family: Verdana, Arial, Helvetica, sans-serif; -} -body { - margin: 0; - padding: 0; -} -footer { - position: absolute; - bottom: 0; - width: 100%; - height: 28px; - background-color: #3F3F3F; - color: #FFFFFF; - font-size: 13px; font-weight: bold; - line-height: 28px; - text-align: center; -} -#container { - background-color: #000000; - position: absolute; - height: 100%; - width: 100%; - margin: 0px auto; - -webkit-perspective: 1000; -} -#card { - -webkit-transition-duration: 2s; - -webkit-transform-style: preserve-3d; -} -#local { - position: absolute; - width: 100%; - transform: scale(-1, 1); - -webkit-transform: scale(-1, 1); - -webkit-backface-visibility: hidden; -} -#remote { - position: absolute; - width: 100%; - -webkit-transform: rotateY(180deg); - -webkit-backface-visibility: hidden; -} -#mini { - position: absolute; - height: 30%; - width: 30%; - bottom: 32px; - right: 4px; - opacity: 1.0; - transform: scale(-1, 1); - -webkit-transform: scale(-1, 1); -} -#localVideo { - width: 100%; - height: 100%; - opacity: 0; - -webkit-transition-property: opacity; - -webkit-transition-duration: 2s; -} -#remoteVideo { - width: 100%; - height: 100%; - opacity: 0; - -webkit-transition-property: opacity; - -webkit-transition-duration: 2s; -} -#miniVideo { - width: 100%; - height: 100%; - opacity: 0; - -webkit-transition-property: opacity; - -webkit-transition-duration: 2s; -} -#hangup { - font-size: 13px; font-weight: bold; - color: #FFFFFF; - width: 128px; - height: 24px; - background-color: #808080; - border-style: solid; - border-color: #FFFFFF; - margin: 2px; -} -#infoDiv { - position: absolute; - float: right; - background-color: grey; - margin: 2px; - display: none; -} diff --git a/samples/js/apprtc/full.html b/samples/js/apprtc/full.html deleted file mode 100644 index b14ac6009..000000000 --- a/samples/js/apprtc/full.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - -
- -
- - - diff --git a/samples/js/apprtc/html/help.html b/samples/js/apprtc/html/help.html deleted file mode 100644 index 7fd2bf624..000000000 --- a/samples/js/apprtc/html/help.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - WebRtc Demo App Help - - -TODO - - diff --git a/samples/js/apprtc/images/webrtc_black_20p.png b/samples/js/apprtc/images/webrtc_black_20p.png deleted file mode 100644 index a35c1dff2..000000000 Binary files a/samples/js/apprtc/images/webrtc_black_20p.png and /dev/null differ diff --git a/samples/js/apprtc/index.html b/samples/js/apprtc/index.html deleted file mode 100644 index a240f2980..000000000 --- a/samples/js/apprtc/index.html +++ /dev/null @@ -1,53 +0,0 @@ - - - -WebRTC Reference App - - - - - - - - - - - - - - -
-
-
-
-
- -
-
-
-
-
- - -
- diff --git a/samples/js/apprtc/js/adapter.js b/samples/js/apprtc/js/adapter.js deleted file mode 120000 index c19e2ce99..000000000 --- a/samples/js/apprtc/js/adapter.js +++ /dev/null @@ -1 +0,0 @@ -../../base/adapter.js \ No newline at end of file diff --git a/samples/js/apprtc/js/main.js b/samples/js/apprtc/js/main.js deleted file mode 100644 index 79313dcb9..000000000 --- a/samples/js/apprtc/js/main.js +++ /dev/null @@ -1,763 +0,0 @@ -var localVideo; -var miniVideo; -var remoteVideo; -var hasLocalStream; -var localStream; -var remoteStream; -var channel; -var pc; -var socket; -var xmlhttp; -var started = false; -var turnDone = false; -var channelReady = false; -var signalingReady = false; -var msgQueue = []; -// Set up audio and video regardless of what devices are present. -var sdpConstraints = {'mandatory': { - 'OfferToReceiveAudio': true, - 'OfferToReceiveVideo': true }}; -var isVideoMuted = false; -var isAudioMuted = false; -// Types of gathered ICE Candidates. -var gatheredIceCandidateTypes = { Local: {}, Remote: {} }; -var infoDivErrors = []; - -function initialize() { - if (errorMessages.length > 0) { - for (i = 0; i < errorMessages.length; ++i) { - window.alert(errorMessages[i]); - } - return; - } - - console.log('Initializing; room=' + roomKey + '.'); - card = document.getElementById('card'); - localVideo = document.getElementById('localVideo'); - // Reset localVideo display to center. - localVideo.addEventListener('loadedmetadata', function(){ - window.onresize();}); - miniVideo = document.getElementById('miniVideo'); - remoteVideo = document.getElementById('remoteVideo'); - resetStatus(); - // NOTE: AppRTCClient.java searches & parses this line; update there when - // changing here. - openChannel(); - maybeRequestTurn(); - - // Caller is always ready to create peerConnection. - signalingReady = initiator; - - if (mediaConstraints.audio === false && - mediaConstraints.video === false) { - hasLocalStream = false; - maybeStart(); - } else { - hasLocalStream = true; - doGetUserMedia(); - } -} - -function openChannel() { - console.log('Opening channel.'); - var channel = new goog.appengine.Channel(channelToken); - var handler = { - 'onopen': onChannelOpened, - 'onmessage': onChannelMessage, - 'onerror': onChannelError, - 'onclose': onChannelClosed - }; - socket = channel.open(handler); -} - -function maybeRequestTurn() { - // Allow to skip turn by passing ts=false to apprtc. - if (turnUrl == '') { - turnDone = true; - return; - } - - for (var i = 0, len = pcConfig.iceServers.length; i < len; i++) { - if (pcConfig.iceServers[i].urls.substr(0, 5) === 'turn:') { - turnDone = true; - return; - } - } - - var currentDomain = document.domain; - if (currentDomain.search('localhost') === -1 && - currentDomain.search('apprtc') === -1) { - // Not authorized domain. Try with default STUN instead. - turnDone = true; - return; - } - - // No TURN server. Get one from computeengineondemand.appspot.com. - xmlhttp = new XMLHttpRequest(); - xmlhttp.onreadystatechange = onTurnResult; - xmlhttp.open('GET', turnUrl, true); - xmlhttp.send(); -} - -function onTurnResult() { - if (xmlhttp.readyState !== 4) - return; - - if (xmlhttp.status === 200) { - var turnServer = JSON.parse(xmlhttp.responseText); - // Create turnUris using the polyfill (adapter.js). - var iceServers = createIceServers(turnServer.uris, - turnServer.username, - turnServer.password); - if (iceServers !== null) { - pcConfig.iceServers = pcConfig.iceServers.concat(iceServers); - } - } else { - messageError('No TURN server; unlikely that media will traverse networks. ' - + 'If this persists please report it to ' - + 'discuss-webrtc@googlegroups.com.'); - } - // If TURN request failed, continue the call with default STUN. - turnDone = true; - maybeStart(); -} - -function resetStatus() { - if (!initiator) { - setStatus('Waiting for someone to join: \ - ' + roomLink + ''); - } else { - setStatus('Initializing...'); - } -} - -function doGetUserMedia() { - // Call into getUserMedia via the polyfill (adapter.js). - try { - getUserMedia(mediaConstraints, onUserMediaSuccess, - onUserMediaError); - console.log('Requested access to local media with mediaConstraints:\n' + - ' \'' + JSON.stringify(mediaConstraints) + '\''); - } catch (e) { - alert('getUserMedia() failed. Is this a WebRTC capable browser?'); - messageError('getUserMedia failed with exception: ' + e.message); - } -} - -function createPeerConnection() { - try { - // Create an RTCPeerConnection via the polyfill (adapter.js). - pc = new RTCPeerConnection(pcConfig, pcConstraints); - pc.onicecandidate = onIceCandidate; - console.log('Created RTCPeerConnnection with:\n' + - ' config: \'' + JSON.stringify(pcConfig) + '\';\n' + - ' constraints: \'' + JSON.stringify(pcConstraints) + '\'.'); - } catch (e) { - messageError('Failed to create PeerConnection, exception: ' + e.message); - alert('Cannot create RTCPeerConnection object; \ - WebRTC is not supported by this browser.'); - return; - } - pc.onaddstream = onRemoteStreamAdded; - pc.onremovestream = onRemoteStreamRemoved; - pc.onsignalingstatechange = onSignalingStateChanged; - pc.oniceconnectionstatechange = onIceConnectionStateChanged; -} - -function maybeStart() { - if (!started && signalingReady && channelReady && turnDone && - (localStream || !hasLocalStream)) { - setStatus('Connecting...'); - console.log('Creating PeerConnection.'); - createPeerConnection(); - - if (hasLocalStream) { - console.log('Adding local stream.'); - pc.addStream(localStream); - } else { - console.log('Not sending any stream.'); - } - started = true; - - if (initiator) - doCall(); - else - calleeStart(); - } -} - -function setStatus(state) { - document.getElementById('status').innerHTML = state; -} - -function doCall() { - var constraints = mergeConstraints(offerConstraints, sdpConstraints); - console.log('Sending offer to peer, with constraints: \n' + - ' \'' + JSON.stringify(constraints) + '\'.') - pc.createOffer(setLocalAndSendMessage, - onCreateSessionDescriptionError, constraints); -} - -function calleeStart() { - // Callee starts to process cached offer and other messages. - while (msgQueue.length > 0) { - processSignalingMessage(msgQueue.shift()); - } -} - -function doAnswer() { - console.log('Sending answer to peer.'); - pc.createAnswer(setLocalAndSendMessage, - onCreateSessionDescriptionError, sdpConstraints); -} - -function mergeConstraints(cons1, cons2) { - var merged = cons1; - for (var name in cons2.mandatory) { - merged.mandatory[name] = cons2.mandatory[name]; - } - merged.optional.concat(cons2.optional); - return merged; -} - -function setLocalAndSendMessage(sessionDescription) { - 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), - onSetRemoteDescriptionSuccess, onSetSessionDescriptionError); - - function onSetRemoteDescriptionSuccess() { - console.log("Set remote session description success."); - // By now all addstream events for the setRemoteDescription have fired. - // So we can know if the peer is sending any stream or is only receiving. - if (remoteStream) { - waitForRemoteVideo(); - } else { - console.log("Not receiving any stream."); - transitionToActive(); - } - } -} - -function sendMessage(message) { - var msgString = JSON.stringify(message); - console.log('C->S: ' + msgString); - // NOTE: AppRTCClient.java searches & parses this line; update there when - // changing here. - path = '/message?r=' + roomKey + '&u=' + me; - var xhr = new XMLHttpRequest(); - xhr.open('POST', path, true); - xhr.send(msgString); -} - -function processSignalingMessage(message) { - if (!started) { - messageError('peerConnection has not been created yet!'); - return; - } - - if (message.type === 'offer') { - setRemote(message); - doAnswer(); - } else if (message.type === 'answer') { - setRemote(message); - } else if (message.type === 'candidate') { - var candidate = new RTCIceCandidate({sdpMLineIndex: message.label, - candidate: message.candidate}); - noteIceCandidate("Remote", iceCandidateType(message.candidate)); - pc.addIceCandidate(candidate, - onAddIceCandidateSuccess, onAddIceCandidateError); - } else if (message.type === 'bye') { - onRemoteHangup(); - } -} - -function onAddIceCandidateSuccess() { - console.log('AddIceCandidate success.'); -} - -function onAddIceCandidateError(error) { - messageError('Failed to add Ice Candidate: ' + error.toString()); -} - -function onChannelOpened() { - console.log('Channel opened.'); - channelReady = true; - maybeStart(); -} - -function onChannelMessage(message) { - console.log('S->C: ' + message.data); - var msg = JSON.parse(message.data); - // Since the turn response is async and also GAE might disorder the - // Message delivery due to possible datastore query at server side, - // So callee needs to cache messages before peerConnection is created. - if (!initiator && !started) { - if (msg.type === 'offer') { - // Add offer to the beginning of msgQueue, since we can't handle - // Early candidates before offer at present. - msgQueue.unshift(msg); - // Callee creates PeerConnection - signalingReady = true; - maybeStart(); - } else { - msgQueue.push(msg); - } - } else { - processSignalingMessage(msg); - } -} - -function onChannelError() { - messageError('Channel error.'); -} - -function onChannelClosed() { - console.log('Channel closed.'); -} - -function messageError(msg) { - console.log(msg); - infoDivErrors.push(msg); - updateInfoDiv(); -} - -function onUserMediaSuccess(stream) { - console.log('User has granted access to local media.'); - // Call the polyfill wrapper to attach the media stream to this element. - attachMediaStream(localVideo, stream); - localVideo.style.opacity = 1; - localStream = stream; - // Caller creates PeerConnection. - maybeStart(); -} - -function onUserMediaError(error) { - messageError('Failed to get access to local media. Error code was ' + - error.code + '. Continuing without sending a stream.'); - alert('Failed to get access to local media. Error code was ' + - error.code + '. Continuing without sending a stream.'); - - hasLocalStream = false; - maybeStart(); -} - -function onCreateSessionDescriptionError(error) { - messageError('Failed to create session description: ' + error.toString()); -} - -function onSetSessionDescriptionSuccess() { - console.log('Set session description success.'); -} - -function onSetSessionDescriptionError(error) { - messageError('Failed to set session description: ' + error.toString()); -} - -function iceCandidateType(candidateSDP) { - if (candidateSDP.indexOf("typ relay ") >= 0) - return "TURN"; - if (candidateSDP.indexOf("typ srflx ") >= 0) - return "STUN"; - if (candidateSDP.indexOf("typ host ") >= 0) - return "HOST"; - return "UNKNOWN"; -} - -function onIceCandidate(event) { - if (event.candidate) { - sendMessage({type: 'candidate', - label: event.candidate.sdpMLineIndex, - id: event.candidate.sdpMid, - candidate: event.candidate.candidate}); - noteIceCandidate("Local", iceCandidateType(event.candidate.candidate)); - } else { - console.log('End of candidates.'); - } -} - -function onRemoteStreamAdded(event) { - console.log('Remote stream added.'); - attachMediaStream(remoteVideo, event.stream); - remoteStream = event.stream; -} - -function onRemoteStreamRemoved(event) { - console.log('Remote stream removed.'); -} - -function onSignalingStateChanged(event) { - updateInfoDiv(); -} - -function onIceConnectionStateChanged(event) { - updateInfoDiv(); -} - -function onHangup() { - console.log('Hanging up.'); - transitionToDone(); - localStream.stop(); - stop(); - // will trigger BYE from server - socket.close(); -} - -function onRemoteHangup() { - console.log('Session terminated.'); - initiator = 0; - transitionToWaiting(); - stop(); -} - -function stop() { - started = false; - signalingReady = false; - isAudioMuted = false; - isVideoMuted = false; - pc.close(); - pc = null; - remoteStream = null; - msgQueue.length = 0; -} - -function waitForRemoteVideo() { - // Call the getVideoTracks method via adapter.js. - videoTracks = remoteStream.getVideoTracks(); - if (videoTracks.length === 0 || remoteVideo.currentTime > 0) { - transitionToActive(); - } else { - setTimeout(waitForRemoteVideo, 100); - } -} - -function transitionToActive() { - reattachMediaStream(miniVideo, localVideo); - remoteVideo.style.opacity = 1; - card.style.webkitTransform = 'rotateY(180deg)'; - setTimeout(function() { localVideo.src = ''; }, 500); - setTimeout(function() { miniVideo.style.opacity = 1; }, 1000); - // Reset window display according to the asperio of remote video. - window.onresize(); - setStatus(''); -} - -function transitionToWaiting() { - card.style.webkitTransform = 'rotateY(0deg)'; - setTimeout(function() { - localVideo.src = miniVideo.src; - miniVideo.src = ''; - remoteVideo.src = '' }, 500); - miniVideo.style.opacity = 0; - remoteVideo.style.opacity = 0; - resetStatus(); -} - -function transitionToDone() { - localVideo.style.opacity = 0; - remoteVideo.style.opacity = 0; - miniVideo.style.opacity = 0; - setStatus('You have left the call. \ - Click here to rejoin.'); -} - -function enterFullScreen() { - container.webkitRequestFullScreen(); -} - -function noteIceCandidate(location, type) { - if (gatheredIceCandidateTypes[location][type]) - return; - gatheredIceCandidateTypes[location][type] = 1; - updateInfoDiv(); -} - -function getInfoDiv() { - return document.getElementById("infoDiv"); -} - -function updateInfoDiv() { - var contents = "
Gathered ICE Candidates\n";
-  for (var endpoint in gatheredIceCandidateTypes) {
-    contents += endpoint + ":\n";
-    for (var type in gatheredIceCandidateTypes[endpoint])
-      contents += "  " + type + "\n";
-  }
-  if (pc != null) {
-    contents += "Gathering: " + pc.iceGatheringState + "\n";
-    contents += "
\n"; - contents += "
PC State:\n";
-    contents += "Signaling: " + pc.signalingState + "\n";
-    contents += "ICE: " + pc.iceConnectionState + "\n";
-  }
-  var div = getInfoDiv();
-  div.innerHTML = contents + "
"; - - for (var msg in infoDivErrors) { - div.innerHTML += '

' + - infoDivErrors[msg] + '

'; - } - if (infoDivErrors.length) - showInfoDiv(); -} - -function toggleInfoDiv() { - var div = getInfoDiv(); - if (div.style.display == "block") { - div.style.display = "none"; - } else { - showInfoDiv(); - } -} - -function showInfoDiv() { - var div = getInfoDiv(); - div.style.display = "block"; -} - -function toggleVideoMute() { - // Call the getVideoTracks method via adapter.js. - videoTracks = localStream.getVideoTracks(); - - if (videoTracks.length === 0) { - console.log('No local video available.'); - return; - } - - if (isVideoMuted) { - for (i = 0; i < videoTracks.length; i++) { - videoTracks[i].enabled = true; - } - console.log('Video unmuted.'); - } else { - for (i = 0; i < videoTracks.length; i++) { - videoTracks[i].enabled = false; - } - console.log('Video muted.'); - } - - isVideoMuted = !isVideoMuted; -} - -function toggleAudioMute() { - // Call the getAudioTracks method via adapter.js. - audioTracks = localStream.getAudioTracks(); - - if (audioTracks.length === 0) { - console.log('No local audio available.'); - return; - } - - if (isAudioMuted) { - for (i = 0; i < audioTracks.length; i++) { - audioTracks[i].enabled = true; - } - console.log('Audio unmuted.'); - } else { - for (i = 0; i < audioTracks.length; i++){ - audioTracks[i].enabled = false; - } - console.log('Audio muted.'); - } - - isAudioMuted = !isAudioMuted; -} - -// Mac: hotkey is Command. -// Non-Mac: hotkey is Control. -// -D: toggle audio mute. -// -E: toggle video mute. -// -I: toggle Info box. -// Return false to screen out original Chrome shortcuts. -document.onkeydown = function(event) { - var hotkey = event.ctrlKey; - if (navigator.appVersion.indexOf('Mac') != -1) - hotkey = event.metaKey; - if (!hotkey) - return; - switch (event.keyCode) { - case 68: - toggleAudioMute(); - return false; - case 69: - toggleVideoMute(); - return false; - case 73: - toggleInfoDiv(); - return false; - default: - return; - } -} - -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. - for (var i = 0; i < sdpLines.length; i++) { - if (sdpLines[i].search('m=audio') !== -1) { - var mLineIndex = i; - break; - } - } - if (mLineIndex === null) - return sdp; - - // 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(name + '/' + rate) !== -1) { - var regexp = new RegExp(':(\\d+) ' + name + '\\/' + rate, 'i'); - var payload = extractSdp(sdpLines[i], regexp); - if (payload) - sdpLines[mLineIndex] = setDefaultCodec(sdpLines[mLineIndex], - payload); - break; - } - } - - // Remove CN in m line and sdp. - sdpLines = removeCN(sdpLines, mLineIndex); - - sdp = sdpLines.join('\r\n'); - return sdp; -} - -// Set Opus in stereo if stereo is enabled. -function addStereo(sdp) { - var sdpLines = sdp.split('\r\n'); - - // Find opus payload. - for (var i = 0; i < sdpLines.length; i++) { - if (sdpLines[i].search('opus/48000') !== -1) { - var opusPayload = extractSdp(sdpLines[i], /:(\d+) opus\/48000/i); - break; - } - } - - // Find the payload in fmtp line. - for (var i = 0; i < sdpLines.length; i++) { - if (sdpLines[i].search('a=fmtp') !== -1) { - var payload = extractSdp(sdpLines[i], /a=fmtp:(\d+)/ ); - if (payload === opusPayload) { - var fmtpLineIndex = i; - break; - } - } - } - // No fmtp line found. - if (fmtpLineIndex === null) - return sdp; - - // Append stereo=1 to fmtp line. - sdpLines[fmtpLineIndex] = sdpLines[fmtpLineIndex].concat(' stereo=1'); - - sdp = sdpLines.join('\r\n'); - return sdp; -} - -function extractSdp(sdpLine, pattern) { - var result = sdpLine.match(pattern); - return (result && result.length == 2)? result[1]: null; -} - -// Set the selected codec to the first in m line. -function setDefaultCodec(mLine, payload) { - var elements = mLine.split(' '); - var newLine = new Array(); - var index = 0; - for (var i = 0; i < elements.length; i++) { - if (index === 3) // Format of media starts from the fourth. - newLine[index++] = payload; // Put target payload to the first. - if (elements[i] !== payload) - newLine[index++] = elements[i]; - } - return newLine.join(' '); -} - -// Strip CN from sdp before CN constraints is ready. -function removeCN(sdpLines, mLineIndex) { - var mLineElements = sdpLines[mLineIndex].split(' '); - // Scan from end for the convenience of removing an item. - for (var i = sdpLines.length-1; i >= 0; i--) { - var payload = extractSdp(sdpLines[i], /a=rtpmap:(\d+) CN\/\d+/i); - if (payload) { - var cnPos = mLineElements.indexOf(payload); - if (cnPos !== -1) { - // Remove CN payload from m line. - mLineElements.splice(cnPos, 1); - } - // Remove CN line in sdp - sdpLines.splice(i, 1); - } - } - - sdpLines[mLineIndex] = mLineElements.join(' '); - return sdpLines; -} - -// Send BYE on refreshing(or leaving) a demo page -// to ensure the room is cleaned for next session. -window.onbeforeunload = function() { - sendMessage({type: 'bye'}); -} - -// Set the video diplaying in the center of window. -window.onresize = function(){ - var aspectRatio; - if (remoteVideo.style.opacity === '1') { - aspectRatio = remoteVideo.videoWidth/remoteVideo.videoHeight; - } else if (localVideo.style.opacity === '1') { - aspectRatio = localVideo.videoWidth/localVideo.videoHeight; - } else { - return; - } - - var innerHeight = this.innerHeight; - var innerWidth = this.innerWidth; - var videoWidth = innerWidth < aspectRatio * window.innerHeight ? - innerWidth : aspectRatio * window.innerHeight; - var videoHeight = innerHeight < window.innerWidth / aspectRatio ? - innerHeight : window.innerWidth / aspectRatio; - containerDiv = document.getElementById('container'); - containerDiv.style.width = videoWidth + 'px'; - containerDiv.style.height = videoHeight + 'px'; - containerDiv.style.left = (innerWidth - videoWidth) / 2 + 'px'; - containerDiv.style.top = (innerHeight - videoHeight) / 2 + 'px'; -}; diff --git a/samples/js/apprtc/test/test_channel.html b/samples/js/apprtc/test/test_channel.html deleted file mode 100644 index 1668ce0df..000000000 --- a/samples/js/apprtc/test/test_channel.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - -

-
-
diff --git a/samples/js/apprtc/turn-prober/README b/samples/js/apprtc/turn-prober/README
deleted file mode 100644
index 58ba3398a..000000000
--- a/samples/js/apprtc/turn-prober/README
+++ /dev/null
@@ -1,9 +0,0 @@
-This script contains a simple prober that verifies that:
-- CEOD vends TURN server URIs with credentials on demand (mimicking apprtc)
-- rfc5766-turn-server vends TURN candidates from the servers vended by CEOD.
-
-To use simply run ./turn-prober.sh
-If it prints "PASS" (and exits 0) then all is well.
-If it prints a mess of logs (and exits non-0) then something has gone sideways
-and apprtc.appspot.com is probably not working well (b/c of missing TURN
-functionality).
diff --git a/samples/js/apprtc/turn-prober/turn-prober.html b/samples/js/apprtc/turn-prober/turn-prober.html
deleted file mode 100644
index 94cf68ecf..000000000
--- a/samples/js/apprtc/turn-prober/turn-prober.html
+++ /dev/null
@@ -1,132 +0,0 @@
-
-  
-    
-  
-  
-  
-
diff --git a/samples/js/apprtc/turn-prober/turn-prober.sh b/samples/js/apprtc/turn-prober/turn-prober.sh
deleted file mode 100755
index 2a063c58e..000000000
--- a/samples/js/apprtc/turn-prober/turn-prober.sh
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/bash -e
-
-function chrome_pids() {
-  ps axuwww|grep $D|grep c[h]rome|awk '{print $2}'
-}
-
-cd $(dirname $0)
-export D=$(mktemp -d)
-
-CHROME_LOG_FILE="${D}/chrome_debug.log"
-touch $CHROME_LOG_FILE
-
-XVFB="xvfb-run -a -e $CHROME_LOG_FILE -s '-screen 0 1024x768x24'"
-if [ -n "$DISPLAY" ]; then
-  XVFB=""
-fi
-
-# "eval" below is required by $XVFB containing a quoted argument.
-eval $XVFB chrome \
-  --enable-logging=stderr \
-  --no-first-run \
-  --disable-web-security \
-  --user-data-dir=$D \
-  --vmodule="*media/*=3,*turn*=3" \
-  "file://${PWD}/turn-prober.html" > $CHROME_LOG_FILE 2>&1 &
-CHROME_PID=$!
-
-while ! grep -q DONE $CHROME_LOG_FILE && chrome_pids|grep -q .; do
-  sleep 0.1
-done
-
-# Suppress bash's Killed message for the chrome above.
-exec 3>&2
-exec 2>/dev/null
-while [ ! -z "$(chrome_pids)" ]; do
-  kill -9 $(chrome_pids)
-done
-exec 2>&3
-exec 3>&-
-
-DONE=$(grep DONE $CHROME_LOG_FILE)
-EXIT_CODE=0
-if ! grep -q "DONE: PASS" $CHROME_LOG_FILE; then
-  cat $CHROME_LOG_FILE
-  EXIT_CODE=1
-fi
-
-rm -rf $D
-exit $EXIT_CODE
diff --git a/samples/js/base/adapter.js b/samples/js/base/adapter.js
deleted file mode 100644
index 3dd894784..000000000
--- a/samples/js/base/adapter.js
+++ /dev/null
@@ -1,198 +0,0 @@
-var RTCPeerConnection = null;
-var getUserMedia = null;
-var attachMediaStream = null;
-var reattachMediaStream = null;
-var webrtcDetectedBrowser = null;
-var webrtcDetectedVersion = null;
-
-function trace(text) {
-  // This function is used for logging.
-  if (text[text.length - 1] == '\n') {
-    text = text.substring(0, text.length - 1);
-  }
-  console.log((performance.now() / 1000).toFixed(3) + ": " + text);
-}
-function maybeFixConfiguration(pcConfig) {
-  if (pcConfig == null) {
-    return;
-  }
-  for (var i = 0; i < pcConfig.iceServers.length; i++) {
-    if (pcConfig.iceServers[i].hasOwnProperty('urls')){
-      pcConfig.iceServers[i]['url'] = pcConfig.iceServers[i]['urls'];
-      delete pcConfig.iceServers[i]['urls'];
-    }
-  }
-}
-
-if (navigator.mozGetUserMedia) {
-  console.log("This appears to be Firefox");
-
-  webrtcDetectedBrowser = "firefox";
-
-  webrtcDetectedVersion =
-           parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
-
-  // The RTCPeerConnection object.
-  var RTCPeerConnection = function(pcConfig, pcConstraints) {
-    // .urls is not supported in FF yet.
-    maybeFixConfiguration(pcConfig);
-    return new mozRTCPeerConnection(pcConfig, pcConstraints);
-  }
-
-  // The RTCSessionDescription object.
-  RTCSessionDescription = mozRTCSessionDescription;
-
-  // The RTCIceCandidate object.
-  RTCIceCandidate = mozRTCIceCandidate;
-
-  // Get UserMedia (only difference is the prefix).
-  // Code from Adam Barth.
-  getUserMedia = navigator.mozGetUserMedia.bind(navigator);
-  navigator.getUserMedia = getUserMedia;
-
-  // Creates iceServer from the url for FF.
-  createIceServer = function(url, username, password) {
-    var iceServer = null;
-    var url_parts = url.split(':');
-    if (url_parts[0].indexOf('stun') === 0) {
-      // Create iceServer with stun url.
-      iceServer = { 'url': url };
-    } else if (url_parts[0].indexOf('turn') === 0) {
-      if (webrtcDetectedVersion < 27) {
-        // Create iceServer with turn url.
-        // Ignore the transport parameter from TURN url for FF version <=27.
-        var turn_url_parts = url.split("?");
-        // Return null for createIceServer if transport=tcp.
-        if (turn_url_parts.length === 1 ||
-            turn_url_parts[1].indexOf('transport=udp') === 0) {
-          iceServer = {'url': turn_url_parts[0],
-                       'credential': password,
-                       'username': username};
-        }
-      } else {
-        // FF 27 and above supports transport parameters in TURN url,
-        // So passing in the full url to create iceServer.
-        iceServer = {'url': url,
-                     'credential': password,
-                     'username': username};
-      }
-    }
-    return iceServer;
-  };
-
-  createIceServers = function(urls, username, password) {
-    var iceServers = [];
-    // Use .url for FireFox.
-    for (i = 0; i < urls.length; i++) {
-      var iceServer = createIceServer(urls[i],
-                                      username,
-                                      password);
-      if (iceServer !== null) {
-        iceServers.push(iceServer);
-      }
-    }
-    return iceServers;
-  }
-
-  // Attach a media stream to an element.
-  attachMediaStream = function(element, stream) {
-    console.log("Attaching media stream");
-    element.mozSrcObject = stream;
-    element.play();
-  };
-
-  reattachMediaStream = function(to, from) {
-    console.log("Reattaching media stream");
-    to.mozSrcObject = from.mozSrcObject;
-    to.play();
-  };
-
-  // Fake get{Video,Audio}Tracks
-  if (!MediaStream.prototype.getVideoTracks) {
-    MediaStream.prototype.getVideoTracks = function() {
-      return [];
-    };
-  }
-
-  if (!MediaStream.prototype.getAudioTracks) {
-    MediaStream.prototype.getAudioTracks = function() {
-      return [];
-    };
-  }
-} else if (navigator.webkitGetUserMedia) {
-  console.log("This appears to be Chrome");
-
-  webrtcDetectedBrowser = "chrome";
-  webrtcDetectedVersion =
-         parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
-
-  // Creates iceServer from the url for Chrome M33 and earlier.
-  createIceServer = function(url, username, password) {
-    var iceServer = null;
-    var url_parts = url.split(':');
-    if (url_parts[0].indexOf('stun') === 0) {
-      // Create iceServer with stun url.
-      iceServer = { 'url': url };
-    } else if (url_parts[0].indexOf('turn') === 0) {
-      // Chrome M28 & above uses below TURN format.
-      iceServer = {'url': url,
-                   'credential': password,
-                   'username': username};
-    }
-    return iceServer;
-  };
-
-  // Creates iceServers from the urls for Chrome M34 and above.
-  createIceServers = function(urls, username, password) {
-    var iceServers = [];
-    if (webrtcDetectedVersion >= 34) {
-      // .urls is supported since Chrome M34.
-      iceServers = {'urls': urls,
-                    'credential': password,
-                    'username': username };
-    } else {
-      for (i = 0; i < urls.length; i++) {
-        var iceServer = createIceServer(urls[i],
-                                        username,
-                                        password);
-        if (iceServer !== null) {
-          iceServers.push(iceServer);
-        }
-      }
-    }
-    return iceServers;
-  };
-
-  // The RTCPeerConnection object.
-  var RTCPeerConnection = function(pcConfig, pcConstraints) {
-    // .urls is supported since Chrome M34.
-    if (webrtcDetectedVersion < 34) {
-      maybeFixConfiguration(pcConfig);
-    }
-    return new webkitRTCPeerConnection(pcConfig, pcConstraints);
-  }
-
-  // Get UserMedia (only difference is the prefix).
-  // Code from Adam Barth.
-  getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
-  navigator.getUserMedia = getUserMedia;
-
-  // Attach a media stream to an element.
-  attachMediaStream = function(element, stream) {
-    if (typeof element.srcObject !== 'undefined') {
-      element.srcObject = stream;
-    } else if (typeof element.mozSrcObject !== 'undefined') {
-      element.mozSrcObject = stream;
-    } else if (typeof element.src !== 'undefined') {
-      element.src = URL.createObjectURL(stream);
-    } else {
-      console.log('Error attaching stream to element.');
-    }
-  };
-
-  reattachMediaStream = function(to, from) {
-    to.src = from.src;
-  };
-} else {
-  console.log("Browser does not appear to be WebRTC-capable");
-}