(chunk: EncodedVideoChunk)
| 273 | } |
| 274 | |
| 275 | private async decodeInternal(chunk: EncodedVideoChunk) { |
| 276 | const currentConfigId = this.currentConfigId; |
| 277 | |
| 278 | using lock = this.mutex.lock(); |
| 279 | await lock.ready; // Unconditional await here to queue a microtask |
| 280 | |
| 281 | if (this.currentConfigId !== currentConfigId) { |
| 282 | return; |
| 283 | } |
| 284 | |
| 285 | // Spec 4.5: Decrement [[decodeQueueSize]] and run the Schedule Dequeue Event algorithm. |
| 286 | this.decrementQueue(); |
| 287 | |
| 288 | assert(this.codecContext); |
| 289 | |
| 290 | const data = Buffer.from({ length: chunk.byteLength }); |
| 291 | chunk.copyTo(data); |
| 292 | |
| 293 | this.packet.isKeyframe = chunk.type === 'key'; |
| 294 | this.packet.data = data; |
| 295 | this.packet.timeBase = { num: 1, den: 1e6 }; |
| 296 | this.packet.pts = BigInt(chunk.timestamp); |
| 297 | this.packet.dts = AV_NOPTS_VALUE; |
| 298 | this.packet.duration = BigInt(chunk.duration ?? 0); |
| 299 | |
| 300 | const ret = await this.codecContext.sendPacket(this.packet); |
| 301 | |
| 302 | if (ret < 0) { |
| 303 | // Spec 4.5: If decoding results in an error, queue a task to run the Close VideoDecoder algorithm |
| 304 | // with EncodingError |
| 305 | throw new DOMException('Failed to send packet', 'EncodingError'); |
| 306 | } |
| 307 | |
| 308 | while (true) { |
| 309 | const receiveRet = await this.codecContext.receiveFrame(this.frame); |
| 310 | if (receiveRet < 0) { |
| 311 | break; |
| 312 | } |
| 313 | |
| 314 | this.outputFrame(currentConfigId); |
| 315 | } |
| 316 | } |
| 317 | |
| 318 | /** |
| 319 | * Flushes all pending decode operations and waits for completion. |
no test coverage detected