Article

Implementing Flexible Enhanced Buffering for Your Content

Configure your app for flexible enhanced buffering to stream content faster to your AirPlay-enabled device.

Overview

If you’re working with content that requires flexibility with buffering, use the AVSampleBufferAudioRenderer and AVSampleBufferRenderSynchronizer classes.

Enabling flexible enhanced buffering is a four-step process:

Establish the Media Timeline and Audio Renderer

Instantiate AVSampleBufferRenderSynchronizer and AVSampleBufferAudioRenderer objects:

Listing 1

Instantiate AVSampleBufferRenderSynchronizer and AVSampleBufferAudioRenderer.

private let audioRenderer = AVSampleBufferAudioRenderer()
private let renderSynchronizer = AVSampleBufferRenderSynchronizer()

Tell the Audio Renderer to follow the Media Timeline

Add the AVSampleBufferAudioRenderer to the AVSampleBufferRenderSynchronizer:

Listing 2

Add the AVSampleBufferAudioRenderer to the AVSampleBufferRenderSynchronizer.

renderSynchronizer.addRenderer(audioRenderer)

Start Playback

Set the synchronizer's rate to 1:

Listing 3

Set the synchronizer's rate to 1.

serializationQueue.async {
    if self.automaticFlushObserver == nil {
        self.automaticFlushObserver = NotificationCenter.default.addObserver(forName: .AVSampleBufferAudioRendererWasFlushedAutomatically, object: self.audioRenderer, queue: nil) { notification in
            print("Got notification: \(notification)")
            self.advance(to: self.currentItem, at: self.currentItemCurrentTime)
        }
    }
    self.ensureSampleBufferSource()
    self.renderSynchronizer.rate = 1.0
    self.noteRateChanged()
}

Give Audio Data to the Renderer

Give the renderer some audio data and register for callbacks for when the renderer is ready for more:

Listing 4

Give audio data to the renderer.

self.audioRenderer.requestMediaDataWhenReady(on: serializationQueue) { [weak self] in
    guard let strongSelf = self else { return }
    let audioRenderer = strongSelf.audioRenderer
    while audioRenderer.isReadyForMoreMediaData {
        let sampleBuffer = strongSelf.nextSampleBuffer() // nil means "end of data"
        if let sampleBuffer = sampleBuffer {
            audioRenderer.enqueue(sampleBuffer)
        } else {
            // Make sure to tell the renderer to not expect any more audio data, else it will invoke the closure again
            audioRenderer.stopRequestingMediaData()
            break
        }
    }
}

See Also

Getting Started

Getting AirPlay 2 into Your App

Set up your app to use AirPlay 2 to send content wirelessly.

Implementing Simple Enhanced Buffering for Your Content

Configure your app for simple enhanced buffering to stream content faster to your AirPlay-enabled device.

Playing Custom Audio with Your Own Player

Construct an audio player to play your custom audio data, and optionally take advantage of the advanced features of AirPlay 2.

Integrating AirPlay for Long-Form Video Apps

Integrate AirPlay features and implement a dedicated external playback experience by preparing the routing system for long-form video playback.