Abstract

This document is a temporary version that has deleted all sections except one. This allows the editors to get that section out to the working group and get comments on it before making the associated changes to the rest of the specification. Readers that need more context are advised to have a look at the previos version.

Status of This Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This document is not complete. It is subject to major changes and, while early experimentations are encouraged, it is therefore not intended for implementation. The API is based on preliminary work done in the WHATWG.

This document was published by the Web Real-Time Communication Working Group and Device APIs Working Group as an Editor's Draft. If you wish to make comments regarding this document, please send them to public-media-capture@w3.org (subscribe, archives). All comments are welcome.

Publication as an Editor's Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures (Web Real-Time Communication Working Group, Device APIs Working Group) made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

11. Constrainable Interface

The Constrainable interface allows its consumers to inspect and adjust the properties of the object that implements it. It is broken out as a separate interface so that it can be used in other specifications. The core concept is that of a Capability, which consists of a property or feature of an object and the set of its possible values, which may be specified either as a range or as an enumeration. For example, a camera might be capable of framerates (a property) between 20 and 50 frames per second (a range) and may be able to be positioned (a property) facing towards the user, away from the user, or to the left or right of the user (an enumerated set.) The application can examine a Constrainable object's set of Capabilities via the getCapabilities() accessor.

The application can select the (range of) values it wants for an object's Capabilities by means of one or more ConstraintSets and the applyConstraints() method. A ConstraintSet consists of the names of one or more properties of the object plus the desired value (or a range of desired values) for each of them. Each of those property/value pairs can be considered to be an individual constraint. For example, the application may set a ConstraintSet containing two constraints, the first stating that the framerate of a camera be between 30 and 40 frames per second (a range) and the second that the camera should be facing the user (a specific value). ConstraintSets can be mandatory or optional. In the case of optional ConstraintSets, the UA will consider the ConstraintSets in the order in which they are specified, and will try to satisfy each one, but will ignore a ConstraintSet if it cannot satisfy it. In the case of a mandatory ConstraintSet, the UA will try to satisfy it, and will call the errorCallback if it cannot do so. For example, suppose that an application applies three individual constraints, one stating that the video aspect ratio should be 3 to 2 (height to width), the next that the height should be 600 and the last that the width should be 500. Since these constraints interact with each other (the aspect ratio affects the possible values for height and width, and vice-versa) it is impossible to satisfy all three of them, so if they are all contained in a mandatory ConstraintSet, the UA will call the errorCallback. However if any one of the constraints is placed in an optional ConstraintSet, the other two can be satisfied, so the UA will satisfy the two mandatory ones, silently ignore the optional one, and call the successCallback.

The ordering of optional ConstraintSets is significant. In the example in the previous paragraph, suppose that aspect ratio constraint is part of a mandatory ConstraintSet and that the height and width constraints are part of separate optional ConstraintSets. If the height ConstraintSet is specified first (and the other constraints in the ConstraintSet can also be satisfied), then it will be satisfied and the width ConstraintSet will be ignored. Thus the height will be set to 600 and the the width will be set to 400. On the other hand, if width is specified before height, the width ConstraintSet will be satisfied and the height ConstraintSet will be ignored, resulting in width of 500 and height of 750. (Note that the mandatory aspect ratio constraint is enforced in both cases.) The UA will attempt to satisfy as many optional ConstraintSets as it can, even if some of them cannot be satisfied and must therefore be ignored. Application authors can therefore implement a backoff strategy by specifying multiple optional ConstraintSets for the same property. For example, an application might specify three optional ConstraintSets, the first asking for a framerate greater than 500, the second asking for a framerate greater than 400, and the third asking for one greater than 300. If the UA is capable of setting a framerate greater than 500, it will (and the subsequent two ConstraintSets will be trivially satisfied.) However, if the UA cannot set the framerate above 500, it will ignore that ConstraintSet and attempt to set the framerate above 400. If that fails, it will then try to set it above 300. If the UA cannot satisfy any of the three ConstraintSets, it will set the framerate to any value it can get. If the developer wanted to insist on 300 as a lower bound, he put that in a mandatory ConstraintSet. In that case, the UA would fail altogether if it couldn't get a value over 300, but would choose a value over 500 if possible, then try for a value over 400. An application may inspect the set of ConstraintSets currently in effect via the getConstraints() accessor.

The specific value that the UA chooses for a Capability is referred to as a Setting. For example, if the application applies a ConstraintSet specifying that the framerate must be at least 30 frames per second, and no greater than 40, the Setting can be any intermediate value, e.g., 32, 35, or 37 frames per second. The application can query the current settings of the object's Capabilities via the getSettings() accessor.

