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.

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.