Skip to content

Commit 80a1049

Browse files
committed
docs: add WebCodecs OpenSpec change proposals
Add comprehensive change proposals for implementing W3C WebCodecs spec: - add-webcodecs-definitions: Core definitions and terminology - add-codec-processing-model: Control messages and work queues - add-audiodecoder-interface: AudioDecoder implementation - add-videodecoder-interface: VideoDecoder implementation - add-audioencoder-interface: AudioEncoder implementation - add-videoencoder-interface: VideoEncoder implementation - add-codec-configurations: Config types and validation - add-encoded-media-interfaces: EncodedAudioChunk/EncodedVideoChunk - add-raw-media-interfaces: AudioData, VideoFrame, VideoColorSpace - add-imagedecoder-interface: ImageDecoder for GIF/PNG/JPEG/WebP - add-resource-reclamation: Memory management and cleanup - add-security-considerations: Input validation and resource safety - remove-webcodecs-acknowledgements: Remove W3C-specific content Also adds helper script for proposal generation.
1 parent 7fd7cb1 commit 80a1049

49 files changed

Lines changed: 5521 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Change: Migrate W3C AudioDecoder Interface to OpenSpec
2+
3+
## Why
4+
5+
The AudioDecoder interface is a core W3C WebCodecs API for decoding compressed audio data (AAC, Opus, MP3, etc.) into raw AudioData. Converting this spec section to OpenSpec requirements enables:
6+
7+
1. Automated compliance verification against the implementation in `lib/audio-decoder.ts` and `src/audio_decoder.cc`
8+
2. Clear traceability between spec requirements and test cases
9+
3. Consistent spec-driven development aligned with existing `add-webcodecs-definitions` and `add-codec-processing-model` changes
10+
11+
## What Changes
12+
13+
- **ADDED**: New `audiodecoder-interface` capability under `openspec/specs/`
14+
- Migrates W3C WebCodecs Section 3 from `docs/specs/3-audiodecoder-interface/`:
15+
- Constructor initialization (internal slots, callbacks)
16+
- Attributes (state, decodeQueueSize, ondequeue)
17+
- Methods (configure, decode, flush, reset, close, isConfigSupported)
18+
- Algorithms (Schedule Dequeue Event, Output AudioData, Reset AudioDecoder, Close AudioDecoder)
19+
- State machine transitions (unconfigured -> configured -> closed)
20+
- Key chunk validation requirements
21+
22+
## Impact
23+
24+
- Affected specs: None (new capability)
25+
- Affected code: `lib/audio-decoder.ts`, `src/audio_decoder.cc` (existing implementation to verify against)
26+
- Depends on:
27+
- `add-webcodecs-definitions` (references Codec, Key Chunk, Internal Pending Output, System Resources)
28+
- `add-codec-processing-model` (references control message queue, codec work queue)
Lines changed: 343 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,343 @@
1+
# AudioDecoder Interface
2+
3+
W3C WebCodecs AudioDecoder interface specification requirements.
4+
5+
Reference: `docs/specs/3-audiodecoder-interface/TOC.md`
6+
7+
## ADDED Requirements
8+
9+
### Requirement: AudioDecoder Constructor Initialization
10+
11+
The `AudioDecoder` constructor SHALL initialize all internal slots as specified by the W3C WebCodecs specification when invoked with a valid `AudioDecoderInit` dictionary.
12+
13+
#### Scenario: Constructor creates new AudioDecoder with required callbacks
14+
15+
- **WHEN** the AudioDecoder constructor is called with a valid `AudioDecoderInit` containing `output` and `error` callbacks
16+
- **THEN** a new AudioDecoder instance MUST be created
17+
- **AND** `[[control message queue]]` MUST be assigned a new empty queue
18+
- **AND** `[[message queue blocked]]` MUST be assigned `false`
19+
- **AND** `[[codec implementation]]` MUST be assigned `null`
20+
- **AND** `[[codec work queue]]` MUST be assigned a new parallel queue
21+
- **AND** `[[codec saturated]]` MUST be assigned `false`
22+
- **AND** `[[output callback]]` MUST be assigned the provided `output` callback
23+
- **AND** `[[error callback]]` MUST be assigned the provided `error` callback
24+
- **AND** `[[key chunk required]]` MUST be assigned `true`
25+
- **AND** `[[state]]` MUST be assigned `"unconfigured"`
26+
- **AND** `[[decodeQueueSize]]` MUST be assigned `0`
27+
- **AND** `[[pending flush promises]]` MUST be assigned a new empty list
28+
- **AND** `[[dequeue event scheduled]]` MUST be assigned `false`
29+
30+
#### Scenario: Constructor rejects missing output callback
31+
32+
- **WHEN** the AudioDecoder constructor is called without an `output` callback
33+
- **THEN** a TypeError MUST be thrown
34+
35+
#### Scenario: Constructor rejects missing error callback
36+
37+
- **WHEN** the AudioDecoder constructor is called without an `error` callback
38+
- **THEN** a TypeError MUST be thrown
39+
40+
---
41+
42+
### Requirement: AudioDecoder State Attribute
43+
44+
The `state` attribute SHALL return the current `CodecState` of the AudioDecoder instance.
45+
46+
#### Scenario: State returns current codec state
47+
48+
- **WHEN** the `state` attribute is accessed
49+
- **THEN** it MUST return the value of `[[state]]` internal slot
50+
- **AND** the value MUST be one of: `"unconfigured"`, `"configured"`, or `"closed"`
51+
52+
---
53+
54+
### Requirement: AudioDecoder DecodeQueueSize Attribute
55+
56+
The `decodeQueueSize` attribute SHALL return the number of pending decode requests.
57+
58+
#### Scenario: DecodeQueueSize reflects pending work
59+
60+
- **WHEN** the `decodeQueueSize` attribute is accessed
61+
- **THEN** it MUST return the value of `[[decodeQueueSize]]` internal slot
62+
- **AND** the value MUST decrease as the underlying codec accepts new input
63+
64+
---
65+
66+
### Requirement: AudioDecoder Dequeue Event
67+
68+
The AudioDecoder SHALL fire a `dequeue` event when `decodeQueueSize` has decreased.
69+
70+
#### Scenario: Dequeue event fires after queue size decreases
71+
72+
- **WHEN** `[[decodeQueueSize]]` decreases
73+
- **THEN** the Schedule Dequeue Event algorithm MUST be run
74+
75+
#### Scenario: Dequeue event coalescing prevents spam
76+
77+
- **WHEN** `[[dequeue event scheduled]]` equals `true`
78+
- **AND** the Schedule Dequeue Event algorithm is invoked
79+
- **THEN** no additional event MUST be scheduled
80+
81+
---
82+
83+
### Requirement: AudioDecoder Configure Method
84+
85+
The `configure()` method SHALL enqueue a control message to configure the decoder for decoding chunks as described by the provided config.
86+
87+
#### Scenario: Configure with valid config transitions to configured state
88+
89+
- **WHEN** `configure()` is called with a valid `AudioDecoderConfig`
90+
- **AND** `[[state]]` is not `"closed"`
91+
- **THEN** `[[state]]` MUST be set to `"configured"`
92+
- **AND** `[[key chunk required]]` MUST be set to `true`
93+
- **AND** a control message to configure the decoder MUST be enqueued
94+
- **AND** the control message queue MUST be processed
95+
96+
#### Scenario: Configure rejects invalid config
97+
98+
- **WHEN** `configure()` is called with an invalid `AudioDecoderConfig`
99+
- **THEN** a TypeError MUST be thrown
100+
101+
#### Scenario: Configure throws when closed
102+
103+
- **WHEN** `configure()` is called
104+
- **AND** `[[state]]` is `"closed"`
105+
- **THEN** an InvalidStateError DOMException MUST be thrown
106+
107+
#### Scenario: Configure rejects unsupported codec asynchronously
108+
109+
- **WHEN** a control message to configure the decoder is run
110+
- **AND** the codec configuration is not supported
111+
- **THEN** the Close AudioDecoder algorithm MUST be run with NotSupportedError
112+
113+
---
114+
115+
### Requirement: AudioDecoder Decode Method
116+
117+
The `decode()` method SHALL enqueue a control message to decode the given EncodedAudioChunk.
118+
119+
#### Scenario: Decode enqueues chunk for processing
120+
121+
- **WHEN** `decode()` is called with a valid EncodedAudioChunk
122+
- **AND** `[[state]]` is `"configured"`
123+
- **THEN** `[[decodeQueueSize]]` MUST be incremented
124+
- **AND** a control message to decode the chunk MUST be enqueued
125+
- **AND** the control message queue MUST be processed
126+
127+
#### Scenario: Decode throws when unconfigured
128+
129+
- **WHEN** `decode()` is called
130+
- **AND** `[[state]]` is `"unconfigured"`
131+
- **THEN** an InvalidStateError DOMException MUST be thrown
132+
133+
#### Scenario: Decode throws when closed
134+
135+
- **WHEN** `decode()` is called
136+
- **AND** `[[state]]` is `"closed"`
137+
- **THEN** an InvalidStateError DOMException MUST be thrown
138+
139+
#### Scenario: Decode requires key chunk after configure
140+
141+
- **WHEN** `decode()` is called
142+
- **AND** `[[key chunk required]]` is `true`
143+
- **AND** the chunk `[[type]]` is not `"key"`
144+
- **THEN** a DataError DOMException MUST be thrown
145+
146+
#### Scenario: Decode clears key chunk requirement after key chunk
147+
148+
- **WHEN** `decode()` is called
149+
- **AND** `[[key chunk required]]` is `true`
150+
- **AND** the chunk `[[type]]` is `"key"`
151+
- **THEN** `[[key chunk required]]` MUST be set to `false`
152+
153+
---
154+
155+
### Requirement: AudioDecoder Flush Method
156+
157+
The `flush()` method SHALL complete all control messages in the queue and emit all outputs, returning a Promise.
158+
159+
#### Scenario: Flush returns promise when configured
160+
161+
- **WHEN** `flush()` is called
162+
- **AND** `[[state]]` is `"configured"`
163+
- **THEN** `[[key chunk required]]` MUST be set to `true`
164+
- **AND** a new Promise MUST be created and appended to `[[pending flush promises]]`
165+
- **AND** a control message to flush MUST be enqueued
166+
- **AND** the Promise MUST be returned
167+
168+
#### Scenario: Flush rejects when unconfigured
169+
170+
- **WHEN** `flush()` is called
171+
- **AND** `[[state]]` is `"unconfigured"`
172+
- **THEN** a rejected Promise with InvalidStateError DOMException MUST be returned
173+
174+
#### Scenario: Flush rejects when closed
175+
176+
- **WHEN** `flush()` is called
177+
- **AND** `[[state]]` is `"closed"`
178+
- **THEN** a rejected Promise with InvalidStateError DOMException MUST be returned
179+
180+
#### Scenario: Flush emits all pending outputs
181+
182+
- **WHEN** a control message to flush is run
183+
- **THEN** `[[codec implementation]]` MUST be signaled to emit all internal pending outputs
184+
- **AND** the Output AudioData algorithm MUST be run with any decoded outputs
185+
- **AND** the flush promise MUST be resolved
186+
187+
---
188+
189+
### Requirement: AudioDecoder Reset Method
190+
191+
The `reset()` method SHALL immediately reset all state including configuration, control messages, and pending callbacks.
192+
193+
#### Scenario: Reset clears state when configured
194+
195+
- **WHEN** `reset()` is called
196+
- **AND** `[[state]]` is not `"closed"`
197+
- **THEN** `[[state]]` MUST be set to `"unconfigured"`
198+
- **AND** `[[codec implementation]]` MUST be signaled to cease producing output
199+
- **AND** all control messages MUST be removed from `[[control message queue]]`
200+
- **AND** `[[decodeQueueSize]]` MUST be set to `0` if greater than zero
201+
- **AND** the Schedule Dequeue Event algorithm MUST be run if queue size was reduced
202+
- **AND** all promises in `[[pending flush promises]]` MUST be rejected with AbortError
203+
204+
#### Scenario: Reset is no-op when closed
205+
206+
- **WHEN** `reset()` is called
207+
- **AND** `[[state]]` is `"closed"`
208+
- **THEN** the method MUST return without error (no-op)
209+
210+
---
211+
212+
### Requirement: AudioDecoder Close Method
213+
214+
The `close()` method SHALL immediately abort all pending work and release system resources. Close is final.
215+
216+
#### Scenario: Close releases resources
217+
218+
- **WHEN** `close()` is called
219+
- **THEN** the Reset AudioDecoder algorithm MUST be run with AbortError
220+
- **AND** `[[state]]` MUST be set to `"closed"`
221+
- **AND** `[[codec implementation]]` MUST be cleared and system resources released
222+
223+
#### Scenario: Close does not invoke error callback for AbortError
224+
225+
- **WHEN** the Close AudioDecoder algorithm runs with AbortError
226+
- **THEN** `[[error callback]]` MUST NOT be invoked
227+
228+
#### Scenario: Close invokes error callback for other errors
229+
230+
- **WHEN** the Close AudioDecoder algorithm runs with an error that is not AbortError
231+
- **THEN** `[[error callback]]` MUST be invoked with the error
232+
233+
---
234+
235+
### Requirement: AudioDecoder isConfigSupported Static Method
236+
237+
The `isConfigSupported()` static method SHALL return a Promise indicating whether the provided config is supported.
238+
239+
#### Scenario: isConfigSupported resolves with support information
240+
241+
- **WHEN** `isConfigSupported()` is called with a valid `AudioDecoderConfig`
242+
- **THEN** a Promise MUST be returned
243+
- **AND** the Promise MUST resolve with an `AudioDecoderSupport` dictionary
244+
- **AND** `AudioDecoderSupport.supported` MUST be `true` if the config is supported, `false` otherwise
245+
- **AND** `AudioDecoderSupport.config` MUST contain only recognized dictionary members
246+
247+
#### Scenario: isConfigSupported rejects invalid config
248+
249+
- **WHEN** `isConfigSupported()` is called with an invalid `AudioDecoderConfig`
250+
- **THEN** a rejected Promise with TypeError MUST be returned
251+
252+
---
253+
254+
### Requirement: AudioDecoder Output AudioData Algorithm
255+
256+
The Output AudioData algorithm SHALL create AudioData instances from decoded outputs and invoke the output callback.
257+
258+
#### Scenario: Output AudioData creates valid AudioData
259+
260+
- **WHEN** the Output AudioData algorithm runs with decoded outputs
261+
- **THEN** for each output, an AudioData instance MUST be created
262+
- **AND** `[[Detached]]` MUST be `false`
263+
- **AND** `[[timestamp]]` MUST match the associated EncodedAudioChunk timestamp
264+
- **AND** `[[format]]` MUST be set to the recognized AudioSampleFormat or `null`
265+
- **AND** `[[sample rate]]`, `[[number of frames]]`, and `[[number of channels]]` MUST be set from output
266+
- **AND** `[[output callback]]` MUST be invoked with the AudioData
267+
268+
---
269+
270+
### Requirement: AudioDecoder Schedule Dequeue Event Algorithm
271+
272+
The Schedule Dequeue Event algorithm SHALL fire a dequeue event, coalescing multiple invocations.
273+
274+
#### Scenario: Schedule Dequeue Event fires event
275+
276+
- **WHEN** the Schedule Dequeue Event algorithm runs
277+
- **AND** `[[dequeue event scheduled]]` is `false`
278+
- **THEN** `[[dequeue event scheduled]]` MUST be set to `true`
279+
- **AND** a task MUST be queued to fire a `dequeue` event
280+
- **AND** after firing, `[[dequeue event scheduled]]` MUST be set to `false`
281+
282+
#### Scenario: Schedule Dequeue Event no-op when already scheduled
283+
284+
- **WHEN** the Schedule Dequeue Event algorithm runs
285+
- **AND** `[[dequeue event scheduled]]` is `true`
286+
- **THEN** the algorithm MUST return immediately without scheduling another event
287+
288+
---
289+
290+
### Requirement: Valid AudioDecoderConfig
291+
292+
An `AudioDecoderConfig` SHALL be considered valid only if it contains all required members with valid values.
293+
294+
#### Scenario: Valid config has required members
295+
296+
- **WHEN** validating an AudioDecoderConfig
297+
- **THEN** `codec` MUST be defined and non-empty
298+
- **AND** `sampleRate` MUST be defined and a positive integer
299+
- **AND** `numberOfChannels` MUST be defined and a positive integer
300+
301+
#### Scenario: Empty codec string is invalid
302+
303+
- **WHEN** validating an AudioDecoderConfig
304+
- **AND** `codec` is an empty string
305+
- **THEN** the config MUST be considered invalid
306+
307+
---
308+
309+
### Requirement: AudioDecoder Codec Saturation Handling
310+
311+
The AudioDecoder SHALL handle codec saturation by pausing queue processing until the codec is ready.
312+
313+
#### Scenario: Decode respects codec saturation
314+
315+
- **WHEN** a control message to decode is run
316+
- **AND** `[[codec saturated]]` equals `true`
317+
- **THEN** the message MUST return `"not processed"` and remain in queue
318+
319+
#### Scenario: Decode sets saturation flag
320+
321+
- **WHEN** a control message to decode is run
322+
- **AND** decoding will cause `[[codec implementation]]` to become saturated
323+
- **THEN** `[[codec saturated]]` MUST be set to `true`
324+
325+
#### Scenario: Decode clears saturation when codec is ready
326+
327+
- **WHEN** decoding completes
328+
- **AND** `[[codec saturated]]` equals `true`
329+
- **AND** `[[codec implementation]]` is no longer saturated
330+
- **THEN** `[[codec saturated]]` MUST be set to `false`
331+
- **AND** the control message queue MUST be processed
332+
333+
---
334+
335+
### Requirement: AudioDecoder Decode Error Handling
336+
337+
The AudioDecoder SHALL close with an EncodingError if decoding fails.
338+
339+
#### Scenario: Decode error closes decoder
340+
341+
- **WHEN** a control message to decode is run
342+
- **AND** decoding results in an error
343+
- **THEN** the Close AudioDecoder algorithm MUST be run with EncodingError
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Tasks: Migrate W3C AudioDecoder Interface to OpenSpec
2+
3+
## 1. Verification
4+
5+
- [ ] 1.1 Verify spec delta requirements match W3C spec in `docs/specs/3-audiodecoder-interface/`
6+
- [ ] 1.2 Verify requirements align with current implementation in `lib/audio-decoder.ts`
7+
- [ ] 1.3 Cross-reference with `add-webcodecs-definitions` and `add-codec-processing-model` for consistency
8+
9+
## 2. Testing
10+
11+
- [ ] 2.1 Verify existing tests in `test/golden/` cover AudioDecoder requirements
12+
- [ ] 2.2 Identify gaps between spec requirements and test coverage
13+
- [ ] 2.3 Document test mapping for each requirement
14+
15+
## 3. Documentation
16+
17+
- [ ] 3.1 Update compliance matrix in `docs/specs/compliance-matrix.md` with AudioDecoder section status
18+
- [ ] 3.2 Add cross-references to related capabilities (definitions, processing model)
19+
20+
## 4. Archive
21+
22+
- [ ] 4.1 Run `openspec archive add-audiodecoder-interface` after approval and verification
23+
- [ ] 4.2 Verify archived spec renders correctly in `openspec/specs/audiodecoder-interface/spec.md`

0 commit comments

Comments
 (0)