11.1 Interface Definition

[NoInterfaceObject]
interface Constrainable {
    Capabilities getCapabilities ();
    Constraints  getConstraints ();
    Settings     getSettings ();
    void         applyConstraints (Constraints constraints, VoidFunction successCallback, ConstraintErrorCallback errorCallback);
                attribute EventHandler onoverconstrained;
};

11.1.1 Attributes

onoverconstrained of type EventHandler,
This event handler, of type overconstrained, must be supported by all objects implementing the Constrainable interface.

The UA must raise a MediaErrorEvent named "overconstrained" if changing circumstances at runtime result in the currently valid mandatory ConstraintSet no longer being satisfied. This MediaErrorEvent must contain a MediaError whose name is "overconstrainedError", and whose constraintName attribute is set to one of the mandatory constraints that can no longer be satisfied. The message attribute of the MediaError SHOULD contain a string that is useful for debugging. The conditions under which this error might occur are platform and application-specific. For example, the user might physically manipulate a camera in a way that makes it impossible to provide a resolution that satisfies the constraints. The UA MAY take other actions as a result of the overconstrained situation.

11.1.2 Methods

applyConstraints

The applyConstraints() algorithm for applying constraints is stated below. Here are some preliminary definitions that are used in the statement of the algorithm:

  • We refer to each property/value pair in a ConstraintSet as a 'constraint' (since it is intended to constrain the corresponding Capability of the Constrainable object to a value that is within the range or list of values it specifies.)
  • A set of values for the properties of an object O satisfy ConstraintSet C if each value a) is in the set of supported values specified by the corresponding Capability of O, and b) is in the range or list of values specified by the constraint in C that applies to that property, if there is one, and c) there is no constraint in C that does not correspond to a Capability in O. (Note that although this definition ignores the difference between mandatory and optional ConstraintSets, the algorithm below distinguishes between them.)
  • A ConstraintSet C can be satisfied by an object O if it is possible to choose a sequence of values for the properties of O that satisfy C.
  • To apply a set of ConstraintSet C to object O is to choose such a sequence of values that satisfy C and assign them as the settings for the properties of O.

When applyConstraints is called, the UA must queue a task to run the following steps:

  1. let desiredContraints be the argument to this function. Each constraint must specify one or more values (or a range of values) for its property. A property may appear more than once in the list of optional ConstraintSets.
  2. Let newConstraints be an initially empty Constraints dictionary. Let existingConstraints be the Constraints currently in effect (i.e. what is returned by getConstraints.)
  3. Let object be the Constrainable object on which this method was called. Let copy be an unconstrained copy of object (i.e., copy should behave as if it were object with all ConstraintSets removed.)
  4. If the mandatory ConstraintSet in desiredConstraints is non-null and cannot be satisfied by copy, call the errorCallback, passing it a new MediaError with name ConstraintNotSatisfied and constraintName set to any of the mandatory constraints that could not be satisfied, and return. existingConstraints remain in effect in this case.
  5. Otherwise if the mandatory ConstraintSet is non-null, set it as the value of the 'mandatory' element in newConstraints
  6. Iterate over the optional ConstraintSets in desiredConstraints in the order in which they were specified. For each ConstraintSet,if it and newConstraints together can be satisfied by copy, append it to the value of the 'optional' element in newConstraints. Otherwise, ignore it.
  7. In a single operation, remove existingConstraints from object, apply newConstraints, and fire the successCallback. From this point on until applyConstraints() is called successfully again, getConstraints() must return newConstraints. Note: the UA MAY modify the values of one or more properties of object at any time, as long as the resulting set of values satisfy the current set of constraints.
ParameterTypeNullableOptionalDescription
constraintsConstraintsA new constraint structure to apply to this object.
successCallbackVoidFunctionCalled if the mandatory ConstraintSet can be satisfied.
errorCallbackConstraintErrorCallbackCalled if the mandatory ConstraintSet cannot be satisfied.
Return type: void
getCapabilities

The getCapabilities() method returns the dictionary of the capabilities that the object supports.

Note

It is possible that the underlying hardware may not exactly map to the range defined in the registry entry. Where this is possible, the entry should define how to translate and scale the hardware's setting onto the values defined in the entry. For example, suppose that a registry entry defines a hypothetical fluxCapacitance capability that is defined to be the range from -10 (min) to 10 (max), but there are common hardware devices that support only values of "off" "medium" and "full". The registry entry might specify that for such hardware, the user agent should map the range value of -10 to "off", 10 to "full", and 0 to "medium". It might also indicate that given a ConstraintSet imposing a strict value of 3, the user agent should attempt to set the value of "medium" on the hardware, and and that getSettings() should return a fluxCapacitance of 0, since that is the value defined as corresponding to "medium".

No parameters.
Return type: Capabilities
getConstraints

The getConstraints() method returns all the ConstraintSets that were applied to the object in the last successful call of applyConstraints(). The value must contain only the ConstraintSets that were successfully applied, and it must maintain the order that they were specified in.

If no mandatory ConstraintSet has been defined, the mandatory field will not be present (it will be undefined). If no optional ConstraintSets have been defined, the optional field will not be present (it will be undefined). If neither optional nor mandatory ConstraintSets have been created, the value will be null.

No parameters.
Return type: Constraints
getSettings
The getSettings() method returns the current settings of all the properties of the object, whether they are platform defaults or have been set by applyConstraints(). Note that the actual setting of a property must be a single value.
No parameters.
Return type: Settings

11.1.3 applyConstraints Failure Callback

ConstraintErrorCallback
callback ConstraintErrorCallback = void (MediaError error);
Callback ConstraintErrorCallback Parameters
error of type MediaError
An MediaError holding the mandatory constraint that could not be satisfied.

An example of Constraints that could be passed into applyConstraints() or returned as a value of constraints is below. It uses the properties defined in the Track property registry.

Example 5
{
  "mandatory": {
    "width": {
      "min": 640
    },
    "height": {
      "min": 480
    }
  },
  "optional": [{
    "width": 650
  }, {
    "width": {
      "min": 650
    }
  }, {
    "frameRate": 60
  }, {
    "width": {
      "max": 800
    }
  }, {
    "facingMode": "user"
  }]
}                             

11.2 The Property Registry

For each class/interface that implements Constrainable, there must be a corresponding registry that defines the constrainable properties of that class of object. The registry entries must contain the name of each property along with its set of legal values. The registry for MediaStreamTrack is defined below. The syntax for the specification of the set of legal values depends on the type of the values. In addition to the standard atomic types (boolean, long, float, DOMString), legal values include lists of any of the atomic types, plus min-max ranges, as defined below.

List values must be interpreted as disjunctions. For example, if a property 'facingMode' for a camera is defined as having legal values ["left", "right", "user", "environment"], this means that 'facingMode' can have the value "left", the value "right", the value "environment" or the value "user". Similarly Constraints restricting 'facingMode' to ["user", "left", "right"] would mean that the UA should select a camera (or point the camera, if that is possible) so that "facingMode" is either "user", "left", or "right". This Constraint would thus request that the camera not be facing away from the user, but would allow the UA to choose among the other directions.

11.2.1 PropertyValueSet

typedef PropertyValueSet DOMString[];

11.2.2 PropertyValueDoubleRange

dictionary PropertyValueDoubleRange {
    double max;
    double min;
};
11.2.2.1 Dictionary PropertyValueDoubleRange Members
max of type double
The maximum legal value of this property.
min of type double
The minimum value of this Property.

11.2.3 PropertyValueLongRange

dictionary PropertyValueLongRange {
    long max;
    long min;
};
11.2.3.1 Dictionary PropertyValueLongRange Members
max of type long
The maximum legal value of this property.
min of type long
The minimum value of this Property.

11.3 Capabilities

Capabilities are dictionary containing one or more key-value pairs, where each key must be a constrainable property defined in the associated registry, and each value must be a subset of the set of values defined for that property in the registry. The exact syntax of the value expression depends on the type of the property but is of type ConstraintValues. The Capabilities dictionary specifies the subset of the constrainable properties and values from the registry that the UA supports. Note that a UA may support only a subset of the properties that are defined in the registry, and may support a subset of the set values for those properties that it does support. Note that Capabilities are returned from the UA to the application, and cannot be specified by the application. However, the application can control the Settings that the UA chooses for Capabilities by means of ConstraintSets.

An example of a Capabilities dictionary is shown below. This example is not very realistic in that a browser would actually be required to support more settings that just these.

Example 6
{
  "frameRate": {
    "min": 1.0,
    "max": 60.0
  },
  "facingMode": ["user", "environment"]
}                         

11.4 Settings

A Setting is a dictionary containing one or more key-value pairs. It must contain each key returned in getCapabilities(). There must be a single value for each key and the value must a member of the set defined for that property by capabilities(). The exact syntax of the value expression depends on the type of the property. It will be a DomString for properties of type PropertyValueSet, it will be a long for properties of type PropertyValueLongRange , it will be a double for properties of type PropertyValueDoubleRange. Thus the Settings dictionary contains the actual values that the UA has chosen for the object's Capabilities.

