Add audio and video parameters for setting media constraints.

- These replace the media parameter, now removed.
- Organize the parameter getting a bit.

To describe the new parameters, I'll just copy the code comments here:
Use "audio" and "video" to set the media stream constraints. "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 constraint defaults to True.

audio-specific parsing:
To set certain constraints, pass in a comma-separated list of audio
constraint strings. If preceded by a "-", the constraint will be set to
False, and otherwise to True. There is no validation of constraint
strings. Examples:
  "?audio=googEchoCancellation" (enables echo cancellation)
  "?audio=-googEchoCancellation,googAutoGainControl" (disables echo
      cancellation and enables gain control)

TESTED=Verified that passing true, false and various audio constraints
has the desired effect in apprtc.

R=vikasmarwaha@google.com

Review URL: https://webrtc-codereview.appspot.com/2345004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@4919 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
andrew@webrtc.org 2013-10-03 22:37:29 +00:00
parent 4446134757
commit bab2aa5113

View File

@ -118,34 +118,45 @@ def on_message(room, user, message):
new_message.put() new_message.put()
logging.info('Saved message for user ' + user) logging.info('Saved message for user ' + user)
def make_media_constraints(media, min_re, max_re): def make_media_constraints(audio, video, min_resolution, max_resolution):
video_constraints = { 'optional': [], 'mandatory': {} } if not audio or audio.lower() == 'true':
media_constraints = { 'video':video_constraints, 'audio':True } audio_constraints = True
elif audio.lower() == 'false':
audio_constraints = False
else:
audio_constraints = { 'mandatory': {}, 'optional': [] }
if audio:
for constraint in audio.split(','):
# TODO(ajm): We should probably be using the optional list here, but
# Chrome M31 won't override its default settings unless the constraints
# are mandatory. Chrome M32+, however, won't override optional settings.
if constraint.startswith('-'):
audio_constraints['mandatory'][constraint[1:]] = False
else:
audio_constraints['mandatory'][constraint] = True
# Media: audio:audio only; video:video only; (default):both. if not video or video.lower() == 'true':
if media.lower() == 'audio': video_constraints = True
media_constraints['video'] = False elif video.lower() == 'false':
elif media.lower() == 'video': video_constraints = False
media_constraints['audio'] = False else:
video_constraints = { 'mandatory': {}, 'optional': [] }
if media.lower() != 'audio' : if min_resolution:
if min_re: min_sizes = min_resolution.split('x')
min_sizes = min_re.split('x')
if len(min_sizes) == 2: if len(min_sizes) == 2:
video_constraints['mandatory']['minWidth'] = min_sizes[0] video_constraints['mandatory']['minWidth'] = min_sizes[0]
video_constraints['mandatory']['minHeight'] = min_sizes[1] video_constraints['mandatory']['minHeight'] = min_sizes[1]
else: else:
logging.info('Ignored invalid min_re: ' + min_re) logging.info('Ignored invalid minre: ' + min_resolution)
if max_re: if max_resolution:
max_sizes = max_re.split('x') max_sizes = max_resolution.split('x')
if len(max_sizes) == 2: if len(max_sizes) == 2:
video_constraints['mandatory']['maxWidth'] = max_sizes[0] video_constraints['mandatory']['maxWidth'] = max_sizes[0]
video_constraints['mandatory']['maxHeight'] = max_sizes[1] video_constraints['mandatory']['maxHeight'] = max_sizes[1]
else: else:
logging.info('Ignored invalid max_re: ' + max_re) logging.info('Ignored invalid maxre: ' + max_resolution)
media_constraints['video'] = video_constraints
return media_constraints return { 'audio': audio_constraints, 'video': video_constraints }
def make_pc_constraints(compat): def make_pc_constraints(compat):
constraints = { 'optional': [] } constraints = { 'optional': [] }
@ -305,41 +316,66 @@ class MainPage(webapp2.RequestHandler):
def get(self): def get(self):
"""Renders the main page. When this page is shown, we create a new """Renders the main page. When this page is shown, we create a new
channel to push asynchronous updates to the client.""" channel to push asynchronous updates to the client."""
# get the base url without arguments. # Get the base url without arguments.
base_url = self.request.path_url base_url = self.request.path_url
user_agent = self.request.headers['User-Agent'] user_agent = self.request.headers['User-Agent']
room_key = sanitize(self.request.get('r')) room_key = sanitize(self.request.get('r'))
debug = self.request.get('debug')
unittest = self.request.get('unittest')
stun_server = self.request.get('ss') stun_server = self.request.get('ss')
if not stun_server:
stun_server = get_default_stun_server(user_agent)
turn_server = self.request.get('ts') turn_server = self.request.get('ts')
min_re = self.request.get('minre')
max_re = self.request.get('maxre') ts_pwd = self.request.get('tp')
# Use "audio" and "video" to set the media stream constraints. "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 constraint defaults to True.
#
# audio-specific parsing:
# To set certain constraints, pass in a comma-separated list of audio
# constraint strings. If preceded by a "-", the constraint will be set to
# False, and otherwise to True. There is no validation of constraint
# strings. Examples:
# "?audio=googEchoCancellation" (enables echo cancellation)
# "?audio=-googEchoCancellation,googAutoGainControl" (disables echo
# cancellation and enables gain control)
# The strings are defined here:
# https://code.google.com/p/webrtc/source/browse/trunk/talk/app/webrtc/localaudiosource.cc
#
# TODO(ajm): There is currently no video functionality beyond True/False.
# Move the resolution settings here instead?
audio = self.request.get('audio')
video = self.request.get('video')
min_resolution = self.request.get('minre')
max_resolution = self.request.get('maxre')
hd_video = self.request.get('hd')
if hd_video.lower() == 'true':
min_resolution = '1280x720'
audio_send_codec = self.request.get('asc') audio_send_codec = self.request.get('asc')
if not audio_send_codec: if not audio_send_codec:
audio_send_codec = get_preferred_audio_send_codec(user_agent) audio_send_codec = get_preferred_audio_send_codec(user_agent)
audio_receive_codec = self.request.get('arc') audio_receive_codec = self.request.get('arc')
if not audio_receive_codec: if not audio_receive_codec:
audio_receive_codec = get_preferred_audio_receive_codec() audio_receive_codec = get_preferred_audio_receive_codec()
hd_video = self.request.get('hd')
turn_url = 'https://computeengineondemand.appspot.com/' # Set stereo to false by default.
if hd_video.lower() == 'true':
min_re = '1280x720'
ts_pwd = self.request.get('tp')
media = self.request.get('media')
# set compat to true by default.
compat = 'true'
if self.request.get('compat'):
compat = self.request.get('compat')
if debug == 'loopback':
# set compat to false as DTLS does not work for loopback.
compat = 'false'
# set stereo to false by default
stereo = 'false' stereo = 'false'
if self.request.get('stereo'): if self.request.get('stereo'):
stereo = self.request.get('stereo') stereo = self.request.get('stereo')
if not stun_server:
stun_server = get_default_stun_server(user_agent) # Set compat to true by default.
compat = 'true'
if self.request.get('compat'):
compat = self.request.get('compat')
debug = self.request.get('debug')
if debug == 'loopback':
# Set compat to false as DTLS does not work for loopback.
compat = 'false'
# token_timeout for channel creation, default 30min, max 2 days, min 3min. # token_timeout for channel creation, default 30min, max 2 days, min 3min.
token_timeout = self.request.get_range('tt', token_timeout = self.request.get_range('tt',
@ -347,6 +383,7 @@ class MainPage(webapp2.RequestHandler):
max_value = 3000, max_value = 3000,
default = 30) default = 30)
unittest = self.request.get('unittest')
if unittest: if unittest:
# Always create a new room for the unit tests. # Always create a new room for the unit tests.
room_key = generate_random(8) room_key = generate_random(8)
@ -387,12 +424,14 @@ class MainPage(webapp2.RequestHandler):
room_link = base_url + '?r=' + room_key room_link = base_url + '?r=' + room_key
room_link = append_url_arguments(self.request, room_link) room_link = append_url_arguments(self.request, room_link)
turn_url = 'https://computeengineondemand.appspot.com/'
turn_url = turn_url + 'turn?' + 'username=' + user + '&key=4080218913' turn_url = turn_url + 'turn?' + 'username=' + user + '&key=4080218913'
token = create_channel(room, user, token_timeout) token = create_channel(room, user, token_timeout)
pc_config = make_pc_config(stun_server, turn_server, ts_pwd) pc_config = make_pc_config(stun_server, turn_server, ts_pwd)
pc_constraints = make_pc_constraints(compat) pc_constraints = make_pc_constraints(compat)
offer_constraints = make_offer_constraints() offer_constraints = make_offer_constraints()
media_constraints = make_media_constraints(media, min_re, max_re) media_constraints = make_media_constraints(audio, video, min_resolution,
max_resolution)
template_values = {'token': token, template_values = {'token': token,
'me': user, 'me': user,
'room_key': room_key, 'room_key': room_key,