(configId: number, draining: boolean = false)
| 514 | } |
| 515 | |
| 516 | private async pullResampledFrames(configId: number, draining: boolean = false) { |
| 517 | assert(this.codecContext); |
| 518 | assert(this.resampler); |
| 519 | assert(this.dstFrame); |
| 520 | |
| 521 | const frameSize = this.codecContext.frameSize > 0 |
| 522 | ? this.codecContext.frameSize |
| 523 | : 1024; // Fallback for variable frame size codecs |
| 524 | |
| 525 | // When draining, we gotta pad with silence to reach a multiple of frameSize (except for AAC because it |
| 526 | // sometimes caused a weird "Input contains (near) NaN/+-Inf" error and I wasn't sure why). |
| 527 | if (draining && this.codecContext.frameSize > 0 && this.codecContext.codecId !== AV_CODEC_ID_AAC) { |
| 528 | const remainder = this.resampledSampleCount % frameSize; |
| 529 | |
| 530 | if (remainder > 0) { |
| 531 | const padSamples = frameSize - remainder; |
| 532 | const padBuffers = this.createInputSilenceBuffers(padSamples); |
| 533 | await this.resampler.convert(null, 0, padBuffers, padSamples); |
| 534 | this.resampledSampleCount += padSamples; |
| 535 | } |
| 536 | } |
| 537 | |
| 538 | while (true) { |
| 539 | const outputBuffers = this.createOutputBuffers(frameSize); |
| 540 | const got = await this.resampler.convert(outputBuffers, frameSize, null, 0); |
| 541 | |
| 542 | if (draining ? got <= 0 : got < frameSize) { |
| 543 | break; |
| 544 | } |
| 545 | |
| 546 | // Set up the destination frame and copy data |
| 547 | this.dstFrame.unref(); |
| 548 | this.dstFrame.format = this.codecContext.sampleFormat; |
| 549 | this.dstFrame.channelLayout = this.codecContext.channelLayout; |
| 550 | this.dstFrame.sampleRate = this.codecContext.sampleRate; |
| 551 | this.dstFrame.nbSamples = got; |
| 552 | this.dstFrame.allocBuffer(); |
| 553 | |
| 554 | const concatenated = Buffer.concat(outputBuffers); |
| 555 | this.dstFrame.fromBuffer(concatenated); |
| 556 | |
| 557 | this.dstFrame.pts = this.nextPts; |
| 558 | const durationMicros = BigInt(Math.floor(1e6 * got / this.codecContext.sampleRate)); |
| 559 | this.dstFrame.duration = durationMicros; |
| 560 | this.nextPts += durationMicros; |
| 561 | |
| 562 | await this.sendFrameAndReceivePackets(this.dstFrame, configId); |
| 563 | |
| 564 | if (draining && got < frameSize) { |
| 565 | break; |
| 566 | } |
| 567 | } |
| 568 | } |
| 569 | |
| 570 | /** |
| 571 | * Flushes all pending encode operations and waits for completion. |
no test coverage detected