An example of a Setting dictionary is shown below. This example is not very realistic in that a browser would actually be required to support more settings that just these.

Example 7
{
  "frameRate": 30.0,
  "facingMode": "user"
}

11.5 Constraints

dictionary Constraints {
    ConstraintSet?  mandatory;
    ConstraintSet[] optional;
};

11.5.1 Dictionary Constraints Members

mandatory of type ConstraintSet, nullable

The set of constraints that the UA must satisfy or else call the errorCallback.

optional of type array of ConstraintSet

The set of ConstraintSets that the UA should try to satisfy but may ignore if they cannot be satisfied. The order of these ConstraintSets is significant. In particular, when they are passed as an argument to applyConstraints, the UA must try to satisfy them in the order that is specified. Thus if optional ConstraintSets C1 and C2 can be satisfied individually, but not together, then whichever of C1 and C2 is first in this list will be satisfied, and the other will not. The UA must attempt to satisfy all optional ConstraintSets in the list, even if some cannot be satisfied. Thus, in the preceding example, if optional constraint C3 is specified after C1 and C2, the UA will attempt to satisfy C3 even though C2 cannot be satisfied. Note that a given property name may occur multiple times in these sets.

Each property of a ConstraintSet corresponds to a Capability and specifies a subset of its legal values. Applying a ConstraintSet instructs that UA to restrict the setting of the corresponding Capabilities to the specified values or ranges of values. A given property MAY occur both in the mandatory and the optional ConstraintSets list, and MAY occur more than once in the optional ConstraintSets list.

11.5.2 ConstraintSet

Note
Open Issue: Do we need to add support for a boolean type in constraints? Is the ConstraintValue below an OK addition which will allow constraints like { width: 66 } as a short hand for min=max=66.
typedef (DOMString or long or double or boolean) ConstraintValue;
typedef (ConstraintValue or PropertyValueSet or PropertyValueLongRange or PropertyValueDoubleRange) ConstraintValues;
[NoInterfaceObject]
interface ConstraintSet {
    ConstraintValues getter (DOMString name);
};
11.5.2.1 Methods
getter
The property represents the name of the constraint, which correspond to a Capability of the Constrainable object. The value of the property represents the desired range of values for the Capability.
ParameterTypeNullableOptionalDescription
nameDOMString
Return type: ConstraintValues

In ECMAScript, ConstraintSet objects are represented using regular native objects with optional properties whose names represent constraint name. The conversion from an ECMAScript value, representing a ConstraintSet, to an IDL ConstraintSet must not fail if a property name in the ECMAScript value does not match any of the Capabilities of the Constrainable object.

In ECMAScript, all the properties of the ConstraintSet object are optional; the developer may specify any of these properties when creating the object. Note, however, that unknown property names will result in a ConstraintSet that can not be satisfied, as described in applyConstraints() above.

B. References

B.1 Normative references

[HTML5]
Robin Berjon; Steve Faulkner; Travis Leithead; Erika Doyle Navara; Edward O'Connor; Silvia Pfeiffer. HTML5. 6 August 2013. W3C Candidate Recommendation. URL: http://www.w3.org/TR/html5/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Internet RFC 2119. URL: http://www.ietf.org/rfc/rfc2119.txt
[RTCWEB-CONSTRAINTS]
Dan Burnett. IANA Registry for RTCWeb Constrainable Properties. 21 October 2013. Active Internet-Draft. URL: http://datatracker.ietf.org/doc/draft-burnett-rtcweb-constraints-registry/
[WEBIDL]
Cameron McCormack. Web IDL. 19 April 2012. W3C Candidate Recommendation. URL: http://www.w3.org/TR/WebIDL/
[WEBRTC10]
Adam Bergkvist; Daniel Burnett; Cullen Jennings; Anant Narayanan. WebRTC 1.0: Real-time Communication Between Browsers. 10 September 2013. W3C Working Draft. URL: http://www.w3.org/TR/webrtc/

B.2 Informative references

[mediastream-imagecap]
Giridhar Mandyam. MediaStream Image Capture. W3C Working Draft. URL: http://www.w3.org/TR/image-capture/
[mediastream-rec]
Jim Barnett; Travis Leithead. MediaStream Recording. W3C Working Draft. URL: https://dvcs.w3.org/hg/dap/raw-file/tip/media-stream-capture/MediaRecorder.html