I need to make a program that asks for how many days there are in a particular month, and then ask for the minimum and maximum temperature for each of the days.
So now i'm wondering how i'm supposed to make it ask for the temperature of exactly 30 days, and not 28 or 29 or 31, if it's 30 that i've entered.
I don't know how clear i made myself there, but i hope someone can help me out :)
(i'm not asking anyone to write everything for me, but to just point me in the right direction)
Thanks!
have you got any code so far? post what you have, and we can try to help.
Also, do you really want to specify how many days are in the month, or would you like to just specify which month and have it automatically know number of days (with perhaps exception of having to ask if it's leapyear or not for feburary)?
You can hard code an array to contain that information.
I don't really have any code yet. But what i was thinking is that there's gotta be an easier way to fill in the temperatures than what i've thought of, which is to make an int for every temperature (if that would work at all).
int mintemp1, mintemp2, mintemp3, mintemp4, mintemp5, mintemp6, mintemp7;
int mintemp8, mintemp9, mintemp10, mintemp11, mintemp12, mintemp13, mintemp14;
int mintemp15, mintemp16, mintemp17, mintemp18, mintemp19, mintemp20;
int mintemp21, mintemp22, mintemp23, mintemp24, mintemp25, mintemp26;
int mintemp27, mintemp28, mintemp29, mintemp30, mintemp31;
And the program should then ask me to fill in the temp. for the number of days that i type in, and forget about the rest of the ints/days.
This is not how you would do it, right?
And yes, i have to specify the number of days, not just bringing up some pre-made calendar.
Ok, i've discovered that i don't really need to store every temperature that i enter. It's enough that i just add them all together and divide on the number of days (i need to find the average temperature). So i won't need all those ints.
What i need to find out now is how to make it ask for the temperature for only the entered number of days. You know, if i enter 28, then i will have to enter 28 temps.
I'm guessing that a for-loop is needed here?
I tried putting something together (this actually seems to work as intended):
Also, i'm supposed to use consts for the max and min temperatures, instead of hard coding them everywhere like i've done here. But i don't understand why and how i'm supposed to use it, since they are a range from -70 to 70, and not a single number. Any ideas?


Activist: How many classes must we skip for world to know we're suffering? | IOL News
Madrid - Youths from developing countries are concerned about the planet's future and their respective governments' inadequacy at combating climate change.
The announcement was made by activists from the Americas, Africa and Asia during a press conference on Monday at the United Climate Change Conference - COP25 - in Madrid, Spain.
The youngsters shared their fears about the extreme weather patterns and pollution damaging their home countries and continents.
National leaders have been heavily criticised at this year's COP25 for the insufficient mitigation and adaption measures in place to fight climate change.
Nakabuye Flavia, a student from Uganda, described the lack of climate action as "environmental racism".


For most choices of P(Ψ) and g(Ψ), the GS equation (66) has to be solved numerically. For the particular choice of P and g proﬁles given by
|
| (508) |
|
| (509) |
analytical solution to the GS equation can be found, which is given by[16]
|
| (510) |
where c0, c1, c2, and R0 are arbitrary constants. [Proof: By direct substitution, we can verify Ψ of this form is indeed a solution to the GS equation (66).] A useful choice for tokamak application is to set c0 = B0∕(R02κ0q0), c1 = B0(κ02 + 1)∕(R02κ0q0), and c2 = 0. Then Eq. (510) is written
|
| (511) |
which can be solved analytically to give the explicit form of the contour of Ψ on (R,Z) plane:
|
| (512) |
which indicates the magnetic surfaces are up-down symmetrical. Using Eq. (508), i.e.,
|
| (513) |
the pressure is written
|
| (514) |
where P0 is a constant of integration. Note Eq. (511) indicates that that Ψ = 0 at the magnetic axis (R = R0,Z = 0). Therefore, Eq. (514) indicates that P0 is the pressure at the magnetic axis. The toroidal ﬁeld function g is a constant in this case, which implies there is no poloidal current in this equilibrium. (For the Solovev equilibrium (511), I found numerically that the value of the safety factor at the magnetic axis (R = R0,Z = 0) is equal to q0g∕(R0B0). This result should be able to be proved analytically. I will do this later. In calculating the safety factor, we also need the expression of |∇Ψ|, which is given analytically by
Deﬁne Ψ0 = B0R02, and Ψ = Ψ∕Ψ0, then Eq. (511) is written as
where R = R∕R0, Z = Z∕R0. From Eq. (516), we obtain|
| (517) |
Given the value of κ0, q0, for each value of Ψ, we can plot a magnetic surface on (R,Z) plane. An example of the nested magnetic surfaces is shown in Fig. 38.
The minor radius of a magnetic surface of the Solovev equilibrium can be calculated by using Eq. (512), which gives
|
| (518) |
|
| (519) |
and thus
|
| (520) |
where A = 8R02q0∕(B0κ0). In my code of constructing Solovev magnetic surface, the value of a is speciﬁed by users, and then Eq. (520) is solved numerically to obtain the value of Ψ of the ﬂux surface. Note that the case Ψ = 0 corresponds to Rin = Rout = R0, i.e., the magnetic axis, while the case Ψ = R02B0κ0∕(8q0) corresponds to Rin = 0. Therefore, the reasonable value of Ψ of a magnetic surface should be in the range 0 ≤ Ψ < R02B0κ0∕(8q0). This range is used as the interval bracketing a root in the bisection root ﬁnder.
Using Eq. (520), the inverse aspect ratio of a magnetic surface labeled by Ψ can be approximated as[16]
|
| (521) |
Therefore, the value of Ψ of a magnetic surface with the inverse aspect ratio 𝜀 is approximately given by
|
| (522) |


Here you will find a curated collection of resources to help you along your journey. We have everything from looking for help picking a bootcamp, what to do after it is done and you've crossed the Finish Line! Don't forget to create an account to save your favorite articles and resources to your personal profile.


Contact Us
Contact us...
The lion (Panthera leo) is a species in the family Felidae; it is a muscular, deep-chested cat with a short, rounded head, a reduced neck and round ears, and a hairy tuft at the end of its tail.
The lion (Panthera leo) is a species in the family Felidae; it is a muscular, deep-chested cat with a short, rounded head, a reduced neck and round ears, and a hairy tuft at the end of its tail.


Booking ID: {{ selectedBooking._id }}
Vehicle name: {{ selectedBooking.vehicle.name }}
No.of people: {{ selectedBooking.partnersCount }}
Booked From: {{ selectedBooking.bookedFrom }}
Booked Till: {{ selectedBooking.bookedTo }}
Amount: ₹{{ selectedBooking.amount }}
Distance: {{ selectedBooking.location.distance }} kms
Approx Duration Time: {{ durationInHours }} Hrs
Source: {{ sourceName }}
Destination: {{ destinationName }}


{% extends "email/base.html" %} {% block subject %}Added as member to '{{ auditors_group_name }}'{% endblock %} {% block content %}
You are an approver (owner or manager) of one or more audited groups, but you were previously not an auditor. We have automatically made you an auditor by adding you to group '{{ auditors_group_name }}'. For more information, please see Grouper Help.
{% endblock %}


--- layout: post title: "In the News: Teaching Machines on The Learning Hack Podcast" date: 2021-07-19 15:00:00 +0000 tags: image: https://s3.amazonaws.com/audreywatters/2017-11-03-news.jpg imagecredits: https://www.flickr.com/photos/62693815@N03/6277209256 ---
I was a guest on The Learning Hack podcast, and host John Helmer and I discuss Teaching Machines and the influence of B. F. Skinner and behaviorism on education and ed-tech.
Give it a listen...


{% extends "lookup_hub/base.html" %} {% block header %}Welcome to the Lookup Hub{% endblock %} {% block body %}
This is a place for collaborative work on a custom dictionary.
First time here? Visit the Sandbox first.
Or, if you know what you're doing, head on over to the hub.


As part of the Conference App that we built recently I was tasked with learning how to use Angular.
This blog details some of the ups and downs of the learning experience.
All code referred to in this blog post is available on GitHub: https://github.com/Creou/ConferenceApp
Having now finished the first phase of the conference app I at least know something about Angular, although I'm still far from an expert. Undoubted some of the ways that I have accomplished goals could have been done better, but this is part of the learning experience.
This is not a 'learn Angular' blog, it's a blog about me trying to learn Angular.
I've previously worked on WebAPI projects so I was familiar with producing a REST back end. I've also worked on ASP.net and WebForms projects and felt the pain of trying to understand the .Net page lifecycle and custom controls.
I've not done a great deal of HTML or Javascript as most of the projects I'd previously worked on had already existing front end systems in place and had never worked on a single page web application.
Most of my previous experience has been with server side technologies with only minimal front end experience and so I'm pushing myself to keep up to date with newer and emerging front end technologies. Simon had identified a need for an app to assist conference delegates, therefore this seemed like a good excuse to get stuck into learning about a single page app framework.
There are a number of single page app frameworks that we could have chosen like Ember, or Backbone (a comparison of which can be found here: https://www.airpair.com/js/javascript-framework-comparison)
As a company we've recently been exposed to (the results of) Angular on a client project and we were suitably impressed. Also it seems like one of the most popular frameworks and possibly the most supported so we choose this as our framework of choice for this app.
The point of the app is to facilitate the experience of attending a conference with multiple 'Tracks' of discourses that could be attended. A user can view the various sessions grouped by either 'Track' or by time and be presented with list of session titles and times. By clicking on those titles they can find out additional information such as room name/number, the speaker, and the session description. The user can also choose to leave feedback about each session and also about the conference as a whole. This feedback comprises some 1-5 star ratings for various aspects and also free text for suggestions/comments. The feedback is saved to a database for the conference organisers to analyse to improve future events.
If you want to see the finished app you can find it here: http://creouconferenceappserver.azurewebsites.net/app/AwesomeApp.html#/home
Having previously worked with ASP.net web forms I was excited about the (relative/reported) simplicity of the Angular way. Had I had experience of some of the other SPA frameworks this may not have been such a novelty, but this was the first one I'd had opportunity to use/learn. (If you've ever done web forms you will understand).
I was developing the app in Visual Studio and being a fan of Nuget used that to obtain the Angular package. There are some fairly easy to follow videos on the Angular web site, although it wasn't clear from the outset how these simple demos would translate to the requirements of my app.
This is partially due to it being a web technology but I found it initially confusing that there seems to be a fairly large number of different ways to achieve the same result without any being obviously more correct than others. I also think the Angular website needs some love to make it more obvious where the tutorials are. (They are in the 'Develop' toolbar menu). I ended up watching 3rd party tutorial videos which may or may not have contributed to the 'many ways to do something' issue.
Angular code is modular with all dependencies injected via constructor injection. This makes it very easy to write automated tests for.
app.controller('controllerName', function (injected, dependancies, here) { ...code that uses the dependancies... });
The 'single page' is constructed in the usual way, either as a static page or delivered some other way if required (MVC). The single page has a single 'ng-app' attribute on the html tag that signifies that this is an angular container. Also on the static page there is an element with an 'ng-view' attribute. This signifies the container for all of the Angular generated content. Additional content can appear outside of this but will not be inserted by Angular.
 ...  ...

Navigation between 'virtual' pages is via anchor style links which are 'routed' via a routing engine to specified 'controllers' and 'templates'.
app.config(function ($routeProvider, $locationProvider) { ... $routeProvider.when('/byTrack', { templateUrl: 'partials/byTrack.html', controller: 'ByTrackController' }); $routeProvider.when('/byTime', { templateUrl: 'partials/byTime.html', controller: 'ByTimeController' }); ... }
The routing can load templates via HTTP requests from separate files reducing the amount of mark-up that must be loaded on app start-up/page load. 'Templates' are basically the 'view' of MVVM and are Angular compiled HTML files that will get inserted into the ng-view container.
Links do not have to be within the ng-view container as demonstrated in the conference app by a Bootstrap navbar that sits just above the ng-view container.

Home

By Track

By Time

Feedback

Controllers, like other angular components are just JavaScript
functions. The controller prepares data making it available for binding to the
view (equivalent to the view-model?). In our conference app the controllers'
job is typically to make a request from the data layer, and then sort/filter
the data as required. It is also where event listeners are registered to deal
with e.g. button clicks and then sending the data back to the data layer.
In the example below from the conference app the event feed-back controller is fetching the 'company size' values
app.controller('EventFeedbackController', function ($scope, ...) { ... $scope.statii = statiiService.query(function (value) { var x = value; });... }
Which are used to populate a drop down combo box bound in the view:
What size company do you work for?
 <select ng-model="feedback.CompanySize" class="form-control" ng-disabled="formDisable" ng-options="size.Id as size.Text for size in sizes"> <option value="">Select company size</option> </select>

Directives are like code snippets, or partial views. They can have their own controller and template. They are also the only part of the Angular framework where it is recommended to interact directly with the DOM. In the conference app I used a directive to render the sessions in a consistent way and to minimise code duplication as various pages needed to render session information. They can also be used to modify elements rather than replace them. IMHO directives are one of the more complicated bits of Angular with a lot of things, some quite complicated, to understand. However some of the more simple things can be picked up fairly quickly.
Session detail directive from app:
app.directive('sessionDetail', function () { return { templateUrl: 'partials/sessionDetail.html', restrict: 'E', replace: true, scope: { session: '=data' }, controller: 'SessionDetailController' }; });
Some things can be quite trying, for instance directives are supposed to be declared using pascalCase but consumed in hyphenated-format. E.g. my session directive was declared as sessionDetail but had to be consumed as session-detail. It's a feature that you can do this however I didn't realise at first that it was required. You cannot consume your directives in their declared pascalCase, it just doesn't work. There is actually a page on the Angular site that lists some common pitfalls, but personally I think these will depend on your programming background. I also had issues with 'promises'. This is possibly due to the various 'types' of promises that exist currently due to non-universal browser support, but either way promises didn't seem to work as expected in a consistent manner which meant I ended up using call backs some of the time.
It's incredibly easy to knock up a CRUD style application in
minutes once you've got the hang of it with virtually no 'boilerplate'.
Example on SitePoint.
Would I be happy to use Angular again? Yes most definitely. Even when you consider technologies like MVC which make CRUD style operations easy, if you are going to use Ajax or Javascript at all in your pages then it could potentially benefit from Angular.
http://www.codeproject.com/Articles/808213/Developing-a-Large-Scale-Application-with-a-Single
Sam Price
Unless otherwise specified all code in this post is made available under the MIT license. Copyright 2015 Creou Limited.


This is a IBM AP IGA TST Megabot can help running BI central report automatically, accompanying the AI platform IBM Watson, hosted on IBM Cloud.
TST Chatbot is the sample to use Watson Consersation API to interact with computer by human language, TST Chatbot will guide you to fix the technical issues which you used to send request to TST function ID.


Dictionaries
Types of Dictionaries
Visual:
The library also carries visual dictionaries with different languages, such as French, German and Italian,
all in one book with annotated color photographs.
Foreign Language Visual Bilingual Dictionaries:
These books cover many languages and the visuals come in handy when trying to find a specific word.
Subject Dictionaries:
Math, Dinosaurs, Space, Medical
Thesaurus
Thesauri books contain synonyms and antonyms; words that are similar and contrasting. E.g. Antonyms, meaning opposite.
Most Popular Brands
American Heritage
Roget’s Thesaurus
Merriam-Webster’s Collegiate Thesaurus
Encyclopedias
Encyclopedias contain facts about thousands of subjects. Encyclopedias are creditable references for your work.


eXistenZ (1999) Jennifer Jason Leigh, Jude Law, Willem Dafoe, Ian Holm, Don McKellar, Callum Keith Rennie, Sarah Polley, Christopher Eccleston. Music by Howard Shore. Cinematography by Peter Suschitzky. Written and directed by David Cronenberg. 97 minutes. Rated R, 1.5 stars (out of five stars)
Review by Ed Johnson-Ott, NUVO Newsweekly www.nuvo-online.com Archive reviews at http://us.imdb.com/M/reviews_by?Edward+Johnson-ott To receive reviews by e-mail at no charge, send subscription requests to<EMAIL_ADDRESS>"Videodrome" and "Dead Ringers" director David Cronenberg is really getting on my neRvZ. As a follow-up to "Crash," his 1996 endurance test about people who get sexually aroused by car wrecks, he offers "eXistenZ, " a grisly, uninspired tale about virtual reality run amok. Once again, Cronenberg operates on the assumption that if you fill the screen with enough creepy imagery, people will overlook leaden pacing, flat characters and a tired, obvious "question reality" storyline with a final "twist" so obvious that it's almost laughable.
The basic theme of "eXistenZ" was explored more effectively in 1995's "Strange Days," and with far less goo. Cronenberg throws so much blood and guts into this film that at times I felt like I was watching the Surgery Channel on a TV placed in a tank full of bait. I wish he would just take a job in a slaughterhouse and get this fetish out of his system once and for all.
Cronenberg also uses another of his favorite attention-getting devices, grisly sexual imagery. To play eXistenZ (pronounced EGGs-iz-TENZ), participants must have "bio ports" drilled into their lower backs to allow an organic cord to plug the "metaflesh game pod" directly into the spinal column. In addition to showing us the vaguely phallus-shaped cords being plugged into the "bio-ports," we're also treated to a shot of one character inserting a finger into a freshly drilled "port" hole and another of a character licking one of the openings. Golly (nudge, nudge, wink, wink), what could David possibly be alluding to with these images? One thing's for sure: I would never let this guy date my sister.
The gore-porn motif might be acceptable were it serving a novel story, but after an intriguing beginning, the film goes nowhere, and takes what feels like forever to get there. It starts at a test session for eXistenZ. Volunteers meet Allegra Geller (Jennifer Jason Leigh), inventor of the new virtual reality game, and prepare to try out her creation. Suddenly, an audience member leaps forward, shouting revolutionary slogans while trying to assassinate Allegra with a gun that looks as if it were assembled from Thanksgiving turkey leftovers. Ted Pikul (Jude Law), a company lackey and virtual reality virgin, rescues Allegra and the pair take flight. Unsure whom to trust, Allegra cuts off contact with everyone except Ted, enlisting his help to repair the prototype game pod that was damaged in the attack. With great misgivings, Ted agrees to be fitted with a "bio port" and the couple sets off on a virtual reality recovery mission.
Unfortunately, Cronenberg's virtual worlds are considerably less interesting than the real one. Allegra and Ted spend a great portion of the film encountering cryptic figures in a trout farm and a Chinese restaurant. Everyone chases each other around while brandishing organic guns that shoot teeth, Allegra rubs things a lot and bonds with a two- headed sort-of salamander and, when not fighting or making out, the couple wonders whether they've reached reality or just another level of the game. Trust me, this description reads more exciting that it plays out onscreen.
Although only 97 minutes long, "eXistenZ" plods terribly before stumbling to its trite conclusion. Along the way, a great cast is wasted. Wonderful actors like Willem Dafoe, Ian Holm and Sarah Polley are given throwaway parts and Jude Law is saddled with a terminally bland role. Remember the moment in "The Matrix" when Keanu Reeves says "Whoa?" Law's character basically stays at that level of emotional development for the entire movie. Only Jennifer Jason Leigh, as the shy adventurer, plays a fully- fleshed out human being. She's good, but not good enough to salvage this production.
"eXistenZ" has some redeeming qualities. The score is good and the opening scene features some nice moments. Satiric jabs at marketing and consumerism are scattered, too infrequently, throughout the story, and there is a dandy sequence where several game users critique their own virtual characters. But "eXistenZ" is smothered by lousy pacing and an awful "been-there, done-that" feeling. Cautionary tales about virtual reality have already been covered quite nicely, David Lynch handled weirdness more stylishly in any given episode of "Twin Peaks," and Cronenberg's gross-out visuals and freaky sexuality are old news. Hopefully, before making his next movie, Cronenberg will review "The Dead Zone" or "The Fly" and remember how well he can handle the horror genre. Or, better yet, maybe he'll take a walk on a sunny day and try to capture its essence on film. For the King of Ick, what an accomplishment that would be.
© 1999 Ed Johnson-Ott
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


Title: WebCodecs
Repository: wicg/web-codecs
Status: CG-DRAFT
ED: https://wicg.github.io/web-codecs/
Shortname: web-codecs
Level: 1
Group: wicg
Editor: Chris Cunningham, w3cid 114832, Google Inc. https://google.com/
Editor: Paul Adenot, w3cid 62410, Mozilla https://www.mozilla.org/
Editor: Bernard Aboba, w3cid 65611, Microsoft Corporation https://www.microsoft.com/
Abstract: This specification defines interfaces for encoding and decoding audio
Abstract: and video. It also includes an interface for retrieving raw video
Abstract: frames from MediaStreamStracks.
Markup Shorthands:css no, markdown yes, dfn yes
!Participate: Git Repository.
!Participate: File an issue.
!
: Key Frame
:: An encoded frame that does not depend on any other frames for decoding.
: Internal Pending Output
:: Codec outputs such as {{VideoFrame}}s that currently reside in the internal
pipeline of the underlying codec implementation. The underlying codec
implementation may emit new outputs only when a new inputs are provided. The
underlying codec implementation must emit all outputs in response to a
flush.
: Codec System Resources
:: Resources including CPU memory, GPU memory, and exclusive handles to specific
decoding/encoding hardware that may be allocated by the User Agent as part
of codec configuration or generation of {{AudioFrame}} and {{VideoFrame}}
objects. Such resources may be quickly exhuasted and should be released
immediately when no longer in use.
: Advanced Video Coding (AVC)
:: Also known as H.264. Refers to the methods of video compression as defined by
[[!iso14496-10]].
: Picture Parameter Set (PPS)
:: A set of parameters describing AVC coded pictures as defined by
[[!iso14496-10]].
: Sequence Parameter Set (SPS)
:: A set of parameters describing a sequence of AVC coded video as
defined by [[!iso14496-10]].
Codec Processing Model {#codec-processing-model}
================================================
Background {#processing-model-background}
-----------------------------------------
This section is non-normative.
The codec interfaces defined by the specification designed such that new codec
tasks may be scheduled while previous tasks are still pending. For example, web
authors may call `decode()` without waiting for a previous `decode()` to
complete. This is achieved by offloading underlying codec tasks to a separate
thread for parallel execution.
This section describes threading behaviors as they are visible from the
perspective of web authors. Implementers may choose to use more or less threads
as long the exernally visible behaviors of blocking and sequencing are
maintained as follows.
Control Thread and Codec Thread {#control-thread-and-codec-thread}
------------------------------------------------------------------
All steps in this specificaiton will run on either a [=control thread=] or
a [=codec thread=].
The control thread is the thread from which authors will construct
a [=codec=] and invoke its methods. Invoking a codec's methods will typically
result in the creation of [=control messages=] which are later executed on the
[=codec thread=]. Each [=global object=] has a separate control thread.
The codec thread is the thread from which a [=codec=] will
[=dequeue=] [=control messages=] and execute their steps. Each [=codec=]
instance has a separate codec thread. The lifetime of a codec thread matches
that of its associated [=codec=] instance.
The [=control thread=] uses a traditional event loop, as described in [[!HTML]].
The [=codec thread=] uses a specialized [=codec processing loop=].
Communication from the [=control thread=] to the [=codec thread=] is done using
[=control message=] passing. Communication in the other direction is done using
regular event loop tasks.
Each [=codec=] instance has a single control message queue that is
a [=queue=] of control messages.
Queuing a control
message means [=enqueing=] the message to a [=codec=]’s [=control
message queue=]. Invoking codec methods will often queue a control message
to schedule work.
Running a control
message means performing a sequence of steps specified by the method
that enqueued the message. The steps of a control message may depend on
injected state, supplied by the method that enqueued the message.
Resetting the control message
queue means performing these steps:
1. For each [=control message=] in the [=control message queue=]:
1. If a control message's [=injected state=] includes a promise, reject
that promise.
2. Remove the message from the queue.
The codec processing loop must run these steps:
1. While true:
1. If the [=control message queue=] is emtpy, [=continue=].
2. Dequeue |front message| from the [=control message queue=].
3. Run [=control message steps=] described by |front message|.
AudioDecoder Interface {#audiodecoder-interface}
================================================
[Exposed=(Window,DedicatedWorker)]
interface AudioDecoder {
constructor(AudioDecoderInit init);
readonly attribute CodecState state;
readonly attribute long decodeQueueSize;
undefined configure(AudioDecoderConfig config);
undefined decode(EncodedAudioChunk chunk);
Promise flush();
undefined reset();
undefined close();
static Promise isConfigSupported(AudioDecoderConfig config);
};
dictionary AudioDecoderInit {
required AudioFrameOutputCallback output;
required WebCodecsErrorCallback error;
};
callback AudioFrameOutputCallback = undefined(AudioFrame output);
Internal Slots {#audiodecoder-internal-slots}
---------------------------------------------
- [[codec implementation]]
- Underlying decoder implementation provided by the User Agent.
- [[output callback]]
- Callback given at construction for decoded outputs.
- [[error callback]]
- Callback given at construction for decode errors.
Constructors {#audiodecoder-constructors}
-----------------------------------------
AudioDecoder(init)
1. Let d be a new {{AudioDecoder}} object.
2. Assign init.output to the {{AudioDecoder/[[output callback]]}} internal slot.
3. Assign init.error to the {{AudioDecoder/[[error callback]]}} internal slot.
4. Assign "unconfigured" to d.state.
4. Return d.
Attributes {#audiodecoder-attributes}
-------------------------------------
-
state
- Describes the current state of the codec.
-
decodeQueueSize
-
The number of pending decode requests. This number will decrease as the
underlying codec is ready to accept new input.
Methods {#audiodecoder-methods}
-------------------------------
- configure(config)
-
[=Enqueues a control message=] to configure the audio decoder for decoding
chunks as described by |config|.
NOTE: Authors should first check support by calling
{{AudioDecoder/isConfigSupported()}} with |config| to avoid error paths
in the steps below.
When invoked, run these steps:
1. If |config| is not a [=valid AudioDecoderConfig=], throw a
{{TypeError}}.
2. If {{AudioDecoder/state}} is `“closed”`, throw an {{InvalidStateError}}.
3. Set {{AudioDecoder/state}} to `"configured"`.
4. [=Queue a control message=] to configure the decoder with |config|.
[=Running a control message=] to configure the decoder means running
these steps:
1. Let |supported| be the result of running the Check Configuration
Support algorith with |config|.
2. If |supported| is `true`, assign
{{AudioDecoder/[[codec implementation]]}} with an implementation
supporting |config|.
3. Otherwise, run the Close AudioDecoder algorithm with
{{NotSupportedError}}.
- decode(chunk)
-
[=Enqueues a control message=] to decode the given |chunk|.
When invoked, run these steps:
1. If {{VideoDecoder/state}} is not `"configured"`, throw an
{{InvalidStateError}}.
2. Increment {{VideoDecoder/decodeQueueSize}}.
3. [=Queue a control message=] to decode the |chunk|.
Running a control message to decode the chunk means performing these steps:
1. Attempt to use {{VideoDecoder/[[codec implementation]]}} to decode the
chunk.
2. If decoding results in an error, queue a task on the [=control thread=]
event loop to run the [=Close VideoDecoder=] algorithm with
{{EncodingError}}.
3. Queue a task on the [=control thread=] event loop to decrement
{{VideoDecoder/decodeQueueSize}}
4. Let |decoded outputs| be a [=list=] of decoded video data outputs emitted
by {{VideoDecoder/[[codec implementation]]}}.
5. If |decoded outputs| is not empty, queue a task on the [=control thread=]
event loop to run the [=Output VideoFrames=] algorithm with
|decoded outputs|.
- flush()
-
Completes all [=control messages=] in the [=control message queue=]
and emits all outputs.
When invoked, run these steps:
1. If {{AudioDecoder/state}} is not `"configured"`, return
[=a promise rejected with=] {{InvalidStateError}} {{DOMException}}.
2. Let |promise| be a new Promise.
3. [=Queue a control message=] to flush the codec with |promise|.
4. Return |promise|.
Running a control message to flush the codec means performing these steps
with |promise|.
1. Signal {{AudioDecoder/[[codec implementation]]}} to emit all [=internal
pending outputs=].
2. Let |decoded outputs| be a [=list=] of decoded audio data outputs emitted
by {{AudioDecoder/[[codec implementation]]}}.
3. If |decoded outputs| is not empty, queue a task on the [=control thread=]
event loop to run the [=Output AudioFrames=] algorithm with
|decoded outputs|.
4. Queue a task on the [=control thread=] event loop to resolve |promise|.
- reset()
-
Immediately resets all state including configuration,
[=control messages=] in the [=control message queue=], and all pending
callbacks.
When invoked, run the [=Reset AudioDecoder=] algorithm.
- close()
-
Immediately aborts all pending work and releases [=system resources=].
Close is final.
When invoked, run the [=Close AudioDecoder=] algorithm.
- isConfigSupported(config)
-
Returns a promise indicating whether the provided |config| is supported by
the user agent.
NOTE: The returned {{AudioDecoderSupport}} {{AudioDecoderSupport/config}}
will contain only the dictionary members that user agent recognized.
Unrecognized dictionary memebers will be ignored. Authors may detect
unrecognized dictionary members by comparinging
{{AudioDecoderSupport/config}} to their provided |config|.
When invoked, run these steps:
1. If |config| is not a valid AudioDecoderConfig, return
[=a promise rejected with=] {{TypeError}}.
2. Let |p| be a new Promise.
3. Let |checkSupportQueue| be the result of starting a new parallel
queue.
4. Enqueue the following steps to |checkSupportQueue|:
1. Let |decoderSupport| be a newly constructed
{{AudioDecoderSupport}}, initialized as follows:
1. Set {{AudioDecoderSupport/config}} to the result of running the
Clone Configuration algorithm with |config|.
2. Set {{AudioDecoderSupport/supported}} to the result of running
the Check Configuration Support algorithm with |config|.
2. Resolve |p| with |decoderSupport|.
5. Return |p|.
Algorithms {#audiodecoder-algorithms}
-------------------------------------
- Output AudioFrames (with |outputs|)
-
Run these steps:
1. For each |output| in |outputs|:
1. Let |buffer| be an {{AudioBuffer}} containing the decoded audio data in
|output|.
2. Let |frame| be an {{AudioFrame}} containing |buffer| and a timestamp for
the output.
3. Invoke {{AudioDecoder/[[output callback]]}} with frame.
- Reset AudioDecoder
-
Run these steps:
1. If {{AudioDecoder/state}} is `"closed"`, throw an {{InvalidStateError}}.
2. Set {{AudioDecoder/state}} to `"unconfigured"`.
3. Signal {{AudioDecoder/[[codec implementation]]}} to cease producing
output for the previous configuration.
4. [=Reset the control message queue=].
5. Set {{AudioDecoder/decodeQueueSize}} to zero.
- Close AudioDecoder (with error)
-
Run these steps:
1. Run the [=Reset AudioDecoder=] algorithm.
2. Set {{AudioDecoder/state}} to `"closed"`.
3. Clear {{AudioDecoder/[[codec implementation]]}} and release associated
[=system resources=].
4. If |error| is set, queue a task on the [=control thread=] event loop to
invoke the {{AudioDecoder/[[error callback]]}} with |error|.
VideoDecoder Interface {#videodecoder-interface}
================================================
[Exposed=(Window,DedicatedWorker)]
interface VideoDecoder {
constructor(VideoDecoderInit init);
readonly attribute CodecState state;
readonly attribute long decodeQueueSize;
undefined configure(VideoDecoderConfig config);
undefined decode(EncodedVideoChunk chunk);
Promise flush();
undefined reset();
undefined close();
static Promise isConfigSupported(VideoDecoderConfig config);
};
dictionary VideoDecoderInit {
required VideoFrameOutputCallback output;
required WebCodecsErrorCallback error;
};
callback VideoFrameOutputCallback = undefined(VideoFrame output);
Internal Slots {#videodecoder-internal-slots}
---------------------------------------------
- [[codec implementation]]
- Underlying decoder implementation provided by the User Agent.
- [[output callback]]
- Callback given at construction for decoded outputs.
- [[error callback]]
- Callback given at construction for decode errors.
Constructors {#videodecoder-constructors}
-----------------------------------------
VideoDecoder(init)
1. Let d be a new VideoDecoder object.
2. Assign `init.output` to the {{VideoDecoder/[[output callback]]}} internal slot.
3. Assign `init.error` to the {{VideoDecoder/[[error callback]]}} internal slot.
4. Assign "unconfigured" to `d.state`.
5. Return d.
Attributes {#videodecoder-attributes}
-------------------------------------
-
state
- Describes the current state of the codec.
-
decodeQueueSize
-
The number of pending decode requests. This number will decrease as the
underlying codec is ready to accept new input.
Methods {#videodecoder-methods}
-------------------------------
- configure(config)
-
[=Enqueues a control message=] to configure the video decoder for decoding
chunks as described by |config|.
NOTE: Authors should first check support by calling
{{VideoDecoder/isConfigSupported()}} with |config| to avoid error paths
in the steps below.
When invoked, run these steps:
1. If |config| is not a [=valid VideoDecoderConfig=], throw a
{{TypeError}}.
2. If {{VideoDecoder/state}} is `“closed”`, throw an {{InvalidStateError}}.
3. Set {{VideoDecoder/state}} to `"configured"`.
4. [=Queue a control message=] to configure the decoder with |config|.
[=Running a control message=] to configure the decoder means running
these steps:
1. Let |supported| be the result of running the Check Configuration
Support algorith with |config|.
2. If |supported| is `true`, assign
{{VideoDecoder/[[codec implementation]]}} with an implementation
supporting |config|.
3. Otherwise, run the Close VideoDecoder algorithm with
{{NotSupportedError}}.
- decode(chunk)
-
[=Enqueues a control message=] to decode the given |chunk|.
When invoked, run these steps:
1. If {{VideoDecoder/state}} is not `"configured"`, throw an
{{InvalidStateError}}.
2. Increment {{VideoDecoder/decodeQueueSize}}.
3. [=Queue a control message=] to decode the |chunk|.
Running a control message to decode the chunk means performing these steps:
1. Attempt to use {{VideoDecoder/[[codec implementation]]}} to decode the
chunk.
2. If decoding results in an error, queue a task on the [=control thread=]
event loop to run the [=Close VideoDecoder=] algorithm with
{{EncodingError}}.
3. Queue a task on the [=control thread=] event loop to decrement
{{VideoDecoder/decodeQueueSize}}
4. Let |decoded outputs| be a [=list=] of decoded video data outputs emitted
by {{VideoDecoder/[[codec implementation]]}}.
5. If |decoded outputs| is not empty, queue a task on the [=control thread=]
event loop to run the [=Output VideoFrames=] algorithm with
|decoded outputs|.
- flush()
-
Completes all [=control messages=] in the [=control message queue=]
and emits all outputs.
When invoked, run these steps:
1. If {{VideoDecoder/state}} is not `"configured"`, return
[=a promise rejected with=] {{InvalidStateError}} {{DOMException}}.
2. Let |promise| be a new Promise.
3. [=Queue a control message=] to flush the codec with |promise|.
4. Return |promise|.
Running a control message to flush the codec means performing these steps
with |promise|.
1. Signal {{VideoDecoder/[[codec implementation]]}} to emit all [=internal
pending outputs=].
2. Let |decoded outputs| be a [=list=] of decoded video data outputs emitted
by {{VideoDecoder/[[codec implementation]]}}.
3. If |decoded outputs| is not empty, queue a task on the [=control thread=]
event loop to run the [=Output VideoFrames=] algorithm with
|decoded outputs|.
4. Queue a task on the [=control thread=] event loop to resolve |promise|.
- reset()
-
Immediately resets all state including configuration,
[=control messages=] in the [=control message queue=], and all pending
callbacks.
When invoked, run the [=Reset VideoDecoder=] algorithm.
- close()
-
Immediately aborts all pending work and releases [=system resources=].
Close is final.
When invoked, run the [=Close VideoDecoder=] algorithm.
- isConfigSupported(config)
-
Returns a promise indicating whether the provided |config| is supported by
the user agent.
NOTE: The returned {{VideoDecoderSupport}} {{VideoDecoderSupport/config}}
will contain only the dictionary members that user agent recognized.
Unrecognized dictionary memebers will be ignored. Authors may detect
unrecognized dictionary members by comparinging
{{VideoDecoderSupport/config}} to their provided |config|.
When invoked, run these steps:
1. If |config| is not a valid VideoDecoderConfig, return
[=a promise rejected with=] {{TypeError}}.
2. Let |p| be a new Promise.
3. Let |checkSupportQueue| be the result of starting a new parallel
queue.
4. Enqueue the following steps to |checkSupportQueue|:
1. Let |decoderSupport| be a newly constructed
{{VideoDecoderSupport}}, initialized as follows:
1. Set {{VideoDecoderSupport/config}} to the result of running the
Clone Configuration algorithm with |config|.
2. Set {{VideoDecoderSupport/supported}} to the result of running
the Check Configuration Support algorithm with |config|.
2. Resolve |p| with |decoderSupport|.
5. Return |p|.
Algorithms {#videodecoder-algorithms}
-------------------------------------
- Output VideoFrames (with |outputs|)
-
Run these steps:
1. For each |output| in |outputs|:
1. Let |planes| be a sequence of {{Plane}}s containing the decoded video
frame data from |output|.
2. Let |pixelFormat| be the {{PixelFormat}} of |planes|.
3. Let |frameInit| be a {{VideoFrameInit}} with the following keys:
1. Let {{VideoFrameInit/timestamp}} and {{VideoFrameInit/duration}}
be the {{EncodedVideoChunk/timestamp}} and
{{EncodedVideoChunk/duration}} from the {{EncodedVideoChunk}}
associated with |output|.
2. Let {{VideoFrameInit/codedWidth}} and
{{VideoFrameInit/codedHeight}}
be the width and height of the decoded video frame |output| in
pixels, prior to any cropping or aspect ratio adjustments.
3. Let {{VideoFrameInit/cropLeft}}, {{VideoFrameInit/cropTop}},
{{VideoFrameInit/cropWidth}}, and {{VideoFrameInit/cropHeight}}
be the crop region of the decoded video frame |output| in
pixels, prior to any aspect ratio adjustments.
4. Let {{VideoFrameInit/displayWidth}} and
{{VideoFrameInit/displayHeight}} be the display size of the
decoded video frame in pixels.
4. Let |frame| be a {{VideoFrame}}, constructed with |pixelFormat|,
|planes|, and |frameInit|.
5. Invoke {{VideoDecoder/[[output callback]]}} with |frame|.
- Reset VideoDecoder
-
Run these steps:
1. If {{VideoDecoder/state}} is `"closed"`, throw an {{InvalidStateError}}.
2. Set {{VideoDecoder/state}} to `"unconfigured"`.
3. Signal {{VideoDecoder/[[codec implementation]]}} to cease producing
output for the previous configuration.
4. [=Reset the control message queue=].
5. Set {{VideoDecoder/decodeQueueSize}} to zero.
- Close VideoDecoder (with |error|)
-
Run these steps:
1. Run the [=Reset VideoDecoder=] algorithm.
2. Set {{VideoDecoder/state}} to `"closed"`.
3. Clear {{VideoDecoder/[[codec implementation]]}} and release associated
[=system resources=].
4. If |error| is set, queue a task on the [=control thread=] event loop to
invoke the {{VideoDecoder/[[error callback]]}} with |error|.
AudioEncoder Interface {#audioencoder-interface}
================================================
[Exposed=(Window,DedicatedWorker)]
interface AudioEncoder {
constructor(AudioEncoderInit init);
readonly attribute CodecState state;
readonly attribute long encodeQueueSize;
undefined configure(AudioEncoderConfig config);
undefined encode(AudioFrame frame);
Promise flush();
undefined reset();
undefined close();
static Promise isConfigSupported(AudioEncoderConfig config);
};
dictionary AudioEncoderInit {
required EncodedAudioChunkOutputCallback output;
required WebCodecsErrorCallback error;
};
callback EncodedAudioChunkOutputCallback = undefined(EncodedAudioChunk output);
Internal Slots {#audioencoder-internal-slots}
---------------------------------------------
- [[codec implementation]]
- Underlying encoder implementation provided by the User Agent.
- [[output callback]]
- Callback given at construction for encoded outputs.
- [[error callback]]
- Callback given at construction for encode errors.
Constructors {#audioencoder-constructors}
-----------------------------------------
AudioEncoder(init)
1. Let e be a new AudioEncoder object.
2. Assign `init.output` to the {{AudioEncoder/[[output callback]]}} internal slot.
3. Assign `init.error` to the {{AudioEncoder/[[error callback]]}} internal slot.
4. Assign "unconfigured" to `e.state`.
5. Return e.
Attributes {#audioencoder-attributes}
-------------------------------------
-
state
- Describes the current state of the codec.
-
encodeQueueSize
-
The number of pending encode requests. This number will decrease as the
underlying codec is ready to accept new input.
Methods {#audioencoder-methods}
-------------------------------
- configure(config)
-
[=Enqueues a control message=] to configure the audio encoder for
decoding chunks as described by |config|.
NOTE: Authors should first check support by calling
{{AudioEncoder/isConfigSupported()}} with |config| to avoid error paths
in the steps below.
When invoked, run these steps:
1. If |config| is not a [=valid AudioEncoderConfig=], throw a
{{TypeError}}.
2. If {{AudioEncoder/state}} is `"closed"`, throw an {{InvalidStateError}}.
3. Set {{AudioEncoder/state}} to `"configured"`.
4. [=Queue a control message=] to configure the encoder using |config|.
Running a control message to configure the encoder means performing these
steps:
1. Let |supported| be the result of running the Check Configuration
Support algorith with |config|.
2. If |supported| is `true`, assign
{{AudioEncoder/[[codec implementation]]}} with an implementation
supporting |config|.
3. Otherwise, run the Close AudioEncoder algorithm with
{{NotSupportedError}}.
- encode(frame)
-
[=Enqueues a control message=] to encode the given |frame|.
NOTE: This method will destroy the AudioFrame. Authors who wish to retain a
copy, should call `frame.clone()` prior to calling encode().
When invoked, run these steps:
1. If the value of |frame|'s {{AudioFrame/[[detached]]}} internal slot is
`true`, throw a {{TypeError}}.
2. If {{AudioEncoder/state}} is not `"configured"`, throw an
{{InvalidStateError}}.
3. Let |frameClone| hold the result of running the [=Clone Frame=]
algorithm with |frame|.
4. Destroy the original |frame| by invoking `frame.destroy()`.
5. Increment {{AudioEncoder/encodeQueueSize}}.
6. [=Queue a control message=] to encode |frameClone|.
Running a control message to encode the frame means performing these steps.
1. Attempt to use {{AudioEncoder/[[codec implementation]]}} to encode
|frameClone|.
2. If encoding results in an error, queue a task on the [=control thread=]
event loop to run the [=Close AudioEncoder=] algorithm with
{{EncodingError}}.
3. Queue a task on the [=control thread=] event loop to decrement
{{AudioEncoder/encodeQueueSize}}.
4. Let |encoded outputs| be a [=list=] of encoded audio data outputs
emitted by {{AudioEncoder/[[codec implementation]]}}.
5. If |encoded outputs| is not empty, queue a task on the [=control thread=]
event loop to run the [=Output EncodedAudioChunks=] algorithm with
|encoded outputs|.
- flush()
-
Completes all [=control messages=] in the [=control message queue=]
and emits all outputs.
When invoked, run these steps:
1. If {{AudioEncoder/state}} is not `"configured"`, return
[=a promise rejected with=] {{InvalidStateError}} {{DOMException}}.
2. Let |promise| be a new Promise.
3. [=Queue a control message=] to flush the codec with |promise|.
4. Return |promise|.
Running a control message to flush the codec means performing these steps
with |promise|.
1. Signal {{AudioEncoder/[[codec implementation]]}} to emit all [=internal
pending outputs=].
2. Let |encoded outputs| be a [=list=] of encoded audio data outputs
emitted by {{AudioEncoder/[[codec implementation]]}}.
5. If |encoded outputs| is not empty, queue a task on the [=control thread=]
event loop to run the [=Output EncodedAudioChunks=] algorithm with
|encoded outputs|.
3. Queue a task on the [=control thread=] event loop to resolve |promise|.
- reset()
-
Immediately resets all state including configuration,
[=control messages=] in the [=control message queue=], and all pending
callbacks.
When invoked, run the [=Reset AudioEncoder=] algorithm.
- close()
-
Immediately aborts all pending work and releases [=system resources=].
Close is final.
When invoked, run the [=Close AudioEncoder=] algorithm.
- isConfigSupported(config)
-
Returns a promise indicating whether the provided |config| is supported by
the user agent.
NOTE: The returned {{AudioEncoderSupport}} {{AudioEncoderSupport/config}}
will contain only the dictionary members that user agent recognized.
Unrecognized dictionary memebers will be ignored. Authors may detect
unrecognized dictionary members by comparinging
{{AudioEncoderSupport/config}} to their provided |config|.
When invoked, run these steps:
1. If |config| is not a valid AudioEncoderConfig, return
[=a promise rejected with=] {{TypeError}}.
2. Let |p| be a new Promise.
3. Let |checkSupportQueue| be the result of starting a new parallel
queue.
4. Enqueue the following steps to |checkSupportQueue|:
1. Let |encoderSupport| be a newly constructed
{{AudioEncoderSupport}}, initialized as follows:
1. Set {{AudioEncoderSupport/config}} to the result of running the
Clone Configuration algorithm with |config|.
2. Set {{AudioEncoderSupport/supported}} to the result of running
the Check Configuration Support algorithm with |config|.
2. Resolve |p| with |encoderSupport|.
5. Return |p|.
Algorithms {#audioencoder-algorithms}
-------------------------------------
- Output EncodedAudioChunks (with |outputs|)
-
Run these steps:
1. For each |output| in |outputs|:
1. Let |chunkInit| be an {{EncodedAudioChunkInit}} with the following
keys:
1. Let {{EncodedAudioChunkInit/data}} contain the encoded audio data
from |output|.
2. Let {{EncodedAudioChunkInit/type}} be the
{{EncodedAudioChunkType}} of |output|.
3. Let {{EncodedAudioChunkInit/timestamp}} be the
{{AudioFrame/timestamp}} from the AudioFrame associated with
|output|.
2. Let |chunk| be a new {{EncodedAudioChunk}} constructed with
|chunkInit|.
3. Invoke {{AudioEncoder/[[output callback]]}} with |chunk|.
- Reset AudioEncoder
-
Run these steps:
1. If {{AudioEncoder/state}} is `"closed"`, throw an {{InvalidStateError}}.
2. Set {{AudioEncoder/state}} to `"unconfigured"`.
3. Signal {{AudioEncoder/[[codec implementation]]}} to cease producing
output for the previous configuration.
4. [=Reset the control message queue=].
5. Set {{AudioEncoder/encodeQueueSize}} to zero.
- Close AudioEncoder (with |error|)
-
Run these steps:
1. Run the [=Reset AudioEncoder=] algorithm.
2. Set {{AudioEncoder/state}} to `"closed"`.
3. Clear {{AudioEncoder/[[codec implementation]]}} and release associated
[=system resources=].
4. If |error| is set, queue a task on the [=control thread=] event loop
invoke the {{AudioEncoder/[[error callback]]}} with |error|.
VideoEncoder Interface {#videoencoder-interface}
================================================
[Exposed=(Window,DedicatedWorker)]
interface VideoEncoder {
constructor(VideoEncoderInit init);
readonly attribute CodecState state;
readonly attribute long encodeQueueSize;
undefined configure(VideoEncoderConfig config);
undefined encode(VideoFrame frame, optional VideoEncoderEncodeOptions options = {});
Promise flush();
undefined reset();
undefined close();
static Promise isConfigSupported(VideoEncoderConfig config);
};
dictionary VideoEncoderInit {
required EncodedVideoChunkOutputCallback output;
required WebCodecsErrorCallback error;
};
callback EncodedVideoChunkOutputCallback = undefined(EncodedVideoChunk output, VideoDecoderConfig? output_config);
Internal Slots {#videoencoder-internal-slots}
---------------------------------------------
- [[codec implementation]]
- Underlying encoder implementation provided by the User Agent.
- [[output callback]]
- Callback given at construction for encoded outputs.
- [[error callback]]
- Callback given at construction for encode errors.
- [[active encoder config]]
- The {{VideoEncoderConfig}} that is actively applied.
- [[active output config]]
-
The {{VideoDecoderConfig}} that describes how to decode the most recently
emitted {{EncodedVideoChunk}}.
Constructors {#videoencoder-constructors}
-----------------------------------------
VideoEncoder(init)
1. Let e be a new VideoEncoder object.
2. Assign `init.output` to the {{VideoEncoder/[[output callback]]}} internal slot.
3. Assign `init.error` to the {{VideoEncoder/[[error callback]]}} internal slot.
4. Assign "unconfigured" to `e.state`.
5. Return e.
Attributes {#videoencoder-attributes}
-------------------------------------
-
state
- Describes the current state of the codec.
-
encodeQueueSize
-
The number of pending encode requests. This number will decrease as the
underlying codec is ready to accept new input.
Methods {#videoencoder-methods}
-------------------------------
- configure(config)
-
[=Enqueues a control message=] to configure the video encoder for
decoding chunks as described by |config|.
NOTE: Authors should first check support by calling
{{VideoEncoder/isConfigSupported()}} with |config| to avoid error paths
in the steps below.
When invoked, run these steps:
1. If |config| is not a [=valid VideoEncoderConfig=], throw a
{{TypeError}}.
2. If {{VideoEncoder/state}} is `"closed"`, throw an {{InvalidStateError}}.
3. Set {{VideoEncoder/state}} to `"configured"`.
4. [=Queue a control message=] to configure the encoder using |config|.
Running a control message to configure the encoder means performing these
steps:
1. Let |supported| be the result of running the Check Configuration
Support algorith with |config|.
2. If |supported| is `true`, assign
{{VideoEncoder/[[codec implementation]]}} with an implementation
supporting |config|.
3. Otherwise, run the Close VideoEncoder algorithm with
{{NotSupportedError}} and abort these steps.
2. Set {{VideoEncoder/[[active encoder config]]}} to `config`.
- encode(frame, options)
-
[=Enqueues a control message=] to encode the given |frame|.
NOTE: This method will destroy the VideoFrame. Authors who wish to retain a
copy, should call `frame.clone()` prior to calling encode().
When invoked, run these steps:
1. If the value of |frame|'s {{VideoFrame/[[detached]]}} internal slot is
`true`, throw a {{TypeError}}.
2. If {{VideoEncoder/state}} is not `"configured"`, throw an
{{InvalidStateError}}.
3. Let |frameClone| hold the result of running the [=Clone Frame=]
algorithm with |frame|.
4. Destroy the original |frame| by invoking `frame.destroy()`.
5. Increment {{VideoEncoder/encodeQueueSize}}.
6. [=Queue a control message=] to encode |frameClone|.
Running a control message to encode the frame means performing these steps.
1. Attempt to use {{VideoEncoder/[[codec implementation]]}} to encode
|frameClone| according to |options|.
2. If encoding results in an error, queue a task on the [=control thread=]
event loop to run the [=Close VideoEncoder=] algorithm with
{{EncodingError}}.
3. Queue a task on the [=control thread=] event loop to decrement
{{VideoEncoder/encodeQueueSize}}.
4. Let |encoded outputs| be a [=list=] of encoded video data outputs
emitted by {{VideoEncoder/[[codec implementation]]}}.
5. If |encoded outputs| is not empty, queue a task on the [=control thread=]
event loop to run the [=Output EncodedVideoChunks=] algorithm with
|encoded outputs|.
- flush()
-
Completes all [=control messages=] in the [=control message queue=]
and emits all outputs.
When invoked, run these steps:
1. If {{VideoEncoder/state}} is not `"configured"`, return
[=a promise rejected with=] {{InvalidStateError}} {{DOMException}}.
2. Let |promise| be a new Promise.
3. [=Queue a control message=] to flush the codec with |promise|.
4. Return |promise|.
Running a control message to flush the codec means performing these steps
with |promise|.
1. Signal {{VideoEncoder/[[codec implementation]]}} to emit all [=internal
pending outputs=].
2. Let |encoded outputs| be a [=list=] of encoded video data outputs
emitted by {{VideoEncoder/[[codec implementation]]}}.
5. If |encoded outputs| is not empty, queue a task on the [=control thread=]
event loop to run the [=Output EncodedVideoChunks=] algorithm with
|encoded outputs|.
3. Queue a task on the [=control thread=] event loop to resolve |promise|.
- reset()
-
Immediately resets all state including configuration,
[=control messages=] in the [=control message queue=], and all pending
callbacks.
When invoked, run the [=Reset VideoEncoder=] algorithm.
- close()
-
Immediately aborts all pending work and releases [=system resources=].
Close is final.
When invoked, run the [=Close VideoEncoder=] algorithm.
- isConfigSupported(config)
-
Returns a promise indicating whether the provided |config| is supported by
the user agent.
NOTE: The returned {{VideoEncoderSupport}} {{VideoEncoderSupport/config}}
will contain only the dictionary members that user agent recognized.
Unrecognized dictionary memebers will be ignored. Authors may detect
unrecognized dictionary members by comparinging
{{VideoEncoderSupport/config}} to their provided |config|.
When invoked, run these steps:
1. If |config| is not a valid VideoEncoderConfig, return
[=a promise rejected with=] {{TypeError}}.
2. Let |p| be a new Promise.
3. Let |checkSupportQueue| be the result of starting a new parallel
queue.
4. Enqueue the following steps to |checkSupportQueue|:
1. Let |encoderSupport| be a newly constructed
{{VideoEncoderSupport}}, initialized as follows:
1. Set {{VideoEncoderSupport/config}} to the result of running the
Clone Configuration algorithm with |config|.
2. Set {{VideoEncoderSupport/supported}} to the result of running
the Check Configuration Support algorithm with |config|.
2. Resolve |p| with |encoderSupport|.
5. Return |p|.
Algorithms {#videoencoder-algorithms}
-------------------------------------
- Output EncodedVideoChunks (with |outputs|)
-
Run these steps:
1. For each |output| in |outputs|:
1. Let |encoder_config| be the
{{VideoEncoder/[[active encoder config]]}}.
ISSUE: The intent is for |encoder_config| to be the
{{VideoEncoder/[[active encoder config]]}} that was used to
encode |output|. But, as written, it may occur that |output| was
encoded using a previous {{VideoEncoderConfig}} that has since
been replaced by a later call to {{VideoEncoder/configure()}}.
See [#138](https://github.com/WICG/web-codecs/issues/138).
2. Let |output_config| be a {{VideoDecoderConfig}} that describes
|output|. Initialize |output_config| as follows:
1. Assign `encoder_config.codec` to `output_config.codec`.
2. Assign `encoder_config.cropWidth` to `output_config.cropWidth`.
3. Assign `encoder_config.cropHeight` to `output_config.cropHeight`.
4. Assign `encoder_config.displayWidth` to
`output_config.displayWidth`.
5. Assign `encoder_config.displayHeight` to
`output_config.displayHeight`.
6. Assign the remaining keys of `output_config` as determined by
{{VideoEncoder/[[codec implementation]]}}. The user agent
must ensure that the configuration is completely described
such that |output_config| could be used to correctly decode
|output|.
NOTE: This includes supplying the
{{VideoDecoderConfig/description}} to describe codec
specific "extradata" like the avcC bytes for AVC.
3. If |output_config| and {{VideoEncoder/[[active output config]]}} are
equal dictionaries, set |output_config| to null. Otherwise,
set {{VideoEncoder/[[active output config]]}} to |output_config|.
NOTE: The {{VideoDecoderConfig}} |output_config| will be `null`
if the configuration hasn't changed from previous outputs. The
first output will always include a non-null |output_config|.
4. Let |chunkInit| be an {{EncodedVideoChunkInit}} with the following
keys:
1. Let {{EncodedVideoChunkInit/data}} contain the encoded video data
from |output|.
2. Let {{EncodedVideoChunkInit/type}} be the
{{EncodedVideoChunkType}} of |output|.
3. Let {{EncodedVideoChunkInit/timestamp}} be the
{{VideoFrame/timestamp}} from the {{VideoFrame}} associated with
|output|.
4. Let {{EncodedVideoChunkInit/duration}} be the
{{VideoFrame/duration}} from the {{VideoFrame}} associated with
|output|.
5. Let |chunk| be a new {{EncodedVideoChunk}} constructed with
|chunkInit|.
6. Invoke {{VideoEncoder/[[output callback]]}} with |chunk|.
- Reset VideoEncoder
-
Run these steps:
1. If {{VideoEncoder/state}} is `"closed"`, throw an {{InvalidStateError}}.
2. Set {{VideoEncoder/state}} to `"unconfigured"`.
3. Set {{VideoEncoder/[[active encoder config]]}} to `null`.
4. Set {{VideoEncoder/[[active output config]]}} to `null`.
5. Signal {{VideoEncoder/[[codec implementation]]}} to cease producing
output for the previous configuration.
6. [=Reset the control message queue=].
7. Set {{VideoEncoder/encodeQueueSize}} to zero.
- Close VideoEncoder (with |error|)
-
Run these steps:
1. Run the [=Reset VideoEncoder=] algorithm.
2. Set {{VideoEncoder/state}} to `"closed"`.
3. Clear {{VideoEncoder/[[codec implementation]]}} and release associated
[=system resources=].
4. If |error| is set, queue a task on the [=control thread=] event loop
invoke the {{VideoEncoder/[[error callback]]}} with |error|.
Configurations{#configurations}
===============================
Check Configuration Support (with |config|) {#config-support}
------------------------------------------------------------------------
Run these steps:
1. If the user agent can provide a codec to support all entries of the
|config|, including applicable default values for keys that are not
included, return `true`.
NOTE: The types {{AudioDecoderConfig}}, {{VideoDecoderConfig}},
{{AudioEncoderConfig}}, and {{VideoEncoderConfig}} each define their
respective configuration entries and defaults.
NOTE: Support for a given configuration may change dynamically if the
hardware is altered (e.g. external GPU unplugged) or if required
hardware resources are exhausted. User agents should describe support on
a best-effort basis given the resources that are available at the time
of the query.
2. Otherwise, return false.
Clone Configuration (with |config|) {#clone-config}
--------------------------------------------------------------
NOTE: This algorithm will copy only the dictionary members that the user agent
recognizes as part of the dictionary type.
Run these steps:
1. Let |dictType| be the type of dictionary |config|.
2. Let clone be a new empty instance of |dictType|.
3. For each dictionary member |m| defined on |dictType|:
1. If |m| does not [=map/exist=] in |config|, then [=iteration/continue=].
2. If `config[m]` is a nested dictionary, set `clone[m]` to the result of
recursively running the Clone Configuration algorithm with
`config[m]`.
3. Otherwise, assign the value of `config[m]` to `clone[m]`.
Signalling Configuration Support{#config-support-info}
------------------------------------------------------
### AudioDecoderSupport ### {#audio-decoder-support}
dictionary AudioDecoderSupport {
boolean supported;
AudioDecoderConfig config;
};
- supported
-
A boolean indicating the whether the corresponding
{{AudioDecoderSupport/config}} is supported by the user agent.
- config
-
An {{AudioDecoderConfig}} used by the user agent in determining the value of
{{AudioDecoderSupport/supported}}.
### VideoDecoderSupport ### {#video-decoder-support}
dictionary VideoDecoderSupport {
boolean supported;
VideoDecoderConfig config;
};
- supported
-
A boolean indicating the whether the corresponding
{{VideoDecoderSupport/config}} is supported by the user agent.
- config
-
A {{VideoDecoderConfig}} used by the user agent in determining the value of
{{VideoDecoderSupport/supported}}.
### AudioEncoderSupport ### {#audio-encoder-support}
dictionary AudioEncoderSupport {
boolean supported;
AudioEncoderConfig config;
};
- supported
-
A boolean indicating the whether the corresponding
{{AudioEncoderSupport/config}} is supported by the user agent.
- config
-
An {{AudioEncoderConfig}} used by the user agent in determining the value of
{{AudioEncoderSupport/supported}}.
### VideoEncoderSupport ### {#video-encoder-support}
dictionary VideoEncoderSupport {
boolean supported;
VideoEncoderConfig config;
};
- supported
-
A boolean indicating the whether the corresponding
{{VideoEncoderSupport/config}} is supported by the user agent.
- config
-
A {{VideoEncoderConfig}} used by the user agent in determining the value of
{{VideoEncoderSupport/supported}}.
Codec String{#config-codec-string}
----------------------------------------------------
In other media specifications, codec strings historically accompanied a
[=MIME type=] as the "codecs=" parameter
({{MediaSource/isTypeSupported()}}, {{HTMLMediaElement/canPlayType()}})
[[RFC6381]]. In this specification, encoded media is not containerized; hence,
only the value of the codecs parameter is accepted.
A valid codec string must meet the following conditions.
1. Is valid per the relevant codec specification (see examples below).
2. It describes a single codec.
NOTE: Not a comma separated list.
3. It is unambiguous about codec profile and level for codecs that define these
concepts.
Valid examples include:
* 'vp8'
* 'vp<IP_ADDRESS>'
* 'avc1.4D401E',
* 'opus',
* 'mp4a.40.2',
* 'flac'
Invalid examples include:
* 'video/webm; codecs="vp8"' (invalid to supply full mimetype; valid as just
'vp8')
* 'codecs="opus"' (invalid to include codecs= prefix)
* ‘flac,vorbis’ (describes more than one codec)
* ‘vp9’ (ambiguous about profile and level)
* 'video/mp4' (describes a container, not a codec)
AudioDecoderConfig{#audio-decoder-config}
-----------------------------------------
dictionary AudioDecoderConfig {
required DOMString codec;
required unsigned long sampleRate;
required unsigned long numberOfChannels;
BufferSource description;
};
To check if an {{AudioDecoderConfig}} is a valid AudioDecoderConfig,
run these steps:
1. If codec is not a valid codec string, return `false`.
2. Return `true`.
- codec
- Contains a codec string describing the codec.
- sampleRate
- The number of frame samples per second.
- numberOfChannels
- The number of audio channels.
- description
-
A sequence of codec specific bytes, commonly known as extradata.
NOTE: For example, the vorbis "code book".
VideoDecoderConfig{#video-decoder-config}
-----------------------------------------
dictionary VideoDecoderConfig {
required DOMString codec;
BufferSource description;
required unsigned long codedWidth;
required unsigned long codedHeight;
unsigned long cropLeft;
unsigned long cropTop;
unsigned long cropWidth;
unsigned long cropHeight;
unsigned long displayWidth;
unsigned long displayHeight;
HardwareAcceleration hardwareAcceleration = "allow";
};
To check if a {{VideoDecoderConfig}} is a valid VideoDecoderConfig,
run these steps:
1. If {{VideoDecoderConfig/codec}} is not a valid codec string, return
`false`.
2. If {{VideoDecoderConfig/codedWidth}} = 0 or
{{VideoDecoderConfig/codedHeight}} = 0, return `false`.
3. If {{VideoDecoderConfig/cropWidth}} = 0 or {{VideoDecoderConfig/cropHeight}}
= 0, return `false`.
4. If {{VideoDecoderConfig/cropTop}} + {{VideoDecoderConfig/cropHeight}} >=
{{VideoDecoderConfig/codedHeight}}, return `false`.
5. If {{VideoDecoderConfig/cropLeft}} + {{VideoDecoderConfig/cropWidth}} >=
{{VideoDecoderConfig/codedWidth}}, return `false`.
6. If {{VideoDecoderConfig/displayWidth}} = 0 or
{{VideoDecoderConfig/displayHeight}} = 0, return `false`.
7. Return `true`.
- codec
- Contains a codec string describing the codec.
- description
-
A sequence of codec specific bytes, commonly known as extradata.
NOTE: Examples include the VP9 vpcC bytes or the AVC avcC bytes.
- codedWidth
-
Width of the VideoFrame in pixels, prior to any cropping or aspect ratio
adjustments.
- codedHeight
-
Height of the VideoFrame in pixels, prior to any cropping or aspect ratio
adjustments.
- cropLeft
-
The number of pixels to remove from the left of the VideoFrame, prior to
aspect ratio adjustments. Defaults to zero if not present.
- cropTop
-
The number of pixels to remove from the top of the VideoFrame, prior to
aspect ratio adjustments. Defaults to zero if not present.
- cropWidth
-
The width in pixels to include in the crop, starting from cropLeft.
Defaults to codedWidth if not present.
- cropHeight
-
The height in pixels to include in the crop, starting from cropLeft.
Defaults to codedHeight if not present.
- displayWidth
-
Width of the VideoFrame when displayed. Defaults to cropWidth if not
present.
- displayHeight
-
Height of the VideoFrame when displayed. Defaults to cropHeight if not
present.
- hardwareAcceleration
-
Configures hardware acceleration for this codec. See
{{HardwareAcceleration}}.
AudioEncoderConfig{#audio-encoder-config}
-----------------------------------------
dictionary AudioEncoderConfig {
required DOMString codec;
unsigned long sampleRate;
unsigned long numberOfChannels;
};
To check if an {{AudioEncoderConfig}} is a valid AudioEncoderConfig,
run these steps:
1. If {{AudioEncoderConfig/codec}} is not a valid codec string, return
`false`.
2. Return `true`.
- codec
- Contains a codec string describing the codec.
- sampleRate
- The number of frame samples per second.
- numberOfChannels
- The number of audio channels.
VideoEncoderConfig{#video-encoder-config}
-----------------------------------------
dictionary VideoEncoderConfig {
required DOMString codec;
unsigned long long bitrate;
required unsigned long cropWidth;
required unsigned long cropHeight;
unsigned long displayWidth;
unsigned long displayHeight;
HardwareAcceleration hardwareAcceleration = "allow";
AvcEncoderConfig avc;
};
To check if a {{VideoEncoderConfig}} is a valid VideoEncoderConfig,
run these steps:
1. If {{VideoEncoderConfig/codec}} is not a valid codec string, return
`false`.
2. If {{VideoEncoderConfig/cropWidth}} = 0 or {{VideoEncoderConfig/cropHeight}}
= 0, return `false`.
3. If {{VideoEncoderConfig/displayWidth}} = 0 or
{{VideoEncoderConfig/displayHeight}} = 0, return `false`.
4. If {{VideoEncoderConfig/avc}} is present, but {{VideoEncoderConfig/codec}}
does not describe the AVC codec, per [[RFC6381]], return `false`.
4. Return `true`.
- codec
- Contains a codec string describing the codec.
- bitrate
- The average bitrate of the encoded video given in units of bits per second.
- cropWidth
-
The encoded width of output {{EncodedVideoChunk}}s in pixels, prior to any
display aspect ratio adjustments.
The encoder must scale any {{VideoFrame}} who's {{VideoFrame/cropWidth}}
differs from this value.
- cropHeight
-
The encoded height of output {{EncodedVideoChunk}}s in pixels, prior to any
display aspect ratio adjustments.
The encoder must scale any {{VideoFrame}} who's {{VideoFrame/cropHeight}}
differs from this value.
NOTE: The {{VideoEncoder}} will scale, not crop, input {{VideoFrame}}s to the
specified {{VideoEncoderConfig/cropWidth}} and
{{VideoEncoderConfig/cropHeight}}.
The naming of {{VideoEncoderConfig/cropWidth}} and
{{VideoEncoderConfig/cropHeight}} reflects that the encoded chunks may be
decoded to produce {{VideoFrame}}s who's {{VideoFrame/cropWidth}}
and {{VideoFrame/cropHeight}} will match these values.
- displayWidth
-
The intended display width of output {{EncodedVideoChunk}}s in pixels.
Defaults to {{VideoEncoderConfig/cropWidth}} if not present.
- displayHeight
-
The intended display height of output {{EncodedVideoChunk}}s in pixels.
Defaults to {{VideoEncoderConfig/cropWidth}} if not present.
NOTE: Providing a {{VideoEncoderConfig/displayWidth}} or
{{VideoEncoderConfig/displayHeight}} that differs from the crop dimensions
signals that chunks should be scaled after decoding to arrive at the final
display aspect ratio.
For many codecs this is merely pass-through information, but some codecs
may optionally include display sizing in the bitstream.
- avc
- Contains codec specific configuration options for the AVC (H.264) codec.
- hardwareAcceleration
-
Configures hardware acceleration for this codec. See
{{HardwareAcceleration}}.
### AvcEncoderConfig ### {#avc-encoder-config}
dictionary AvcEncoderConfig {
AvcBitstreamFormat format = "avc";
};
- format
-
Configures the format of output AVC {{EncodedVideoChunk}}s. See
{{AvcBitstreamFormat}}.
#### AvcBitstreamFormat #### {#avc-bitstream-format}
enum AvcBitstreamFormat {
"annexb",
"avc",
};
The {{AvcBitstreamFormat}} determines the location of Sequence Parameter
Set (SPS) and Picture Parameter Set (PPS) data, and mechanisms for
packaging the bitstream.
- annexb
-
This format is as described by [[!iso14496-10]], Annex B. Notably,
SPS and PPS data are included periodically throughout the
bitstream.
NOTE: This format is commonly used in live-streaming applications, where
including the SPS and PPS data periodically allows users to easily start
from the middle of the stream.
- avc
-
This format is as described by [[!iso14496-15]], Section 5. Notably,
SPS and PPS data are not included in the bitstream and are
instead passed out of band as a AVCDecoderConfigurationRecord as defined by
[[!iso14496-15]]. This structure is emitted via the
{{VideoEncoder/[[output callback]]}} as the
{{VideoDecoderConfig/description}} of the {{VideoDecoderConfig}}
|output_config|.
NOTE: This format is commonly used in .MP4 files, where the player generally
has random access to the media data.
Hardware Acceleration{#hardware-acceleration}
---------------------------------------------
enum HardwareAcceleration {
"allow",
"deny",
"require",
};
When supported, hardware acceleration offloads encoding or decoding to
specialized hardware.
NOTE: Most authors will be best served by using the default of
{{HardwareAcceleration/allow}}. This gives the user agent flexibility to
optimize based on its knowledge of the system and configuration. A common
strategy will be to prioritize hardware acceleration at higher resolutions
with a fallback to software codecs if hardware acceleration fails.
Authors should carefully weigh the tradeoffs setting a hardware acceleration
preference. The precise trade-offs will be device-specific, but authors should
generally expect the following:
* Setting a value of {{HardwareAcceleration/require}} may significantly
restrict what configurations are supported. It may occur that the user's
device does not offer acceleration for any codec, or only for the most
common profiles of older codecs.
* Hardware acceleration does not simply imply faster encoding / decoding.
Hardware acceleration often has higher startup latency but more consistent
throughput performance. Acceleration will generally reduce CPU load.
* For decoding, hardware acceleration is often less robust to inputs that are
mislabeled or violate the relevant codec specification.
* Hardware acceleration will often be more power efficient than purely
software based codecs.
* For lower resolution content, the overhead added by hardware acceleration
may yield decreased performance and power efficiency compared to purely
software based codecs.
Given these tradeoffs, a good example of using "require" would be if an author
intends to provide their own software based fallback via WebAssembly.
Alternatively, a good example of using "disallow" would be if an author is
especially sensitive to the higher startup latency or decreased robustness
generally associated with hardware acceleration.
- allow
-
Indicates that the user agent may use hardware acceleration if it is
available and compatible with other aspects of the codec configuration.
- deny
-
Indicates that the user agent must not use hardware acceleration.
NOTE: This will cause the configuration to be unsupported on platforms where
an unaccelerated codec is unavailable or is incompatible with other aspects
of the codec configuration.
- require
-
Indicates that the user agent must use hardware acceleration.
NOTE: This will cause the configuration to be unsupported on platforms where
an accelerated codec is unavailable or is incompatible with other aspects of
the codec configuration.
Configuration Equivalence{#config-equivalence}
----------------------------------------------
Two dictionaries are equal dictionaries if they contain the same
keys and values. For nested dictionaries, apply this definition recursively.
VideoEncoderEncodeOptions{#video-encoder-options}
-------------------------------------------------
dictionary VideoEncoderEncodeOptions {
boolean keyFrame = false;
};
- keyFrame
-
A value of `true` indicates that the given frame MUST be encoded as a key
frame. A value of `false` indicates that the user agent has flexibility to
decide whether the frame will be encoded as a key frame.
CodecState{#codec-state}
------------------------
enum CodecState {
"unconfigured",
"configured",
"closed"
};
- unconfigured
- The codec is not configured for encoding or decoding.
- configured
-
A valid configuration has been provided. The codec is ready for encoding or
decoding.
- closed
-
The codec is no longer usable and underlying [=system resources=] have
been released.
WebCodecsErrorCallback{#error-callback}
---------------------------------------
callback WebCodecsErrorCallback = undefined(DOMException error);
Encoded Media Interfaces (Chunks) {#encoded-media-interfaces}
=============================================================
These interfaces represent chunks of encoded media.
EncodedAudioChunk Interface {#encodedaudiochunk-interface}
------------------------------------------------------------
[Exposed=(Window,DedicatedWorker)]
interface EncodedAudioChunk {
constructor(EncodedAudioChunkInit init);
readonly attribute EncodedAudioChunkType type;
readonly attribute unsigned long long timestamp; // microseconds
readonly attribute ArrayBuffer data;
};
dictionary EncodedAudioChunkInit {
required EncodedAudioChunkType type;
required unsigned long long timestamp;
required BufferSource data;
};
enum EncodedAudioChunkType {
"key",
"delta",
};
### Constructors ###{#encodedaudiochunk-constructors}
EncodedAudioChunk(init)
1. Let |chunk| be a new {{EncodedAudioChunk}} object, initialized as follows
1. Assign `init.type` to `chunk.type`.
2. Assign `init.timestamp` to `chunk.timestamp`.
3. Assign a copy of `init.data` to `chunk.data`.
5. Return |chunk|.
### Attributes ###{#encodedaudiochunk-attributes}
- type
- Describes whether the chunk is a key frame.
- timestamp
- The presentation timestamp, given in microseconds.
- data
- A sequence of bytes containing encoded audio data.
EncodedVideoChunk Interface{#encodedvideochunk-interface}
-----------------------------------------------------------
[Exposed=(Window,DedicatedWorker)]
interface EncodedVideoChunk {
constructor(EncodedVideoChunkInit init);
readonly attribute EncodedVideoChunkType type;
readonly attribute unsigned long long timestamp; // microseconds
readonly attribute unsigned long long? duration; // microseconds
readonly attribute ArrayBuffer data;
};
dictionary EncodedVideoChunkInit {
required EncodedVideoChunkType type;
required unsigned long long timestamp;
unsigned long long duration;
required BufferSource data;
};
enum EncodedVideoChunkType {
"key",
"delta",
};
### Constructors ###{#encodedvideochunk-constructors}
EncodedVideoChunk(init)
1. Let |chunk| be a new {{EncodedVideoChunk}} object, initialized as follows
1. Assign `init.type` to `chunk.type`.
2. Assign `init.timestamp` to `chunk.timestamp`.
3. If duration is present in init, assign `init.duration` to
`chunk.duration`. Otherwise, assign null to `chunk.duration`.
2. Assign a copy of `init.data` to `chunk.data`.
3. Return |chunk|.
### Attributes ###{#encodedvideochunk-attributes}
- type
- Describes whether the chunk is a key frame or not.
- timestamp
- The presentation timestamp, given in microseconds.
- duration
- The presentation duration, given in microseconds.
- data
- A sequence of bytes containing encoded video data.
Raw Media Interfaces (Frames){#raw-media-interfaces}
====================================================
These interfaces represent unencoded (raw) media.
AudioFrame Interface {#audioframe-interface}
---------------------------------------------
[Exposed=(Window,DedicatedWorker)]
interface AudioFrame {
constructor(AudioFrameInit init);
readonly attribute unsigned long long timestamp;
readonly attribute AudioBuffer? buffer;
undefined close();
};
dictionary AudioFrameInit {
required unsigned long long timestamp;
required AudioBuffer buffer;
};
### Internal Slots ###{#audioframe-internal-slots}
- \[[detached]]
-
Boolean indicating whether close() was invoked and underlying resources
have been released.
### Constructors ###{#audioframe-constructors}
AudioFrame(init)
1. Let |frame| be a new {{AudioFrame}} object.
2. Assign `init.timestamp` to `frame.timestamp`.
3. Assign `init.buffer` to `frame.buffer`.
4. Assign `false` to the {{AudioFrame/[[detached]]}} internal slot.
5. Return |frame|.
### Attributes ###{#audioframe-attributes}
- timestamp
- The presentation timestamp, given in microseconds.
- buffer
- The buffer containing decoded audio data.
### Methods ###{#audioframe-methods}
- close()
-
Immediately frees [=system resources=]. When invoked, run these steps:
1. Release [=system resources=] for buffer and set its value to null.
2. Assign `true` to the {{AudioFrame/[[detached]]}} internal slot.
NOTE: This section needs work. We should use the name and semantics of
VideoFrame destroy(). Similarly, we should add clone() to make a deep
copy.
VideoFrame Interface {#videoframe-interface}
--------------------------------------------
[Exposed=(Window,DedicatedWorker)]
interface VideoFrame {
constructor(ImageBitmap imageBitmap, optional VideoFrameInit frameInit = {});
constructor(PixelFormat pixelFormat, sequence<(Plane or PlaneInit)> planes,
optional VideoFrameInit frameInit = {});
readonly attribute PixelFormat format;
readonly attribute FrozenArray planes;
readonly attribute unsigned long codedWidth;
readonly attribute unsigned long codedHeight;
readonly attribute unsigned long cropLeft;
readonly attribute unsigned long cropTop;
readonly attribute unsigned long cropWidth;
readonly attribute unsigned long cropHeight;
readonly attribute unsigned long displayWidth;
readonly attribute unsigned long displayHeight;
readonly attribute unsigned long long? duration;
readonly attribute unsigned long long? timestamp;
undefined destroy();
VideoFrame clone();
Promise createImageBitmap(
optional ImageBitmapOptions options = {});
};
dictionary VideoFrameInit {
unsigned long codedWidth;
unsigned long codedHeight;
unsigned long cropLeft;
unsigned long cropTop;
unsigned long cropWidth;
unsigned long cropHeight;
unsigned long displayWidth;
unsigned long displayHeight;
unsigned long long duration;
unsigned long long timestamp;
};
### Internal Slots ###{#videoframe-internal-slots}
- \[[detached]]
-
Boolean indicating whether {{destroy()}} was invoked and underlying
resources have been released.
### Constructors ###{#videoframe-constructors}
NOTE: this section needs work. Current wording assumes a VideoFrame can always
be easily represented using one of the known pixel formats. In practice, the
underlying UA resources may be GPU backed or formatted in such a way that
conversion to an allowed pixel format requires expensive copies and
translation. When this occurs, we should allow planes to be null and format
to be "opaque" to avoid early optimization. We should make conversion
explicit and user controlled by offering a `videoFrame.convertTo(format)`
that returns a Promise containing a new VideoFrame for which the
copies/translations are performed.
VideoFrame(imageBitmap, frameInit)
1. If |frameInit| is not a [=valid VideoFrameInit=], throw a {{TypeError}}.
2. If the value of |imageBitmap|'s' {{PlatformObject/[[Detached]]}} internal
slot is set to `true`, then throw an {{InvalidStateError}} DOMException.
3. Let |frame| be a new {{VideoFrame}}.
4. Assign `false` to |frame|’s {{VideoFrame/[[detached]]}} internal slot.
5. Use a copy of the pixel data in |imageBitmap| to initialize to following
frame attributes:
1. Initialize `frame.pixelFormat` be the underlying format of imageBitmap.
2. Initialize `frame.planes` to describe the arrangement of memory of the
copied pixel data.
3. Assign regions of the copied pixel data to the
{{Plane/[[plane buffer]]}} internal slot of each plane as
appropriate for the pixel format.
4. Initialize `frame.codedWidth` and `frame.codedHeight` describe the width
and height of the imageBitamp prior to any cropping or aspect ratio
adjustments.
6. Use |frameInit| to initialize the remaining frame attributes:
1. If `frameInit.cropLeft` is present, initialize it `frame.cropLeft`.
Otherwise, default `frame.cropLeft` to zero.
2. If `frameInit.cropTop` is present, initialize it to `frame.cropTop`.
Otherwise, default `frame.cropTop` to zero.
3. If `frameInit.cropWidth` is present, initialize it to `frame.cropWidth`.
Otherwise, default `frame.cropWidth` to `frame.codedWidth`.
4. If `frameInit.cropHeight` is present, initialize it to
`frame.cropHeight`. Otherwise, default `frame.cropHeight` to
`frame.codedHeight`.
5. If `frameInit.displayWidth` is present, initialize it to
`frame.displayWidth`. Otherwise, default `frame.displayWidth` to
`frame.codedWidth`.
6. If `frameInit.displayHeight` is present, initialize it to
`frame.displayHeight`. Otherwise, default `frame.displayHeight` to
`frame.codedHeight`.
7. If `frameInit.duration` is present, initialize it to `frame.duration`.
Otherwise, default `frame.duration` to null.
8. If `frameInit.timestamp` is present, initialize it to `frame.timestamp`.
Otherwise default `frame.timestamp` to null.
7. Return |frame|.
VideoFrame(pixelFormat, planes, frameInit)
1. If either {{VideoFrameInit/codedWidth}} or {{VideoFrameInit/codedHeight}} is
not present in |frameInit|, throw a {{TypeError}}.
2. If |frameInit| is not a [=valid VideoFrameInit=], throw a {{TypeError}}.
3. If the length of |planes| is incompatible with the given pixelFormat, throw a
TypeError.
4. Let |frame| be a new {{VideoFrame}} object.
5. Assign `false` to |frame|’s {{VideoFrame/[[detached]]}} internal slot.
6. Assign `init.pixelFormat` to `frame.pixelFormat`.
7. For each element |p| in |planes|:
1. If |p| is a {{Plane}}, append a copy of p to `frame.planes`. Continue
processing the next element.
2. If |p| is a {{PlaneInit}}, append a new {{Plane}} q to
`frame.planes` initialized as follows:
2. Assign a copy of `p.src` to q's [[plane buffer]] internal slot.
NOTE: the samples should be copied exactly, but the user agent may add
row padding as needed to improve memory alignment.
3. Assign the width of each row in [[plane buffer]], including any
padding, to `q.stride`.
4. Assign `p.rows` to `q.rows`.
5. Assign the product of (`q.rows` * `q.stride)` to `q.length`
8. Assign `frameInit.codedWidth` to `frame.codedWidth`.
9. Assign `frameInit.codedHeight` to `frame.codedHeight`.
10. If `frameInit.cropLeft` is present, assign it `frame.cropLeft`. Otherwise,
default `frame.cropLeft` to zero.
11. If `frameInit.cropTop` is present, assign it to `frame.cropTop`. Otherwise,
default `frame.cropTop` to zero.
12. If `frameInit.cropWidth` is present, assign it to `frame.cropWidth`.
Otherwise, default `frame.cropWidth` to `frame.codedWidth`.
13. If `frameInit.cropHeight` is present, assign it to `frame.cropHeight`.
Otherwise, default `frame.cropHeight` to `frame.codedHeight`.
14. If `frameInit.displayWidth` is present, assign it to `frame.displayWidth`.
Otherwise, default `frame.displayWidth` to `frame.codedWidth`.
15. If `frameInit.displayHeight` is present, assign it to `frame.displayHeight`.
Otherwise, default `frame.displayHeight` to `frame.codedHeight`.
16. If `frameInit.duration` is present, assign it to `frame.duration`.
Otherwise, default `frame.duration` to null.
17. If `frameInit.timestamp` is present, assign it to `frame.timestamp`.
Otherwise, default `frame.timestamp` to null.
18. Return frame.
### Attributes ###{#videoframe-attributes}
- timestamp
-
The presentation timestamp, given in microseconds. The timestamp is copied
from the EncodedVideoChunk corresponding to this VideoFrame.
- duration
-
The presentation duration, given in microseconds. The duration is copied
from the EncodedVideoChunk corresponding to this VideoFrame.
- format
-
Describes the arrangement of bytes in each plane as well as the number and
order of the planes.
- planes
-
Holds pixel data data, laid out as described by format and Plane
attributes.
- codedWidth
-
Width of the VideoFrame in pixels, prior to any cropping or aspect ratio
adjustments.
- codedHeight
-
Height of the VideoFrame in pixels, prior to any cropping or aspect ratio
adjustments.
- cropLeft
-
The number of pixels to remove from the left of the VideoFrame, prior to
aspect ratio adjustments.
- cropTop
-
The number of pixels to remove from the top of the VideoFrame, prior to
aspect ratio adjustments.
- cropWidth
- The width of pixels to include in the crop, starting from cropLeft.
- cropHeight
- The height of pixels to include in the crop, starting from cropLeft.
- displayWidth
- Width of the VideoFrame when displayed.
- displayHeight
- Height of the VideoFrame when displayed.
### Methods ###{#videoframe-methods}
destroy()
Immediately frees [=system resources=]. Destruction applies to all
references, including references that are serialized and passed across
Realms.
NOTE: Authors should take care to manage frame lifetimes by calling
{{VideoFrame/destroy()}} immediately when frames are no longer needed.
NOTE: Use clone() to create a deep copy. Cloned frames have their own lifetime
and will not be affected by destroying the original frame.
When invoked, run these steps:
1. If {{VideoFrame/[[detached]]}} is `true`, throw an {{InvalidStateError}}.
2. Remove all {{Plane}}s from {{VideoFrame/planes}} and release associated
memory.
3. Assign `true` to the {{VideoFrame/[[detached]]}} internal slot.
clone()
Creates a new {{VideoFrame}} with a separate lifetime containing a deep copy of
this frame’s resources.
NOTE: VideoFrames may require a large amount of memory. Use
{{VideoFrame/clone()}} sparingly.
When invoked, run the following steps:
1. If the value of the {{VideoFrame/[[detached]]}} slot is `true`, return
[=a promise rejected with=] {{InvalidStateError}} {{DOMException}}.
2. Let |p| be a new Promise.
3. In parallel, resolve |p| with the result of running the Clone Frame
algorithm with this.
4. Return |p|.
createImageBitmap(options)
Creates an ImageBitmap from this {{VideoFrame}}.
When invoked, run these steps:
1. Let |p| be a new Promise.
2. If either |options|'s {{ImageBitmapOptions/resizeWidth}} or
{{ImageBitmap/resizeHeight}} is present and is 0, then return |p| rejected
with an {{InvalidStateError}} {{DOMException}}.
3. If the this' {{VideoFrame/[[detached]]}} internal slot is set to
`true`, then return |p| rejected with an {{InvalidStateError}}
{{DOMException}}.
4. Let |imageBitmap| be a new {{ImageBitmap}} object.
5. Set |imageBitmap|'s bitmap data to a copy of the {{VideoFrame}} pixel data,
at the frame's intrinsic width and intrinsic height (`i.e`., after any
aspect-ratio correction has been applied), cropped to the source rectangle
with formatting.
6. If the origin of |imageBitmap|'s image is not same origin with entry settings
object's origin, then set the origin-clean flag of |imageBitmap|'s bitmap to
`false`.
7. Run this step in parallel:
1. Resolve p with imageBitmap.
### Algorithms ###{#videoframe-algorithms}
To check if a {{VideoFrameInit}} is a valid VideoFrameInit,
run these steps:
1. If {{VideoFrameInit/codedWidth}} = 0 or {{VideoFrameInit/codedHeight}} = 0,
return `false`.
2. If {{VideoFrameInit/cropWidth}} = 0 or {{VideoFrameInit/cropHeight}} = 0,
return `false`.
3. If {{VideoFrameInit/cropTop}} + {{VideoFrameInit/cropHeight}} >=
{{VideoFrameInit/codedHeight}}, return `false`.
4. If {{VideoFrameInit/cropLeft}} + {{VideoFrameInit/cropWidth}} >=
{{VideoFrameInit/codedWidth}}, return `false`.
5. If {{VideoFrameInit/displayWidth}} = 0 or
{{VideoFrameInit/displayHeight}} = 0, return `false`.
6. Return `true`.
Plane Interface {#plane-interface}
----------------------------------
A {{Plane}} acts like a thin wrapper around an {{ArrayBuffer}}, but may actually
be backed by a texture. {{Plane}}s hide any padding before the first sample
or after the last row.
A {{Plane}} is solely constructed by its {{VideoFrame}}. During construction,
the User Agent may use knowledge of the frame’s {{PixelFormat}} to add
padding to the {{Plane}} to improve memory alignment.
A {{Plane}} cannot be used after the {{VideoFrame}} is destroyed. A new
{{VideoFrame}} can be assembled from existing {{Plane}}s, and the new
{{VideoFrame}} will remain valid when the original is destroyed. This makes
it possible to efficiently add an alpha plane to an existing {{VideoFrame}}.
interface Plane {
readonly attribute unsigned long stride;
readonly attribute unsigned long rows;
readonly attribute unsigned long length;
undefined readInto(ArrayBufferView dst);
};
dictionary PlaneInit {
required BufferSource src;
required unsigned long stride;
required unsigned long rows;
};
### Internal Slots ###{#plane-internal-slots}
- [[parent frame]]
- Refers to the {{VideoFrame}} that constructed and owns this plane.
- [[plane buffer]]
- Internal storage for the plane’s pixel data.
### Attributes ###{#plane-attributes}
- stride
- The width of each row including any padding.
- rows
- The number of rows.
- length
- The total byte length of the plane (stride * rows).
### Methods ###{#plane-methods}
readInto(dst)
Copies the plane data into dst.
When invoked, run these steps:
1. If {{Plane/[[parent frame]]}} has been destroyed, throw an
{{InvalidStateError}}.
2. If {{Plane/length}} is greater than |`dst.byteLength`|, throw a
{{TypeError}}.
3. Copy the {{Plane/[[plane buffer]]}} into dst.
Pixel Format{#pixel-format}
---------------------------
Pixel formats describe the arrangement of bytes in each plane as well as the
number and order of the planes.
NOTE: This section needs work. We expect to add more pixel formats and offer
much more verbose definitions. For now, please see
http://www.fourcc.org/pixel-format/yuv-i420/ for a more complete
description.
enum PixelFormat {
"I420"
};
- I420
-
Planar 4:2:0 YUV.
Algorithms{#raw-media-algorithms}
---------------------------------
- Clone Frame (with |frame|)
-
1. Let |cloneFrame| be a new object of the same type as frame (either
{{AudioFrame}} or {{VideoFrame}}).
2. Initialize each attribute and internal slot of clone with a copy of the
value from the corresponding attribute of this frame.
NOTE: User Agents are encouraged to avoid expensive copies of large
objects (for instance, {{VideoFrame}} pixel data). Frame types are
immutable, so the above step may be implemented using memory sharing
techniques such as reference counting.
3. Return |cloneFrame|.
Security Considerations{#security-considerations}
=================================================
The primary security impact is that features of this API make it easier for an
attacker to exploit vulnerabilities in the underlying platform codecs.
Additionally, new abilities to configure and control the codecs may allow for
new exploits that rely on a specific configuration and/or sequence of control
operations.
Platform codecs are historically an internal detail of APIs like
{{HTMLMediaElement}}, [[WebAudio]], and [[WebRTC]]. In this way, it has always
been possible to attack the underlying codecs by using malformed media
files/streams and invoking the various API control methods.
For example, you can send any stream to a decoder by first wrapping that stream
in a media container (e.g. mp4) and setting that as the {{HTMLMediaElement/src}}
of an {{HTMLMediaElement}}. You can then cause the underlying video decoder to
be {{VideoDecoder/reset()}} by setting a new value for `