diff --git a/index.src.html b/index.src.html
index 09002c20..7481d65d 100644
--- a/index.src.html
+++ b/index.src.html
@@ -2644,8 +2644,7 @@
[Exposed=(Window,DedicatedWorker), Serializable, Transferable]
interface VideoFrame {
constructor(CanvasImageSource image, optional VideoFrameInit init = {});
- constructor(sequence planes,
- VideoFramePlaneInit init);
+ constructor([AllowShared] BufferSource data, VideoFrameBufferInit init);
readonly attribute PixelFormat format;
readonly attribute unsigned long codedWidth;
@@ -2670,21 +2669,22 @@
long long timestamp; // microseconds
};
-dictionary VideoFramePlaneInit {
+dictionary VideoFrameBufferInit {
required PixelFormat format;
- [EnforceRange] required unsigned long codedWidth;
- [EnforceRange] required unsigned long codedHeight;
+ required [EnforceRange] unsigned long codedWidth;
+ required [EnforceRange] unsigned long codedHeight;
+ required [EnforceRange] long long timestamp; // microseconds
+ [EnforceRange] unsigned long long duration; // microseconds
+
+ // Default layout is tightly-packed.
+ sequence layout;
+
+ // Default visible rect is coded size positioned at (0,0)
DOMRectInit visibleRect;
+
+ // Default display dimensions match visibleRect.
[EnforceRange] unsigned long displayWidth;
[EnforceRange] unsigned long displayHeight;
- [EnforceRange] unsigned long long duration; // microseconds
- [EnforceRange] long long timestamp; // microseconds
-};
-
-dictionary PlaneInit {
- required BufferSource data;
- [EnforceRange] required unsigned long stride;
- [EnforceRange] unsigned long offset = 0;
};
@@ -2798,95 +2798,84 @@
6. Return |frame|.
-
- VideoFrame(planes, init)
+
+ VideoFrame(data, init)
-1. If |init| is not a [=valid VideoFramePlaneInit=], throw a
- {{TypeError}}.
-2. If |planes| is incompatible with the given {{VideoFramePlaneInit/format}}
- (e.g. wrong number of planes), throw a {{TypeError}}.
-
- ISSUE: The spec should list additional format specific validation steps (
- e.g. number and order of planes, acceptable sizing, etc...). See
- [#165](https://github.com/w3c/webcodecs/issues/165).
-
-3. Let |resource| be a new [=media resource=] allocated in accordance with
- |init|.
-
- ISSUE: The spec should define explicit rules for each
- {{PixelFormat}} and reference them in the steps above. See
- [#165](https://github.com/w3c/webcodecs/issues/165).
+1. If |init| is not a [=valid VideoFrameBufferInit=], throw a {{TypeError}}.
+2. Let |defaultRect| be «[ "x:" → `0`, "y" → `0`,
+ "width" → |init|.{{VideoFrameBufferInit/codedWidth}}, "height" →
+ |init|.{{VideoFrameBufferInit/codedWidth}} ]».
+3. Let |overrideRect| be `undefined`.
+4. If |init|.{{VideoFrameBufferInit/visibleRect}} [=map/exists=], assign its
+ value to overrideRect.
+4. Let |parsedRect| be the result of running the [=VideoFrame/Parse Visible
+ Rect=] algorithm with |defaultRect|, |overrideRect|,
+ |init|.{{VideoFrameBufferInit/codedWidth}},
+ |init|.{{VideoFrameBufferInit/codedHeight}},
+ |init|.{{VideoFrameBufferInit/format}}.
+5. If |parsedRect| is an exception, return |parsedRect|.
+6. Let |optLayout| be `undefined`.
+7. If |options|.{{VideoFrameBufferInit/layout}} [=map/exists=], assign its value
+ to |optLayout|.
+8. Let |combinedLayout| be the result of running the [=VideoFrame/Compute
+ Layout and Allocation Size=] algorithm with |parsedRect|,
+ |init|.{{VideoFrameBufferInit/format}}, and |optLayout|.
+9. If |combinedLayout| is an excpetion, throw |combinedLayout|.
+10. If `data.byteLength` is less than |combinedLayout|’s
+ [=combined buffer layout/allocationSize=], throw a {{TypeError}}.
+11. Let |resource| be a new [=media resource=] containing a copy |data|. Use
+ {{VideoFrameBufferInit/visibleRect}} and {{VideoFrameBufferInit/layout}}
+ to determine where in |data| the pixels for each plane reside.
NOTE: The User Agent may choose to allocate resource with a larger coded
- size and plane strides to improve memory alignment. Increases will be
- reflected by {{VideoFrame/codedWidth}} and {{VideoFrame/codedHeight}}.
-
-4. Let |resourceReference| be a reference to |resource|.
-5. Let |frame| be a new {{VideoFrame}} object initialized as follows:
- 1. Assign |resourceReference| to
- {{VideoFrame/[[resource reference]]}}.
- 2. Assign {{VideoFramePlaneInit/format}} to {{VideoFrame/[[format]]}}.
- 3. For each |planeInit| in |planes|:
- 1. Let |rows| be the number of sample rows for the Plane coresponding
- to |planeInit| as defined by {{VideoFrame/[[format]]}}.
- 2. Let |dataOffset| be `0`.
- 3. If {{PlaneInit/offset}} [=map/exists=], assign {{PlaneInit/offset}}
- to |dataOffset|.
- 4. Let |row| be `0`.
- 5. While |row| is less than |rows|:
- 1. Copy bytes from {{PlaneInit/data}} to |resource|, starting with
- the byte positioned at |dataOffset| and stopping after
- {{PlaneInit/stride}} bytes have been copied.
-
- NOTE: The User Agent may use {{VideoFramePlaneInit/visibleRect}}
- to copy only the visible rectangle. It may also reposition
- the visible rectangle within |resource|. The final position
- will be reflected by {{VideoFrame/visibleRect}}.
-
- 2. Increment |dataOffset| by {{PlaneInit/stride}}.
- 3. Increment |row| by `1`.
-
- 4. Let |resourceCodedWidth| be the coded width of |resource|.
- 5. Let |resourceCodedHeight| be the coded height of |resource|.
- 6. Let |resourceVisibleLeft| be the left offset for the visible rectangle of
- |resource|.
- 7. Let |resourceVisibleTop| be the top offset for the visible rectangle of
- |resource|.
-
- ISSUE: The spec should provide definitions (and possibly diagrams) for
- coded size, visible rectangle, and display size. See
- [#166](https://github.com/w3c/webcodecs/issues/166).
-
- 8. Assign |resourceCodedWidth|, |resourceCodedHeight|,
+ size and plane strides to improve memory alignment. Increases will be
+ reflected by {{VideoFrame/codedWidth}} and {{VideoFrame/codedHeight}}.
+ Additionally, the User Agent may use
+ {{VideoFrameBufferInit/visibleRect}} to copy only the visible rectangle.
+ It may also reposition the visible rectangle within |resource|. The
+ final position will be reflected by {{VideoFrame/visibleRect}}.
+
+12. Let |resourceCodedWidth| be the coded width of |resource|.
+13. Let |resourceCodedHeight| be the coded height of |resource|.
+14. Let |resourceVisibleLeft| be the left offset for the visible rectangle of
+ |resource|.
+15. Let |resourceVisibleTop| be the top offset for the visible rectangle of
+ |resource|.
+
+ ISSUE: The spec should provide definitions (and possibly diagrams) for
+ coded size, visible rectangle, and display size. See
+ [#166](https://github.com/w3c/webcodecs/issues/166).
+
+16. Let |frame| be a new {{VideoFrame}} object initialized as follows:
+ 1. Assign |resourceCodedWidth|, |resourceCodedHeight|,
|resourceVisibleLeft|, and |resourceVisibleTop| to
{{VideoFrame/[[coded width]]}}, {{VideoFrame/[[coded height]]}},
{{VideoFrame/[[visible left]]}}, and {{VideoFrame/[[visible top]]}}
respectively.
-
- 10. If |init|.{{VideoFramePlaneInit/visibleRect}} [=map/exists=]:
+ 2. If |init|.{{VideoFrameBufferInit/visibleRect}} [=map/exists=]:
1. Let |truncatedVisibleWidth| be the value of
- {{VideoFramePlaneInit/visibleRect}}.{{DOMRectInit/width}} after
+ {{VideoFrameBufferInit/visibleRect}}.{{DOMRectInit/width}} after
truncating.
1. Assign |truncatedVisibleWidth| to {{VideoFrame/[[visible width]]}}.
3. Let |truncatedVisibleHeight| be the value of
- {{VideoFramePlaneInit/visibleRect}}.{{DOMRectInit/height}} after
+ {{VideoFrameBufferInit/visibleRect}}.{{DOMRectInit/height}} after
truncating.
2. Assign |truncatedVisibleHeight| to {{VideoFrame/[[visible height]]}}.
- 11. Otherwise:
+ 3. Otherwise:
1. Assign {{VideoFrame/[[coded width]]}} to
{{VideoFrame/[[visible width]]}}.
2. Assign {{VideoFrame/[[coded height]]}} to
{{VideoFrame/[[visible height]]}}.
- 12. If |init|.{{VideoFramePlaneInit/displayWidth}} [=map/exists=], assign
+ 4. If |init|.{{VideoFrameBufferInit/displayWidth}} [=map/exists=], assign
it to {{VideoFrame/[[display width]]}}. Otherwise, assign
{{VideoFrame/[[visible width]]}} to {{VideoFrame/[[display width]]}}.
- 13. If |init|.{{VideoFramePlaneInit/displayHeight}} [=map/exists=], assign
+ 5. If |init|.{{VideoFrameBufferInit/displayHeight}} [=map/exists=], assign
it to {{VideoFrame/[[display height]]}}. Otherwise, assign
{{VideoFrame/[[visible height]]}} to {{VideoFrame/[[display height]]}}.
- 14. Assign |init|'s {{VideoFramePlaneInit/timestamp}} and
- {{VideoFramePlaneInit/duration}} to {{VideoFrame/[[timestamp]]}} and
+ 6. Assign |init|'s {{VideoFrameBufferInit/timestamp}} and
+ {{VideoFrameBufferInit/duration}} to {{VideoFrame/[[timestamp]]}} and
{{VideoFrame/[[duration]]}} respectively.
-6. Return |frame|.
+17. Return |frame|.
### Attributes ###{#videoframe-attributes}
: format
@@ -2969,10 +2958,10 @@
{{VideoFrame/[[duration]]}}.
### Internal Structures ###{#videoframe-internal-structures}
-A parsed copyto options is a [=struct=] that consists of:
- * A allocationSize (an {{unsigned
+A combined buffer layout is a [=struct=] that consists of:
+ * A allocationSize (an {{unsigned
long}})
- * A computedLayouts (a [=list=] of
+ * A computedLayouts (a [=list=] of
[=computed plane layout=] structs).
A computed plane layout is a [=struct=] that consists of:
@@ -2996,10 +2985,10 @@
1. If {{platform object/[[Detached]]}} is `true`, return `0`.
2. If {{VideoFrame/[[format]]}} is `""`, throw a {{NotSupportedError}}
{{DOMException}}.
- 3. Let |parsedOptions| be the result of running the [=Parse
+ 3. Let |combinedLayout| be the result of running the [=Parse
VideoFrameCopyToOptions=] algorithm with |options|.
- 4. If |parsedOptions| is an excpetion, throw |parsedOptions|.
- 5. Return |parsedOptions|' [=parsed copyto options/allocationSize=]
+ 4. If |combinedLayout| is an excpetion, throw |combinedLayout|.
+ 5. Return |combinedLayout|'s [=combined buffer layout/allocationSize=].
: copyTo(|destination|, |options|)
:: Asynchronously copies the planes of this frame into |destination| according
@@ -3014,12 +3003,12 @@
1. If {{platform object/[[Detached]]}} is `true`, return `0`.
2. If {{VideoFrame/[[format]]}} is `""`, throw a {{NotSupportedError}}
{{DOMException}}.
- 3. Let |parsedOptions| be the result of running the [=Parse
+ 3. Let |combinedLayout| be the result of running the [=Parse
VideoFrameCopyToOptions=] algorithm with |options|.
- 4. If |parsedOptions| is an exception, return a promise rejected with
- |parsedOptions|.
- 5. If `destionation.byteLength` is less than |parsedOptions|' [=parsed
- copyto options/allocationSize=], return a promise rejected with a
+ 4. If |combinedLayout| is an exception, return a promise rejected with
+ |combinedLayout|.
+ 5. If `destionation.byteLength` is less than |combinedLayout|'s [=combined
+ buffer layout/allocationSize=], return a promise rejected with a
{{TypeError}}.
6. Let |p| be a new {{Promise}}.
7. Let |copyStepsQueue| be the result of starting a new [=parallel queue=].
@@ -3029,17 +3018,17 @@
2. Let |numPlanes| be the number of planes as defined by
{{VideoFrame/[[format]]}}.
3. Let |planeIndex| be `0`.
- 4. While |planeIndex| is less than |parsedOptions|' |numPlanes|:
+ 4. While |planeIndex| is less than |combinedLayout|'s |numPlanes|:
1. Let |sourceStride| be the stride of the plane in |resource| as
identified by |planeIndex|.
2. Let |computedLayout| be the [=computed plane layout=] in
- |parsedOptions|' [=parsed copyto options/computedLayouts=] at the
- position of |planeIndex|
+ |combinedLayout|'s [=combined buffer layout/computedLayouts=] at
+ the position of |planeIndex|
3. Let |sourceOffset| be the product of multiplying
|computedLayout|'s [=computed plane layout/sourceTop=] by
|sourceStride|
- 4. Add |computedLayout|'s [=computed plane layout/sourceLeftBytes=] to
- sourceOffset.
+ 4. Add |computedLayout|'s [=computed plane layout/sourceLeftBytes=]
+ to sourceOffset.
5. Let |destinationOffset| be |computedLayout|'s
[=computed plane layout/destinationOffset=].
6. Let |rowBytes| be |computedLayout|'s
@@ -3104,22 +3093,24 @@
{{VideoFrame/[[timestamp]]}} respectively.
2. Return |frame|.
-: To check if a {{VideoFramePlaneInit}} is a
- valid VideoFramePlaneInit, run these steps:
-:: 1. If {{VideoFramePlaneInit/codedWidth}} = 0 or
- {{VideoFramePlaneInit/codedHeight}} = 0,return `false`.
- 2. If {{VideoFramePlaneInit/visibleRect}}.{{DOMRectInit/width}} = 0
- or {{VideoFramePlaneInit/visibleRect}}.{{DOMRectInit/height}} =
+: To check if a {{VideoFrameBufferInit}} is a
+ valid VideoFrameBufferInit, run these steps:
+:: 1. If {{VideoFrameBufferInit/codedWidth}} = 0 or
+ {{VideoFrameBufferInit/codedHeight}} = 0,return `false`.
+ 2. If {{VideoFrameBufferInit/visibleRect}}.{{DOMRectInit/width}} = 0
+ or {{VideoFrameBufferInit/visibleRect}}.{{DOMRectInit/height}} =
0, return `false`.
- 3. If {{VideoFramePlaneInit/visibleRect}}.{{DOMRectInit/y}} +
- {{VideoFramePlaneInit/visibleRect}}.{{DOMRectInit/height}} >=
- {{VideoFramePlaneInit/codedHeight}}, return `false`.
- 4. If {{VideoFramePlaneInit/visibleRect}}.{{DOMRectInit/x}} +
- {{VideoFramePlaneInit/visibleRect}}.{{DOMRectInit/width}} >=
- {{VideoFramePlaneInit/codedWidth}}, return `false`.
- 5. If {{VideoFramePlaneInit/displayWidth}} = 0 or
- {{VideoFramePlaneInit/displayHeight}} = 0, return `false`.
- 6. Return `true`.
+ 3. If {{VideoFrameBufferInit/visibleRect}}.{{DOMRectInit/y}} +
+ {{VideoFrameBufferInit/visibleRect}}.{{DOMRectInit/height}} >=
+ {{VideoFrameBufferInit/codedHeight}}, return `false`.
+ 4. If {{VideoFrameBufferInit/visibleRect}}.{{DOMRectInit/x}} +
+ {{VideoFrameBufferInit/visibleRect}}.{{DOMRectInit/width}} >=
+ {{VideoFrameBufferInit/codedWidth}}, return `false`.
+ 5. If only one of {{VideoFrameBufferInit/displayWidth}} or
+ {{VideoFrameBufferInit/displayHeight}} [=map/exists=], return `false`.
+ 6. If {{VideoFrameBufferInit/displayWidth}} = 0 or
+ {{VideoFrameBufferInit/displayHeight}} = 0, return `false`.
+ 7. Return `true`.
: Initialize Frame From Other Frame (with |init|,
|frame|, and |otherFrame|)
@@ -3151,7 +3142,7 @@
{{VideoFrame/codedWidth}}, {{VideoFrame/displayWidth}}.
5. Assign |height| to the following attributes of |frame|:
{{VideoFrame/codedHeight}}, {{VideoFrame/displayHeight}}.
- 6. Assign «[ "left:" → `0`, "top" → `0`, "width" → |width|, "height" →
+ 6. Assign «[ "x:" → `0`, "y" → `0`, "width" → |width|, "height" →
|height| ]» to |frame|.{{VideoFrame/visibleRect}}.
7. Assign `init`.{{VideoFrameInit/duration}} to
|frame|.{{VideoFrame/duration}}.
@@ -3183,37 +3174,45 @@
{{VideoFrame/[[timestamp]]}}.
: Parse VideoFrameCopyToOptions (with |options|)
-:: 1. Let |parsedRect| be the result of running the [=VideoFrame/Parse CopyTo
- Rect=] with |options|.
- 2. If |parsedRect| is an exception, return |parsedRect|.
- 3. Let |parsedOptions| be the result of running the [=VideoFrame/Compute
- Layout and Allocation Size=] algorithm with |parsedRect| and |options|.
- 6. Return |parsedOptions|.
-
-: Parse CopyTo Rect (with |options|)
-:: 1. Let |sourceRect| be the be the result of performing the getter steps for
+:: 1. Let |defaultRect| be the result of performing the getter steps for
{{VideoFrame/visibleRect}}.
- 2. If {{VideoFrameCopyToOptions/rect}} [=map/exists=] in |options|:
- 1. Let |optRect| be {{VideoFrameCopyToOptions/rect}}:
- 2. If either of |optRect|.{{DOMRectInit/width}} or
+ 2. Let |overrideRect| be `undefined`.
+ 3. If |options|.{{VideoFrameCopyToOptions/rect}} [=map/exists=], assign its
+ value to |overrideRect|.
+ 4. Let |parsedRect| be the result of running the [=VideoFrame/Parse Visible
+ Rect=] algorithm with |defaultRect|, |overrideRect|,
+ {{VideoFrame/[[coded width]]}}, {{VideoFrame/[[coded height]]}}, and
+ {{VideoFrame/[[format]]}}.
+ 5. If |parsedRect| is an exception, return |parsedRect|.
+ 6. Let |optLayout| be `undefined`.
+ 7. If |options|.{{VideoFrameCopyToOptions/layout}} [=map/exists=], assign
+ its value to |optLayout|.
+ 8. Let |combinedLayout| be the result of running the [=VideoFrame/Compute
+ Layout and Allocation Size=] algorithm with |parsedRect|,
+ {{VideoFrame/[[format]]}}, and |optLayout|.
+ 9. Return |combinedLayout|.
+
+: Parse Visible Rect (with |defaultRect|, |overrideRect|, |codedWidth|, |codedHeight|, and |format|)
+:: 1. Let |sourceRect| be |defaultRect|
+ 2. If |overrideRect| is not `undefined`:
+ 1. If either of |overrideRect|.{{DOMRectInit/width}} or
{{DOMRectInit/height}} is `0`, return a {{TypeError}}.
- 3. If the sum of |optRect|.{{DOMRectInit/x}} and
- |optRect|.{{DOMRectInit/width}} is greater than
+ 2. If the sum of |overrideRect|.{{DOMRectInit/x}} and
+ |overrideRect|.{{DOMRectInit/width}} is greater than
{{VideoFrame/[[coded width]]}}, return a {{TypeError}}.
- 4. If the sum of |optRect|.{{DOMRectInit/y}} and
- |optRect|.{{DOMRectInit/height}} is greater than
+ 3. If the sum of |overrideRect|.{{DOMRectInit/y}} and
+ |overrideRect|.{{DOMRectInit/height}} is greater than
{{VideoFrame/[[coded height]]}}, return a {{TypeError}}.
- 5. Assign |optRect| to |sourceRect|.
+ 4. Assign |overrideRect| to |sourceRect|.
3. Let |planeIndex| be `0`.
- 4. Let |numPlanes| be the number of planes as defined by
- {{VideoFrame/[[format]]}}
+ 4. Let |numPlanes| be the number of planes as defined by |format|.
5. While |planeIndex| is less than |numPlanes|:
- NOTE: The following steps validate |rect| is sample-aligned for this
- frame's {{VideoFrame/[[format]]}}.
+ NOTE: The following steps validate |rect| is sample-aligned for the
+ given |format|.
1. Let |plane| be the Plane identified by |planeIndex| as defined by
- {{VideoFrame/[[format]]}}.
+ |format|.
2. Let |sampleWidth| be the horizontal [=sub-sampling factor=] of each
subsample for |plane|.
3. Let |sampleHeight| be the vertical [=sub-sampling factor=] of each subsample
@@ -3228,18 +3227,17 @@
6. Return |sourceRect|.
: Compute Layout and Allocation Size (with
- |parsedRect| and |options|)
-:: 1. Let |numPlanes| be the number of planes as defined by
- {{VideoFrame/[[format]]}}
- 2. If {{VideoFrameCopyToOptions/layout}} [=map/exists=] its size does not
- equal |numPlanes|, throw a {{TypeError}}.
+ |parsedRect|, |format|, and |layout|)
+:: 1. Let |numPlanes| be the number of planes as defined by |format|.
+ 2. If |layout| is not `undefined` and its length does not equal |numPlanes|,
+ throw a {{TypeError}}.
3. Let |minAllocationSize| be `0`.
4. Let |computedLayouts| be a new [=list=].
5. Let |endOffsets| be a new [=list=].
6. Let |planeIndex| be `0`.
7. While |planeIndex| < |numPlanes|:
1. Let |plane| be the Plane identified by |planeIndex| as defined by
- {{VideoFrame/[[format]]}}.
+ |format|.
2. Let |sampleBytes| be the number of bytes per sample for |plane|.
3. Let |sampleWidth| be the horizontal [=sub-sampling factor=] of each
subsample for |plane|.
@@ -3260,9 +3258,9 @@
10. Set |computedLayout|'s [=computed plane layout/sourceWidthBytes=] to
the result of the integer division of
truncated |parsedRect|.{{DOMRectInit/width}} by |sampleWidthBytes|.
- 11. If {{VideoFrameCopyToOptions/layout}} [=map/exists=]:
- 1. Let |planeLayout| be the {{PlaneLayout}} in
- {{VideoFrameCopyToOptions/layout}} at position |planeIndex|.
+ 11. If |layout| is not `undefined`:
+ 1. Let |planeLayout| be the {{PlaneLayout}} in |layout| at position
+ |planeIndex|.
2. If |planeLayout|.{{PlaneLayout/stride}} is less than
|computedLayout|'s [=computed plane layout/sourceWidthBytes=],
return a {{TypeError}}.
@@ -3310,13 +3308,13 @@
4. Increment |earlierPlaneIndex| by `1`.
20. Append |computedLayout| to |computedLayouts|.
21. Increment |planeIndex| by `1`.
- 8. Let |parsedOptions| be a new [=parsed copyto options=], initialized as
+ 8. Let |combinedLayout| be a new [=combined buffer layout=], initialized as
follows:
1. Assign |computedLayouts| to
- [=parsed copyto options/computedLayouts=].
+ [=combined buffer layout/computedLayouts=].
2. Assign |minAllocationSize| to
- [=parsed copyto options/allocationSize=].
- 9. Return |parsedOptions|.
+ [=combined buffer layout/allocationSize=].
+ 9. Return |combinedLayout|.
### Transfer and Serialization ###{#videoframe-transfer-serialization}