Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory Reuse and Decode Length #60

Closed
anthumchris opened this issue May 22, 2020 · 2 comments
Closed

Memory Reuse and Decode Length #60

anthumchris opened this issue May 22, 2020 · 2 comments

Comments

@anthumchris
Copy link

anthumchris commented May 22, 2020

Would it be helpful to offer APIs that use pre-defined ring buffers to reduce garbage collection and maintain low latency? SharedArrayBuffer (SAB) could also be used for cross-realm/thread processing and browser support is returning.

Additionally, would it be helpful to control the decoder by specifying how many samples/frames to decode per call? We could decode quickly at first for low-latency playback and then gradually increase frame sizes after we have enough decoded data for playback continuity.

For example, consider a streaming audio AudioWorklet where GC is reduced using ring buffers and specifying 128 samples to decode synchronously (relates to #19).

audio-worklet-processer.js

// ring buffer of encoded bytes (set by "onmessage" or SAB from main/worker thread)
inputBuffer = new ArrayBuffer(...)

// ring buffers for decoded stereo 2.5s PCM @ 48,000hz
outLeft =  new ArrayBuffer(Float32Array.BYTES_PER_ELEMENT * 48000 * 2.5) // 469K
outRight = new ArrayBuffer(Float32Array.BYTES_PER_ELEMENT * 48000 * 2.5) // 469K

// decoded PCM samples
samplesLeft =  new Float32Array(outLeft)   // 120,000 samples
samplesRight = new Float32Array(outRight)  // 120,000 samples

// new stereo decoder (could also be on Worker/main thread via SAB)
decoder = new AudioDecoder({
  srcBuffer: inputBuffer,
  outputBuffers: [outLeft, outRight]
})

// buffer read/write index values
inStart, inEnd, outStart, outEnd

// return values after decode() call
totalSrcBytesUsed, totalSamplesDecoded

// AudioWorkletProcessor.process - processes 128 frames per quantum
process(inputs_NOT_USED, outputs) {
  // specify the max samples to decode (could also be called on Worker/main thread)
  { totalSrcBytesUsed, totalSamplesDecoded } = decoder.decode({ maxToDecode: 128 })

  // update src & output buffers read/write indexes
  ...

  // output decoded [samplesLeft, samplesRight] to @outputs
 ...
}
@anthumchris anthumchris changed the title Granularity for Memory Usage and Decoding Length Memory Reuse and Decode Length May 26, 2020
@padenot
Copy link
Collaborator

padenot commented Jul 6, 2020

The discussion in #39 is related. In general Bring You Own Buffer (often refered to as BYOB) are favored these days when designing new specs.

@chcunningham
Copy link
Collaborator

We've had the BYOB request from WASM folks as well, and we're keen to do something here. Unfortunately, using a SAB for output creates security concerns because the decoder may internally reference a decoded frame for sometime while it continues to decode later frames. Apps could manipulate the SAB during this period and cause crashes.

We're involved in a cross team (WASM, WebGPU, ...) discussion for memory re-use / reducing copies. The WebCodecs position is here: WICG/reducing-memory-copies#1

I'll go ahead and close and continue tracking in that repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants