Skip to main content

iOS / macOS SDK Advanced Usage

This guide covers playback session management, media-origin authorization, preloading, and runtime controls. For initial integration, see Quick integration.

The examples run in a playback manager that retains self.client, self.session, and self.player as properties. Before replacing the active session, pause the player, detach the old media item, and close its session. Load the new playback URL only after session creation succeeds.

Live and VOD integration policy​

The SDK detects live/VOD automatically; both use the same quick integration. Player feedback is optional and helps P2P scheduling.

Live​

Report the continuous playable buffer ahead of the current position to tune P2P prefetch. For example, position 60 s with buffer ending at 70 s means 10,000 ms. Live start position and target latency remain player settings.

[self.session updateBufferedDurationMs:bufferedMs];

VOD​

Also report playback position so the SDK can prefer already-connected peers with nearby progress and the requested segment. Update position immediately after a completed seek.

[self.session updateCurrentPositionMs:positionMs];
[self.session updateBufferedDurationMs:bufferedMs];

Use non-negative milliseconds; do not count across buffer gaps. Send valid player state about once per second. Stop and drain updates before closing the session.

Complete player feedback example

Add this method to your playback manager. Pass YES for live and NO for VOD; it converts AVPlayer seconds to milliseconds.

#include <math.h>

- (void)syncPlaybackStateForLiveStream:(BOOL)isLive {
if (!self.session || !self.player.currentItem) return;
CMTime currentTime = self.player.currentTime;
double positionSeconds = CMTimeGetSeconds(currentTime);
if (!isfinite(positionSeconds) || positionSeconds < 0) return;

int64_t bufferedMs = 0;
for (NSValue *value in self.player.currentItem.loadedTimeRanges) {
CMTimeRange range = value.CMTimeRangeValue;
if (CMTimeRangeContainsTime(range, currentTime)) {
double seconds = CMTimeGetSeconds(
CMTimeSubtract(CMTimeRangeGetEnd(range), currentTime));
if (isfinite(seconds) && seconds >= 0) {
bufferedMs = (int64_t)(seconds * 1000.0);
}
break;
}
}
[self.session updateBufferedDurationMs:bufferedMs];
if (!isLive) {
[self.session updateCurrentPositionMs:(int64_t)(positionSeconds * 1000.0)];
}
}

MP4 / MP3 file playback​

Use media file URLs for MP4 and MP3 playback. Assign a stable contentId to each media asset. Set mimeType explicitly when the URL has no file extension.

P2PPlaybackOptions *options = [[P2PPlaybackOptions alloc] init];
options.contentId = @"trailer-2026";
options.mimeType = @"mp4";

NSError *error = nil;
self.session = [self.client createPlaybackSessionWithURL:
[NSURL URLWithString:@"https://cdn.example.com/video/trailer.mp4"]
options:options
error:&error];
if (self.session != nil) {
AVPlayerItem *item = [AVPlayerItem playerItemWithURL:self.session.playbackUrl];
self.player = [AVPlayer playerWithPlayerItem:item];
[self.player play];
}

For MP3, replace the example URL with an MP3 file URL and set mimeType = @"mp3".

File acceleration requires the media origin to support single-range HTTP Range requests and return a valid Content-Range. If the origin does not meet these requirements, acceleration is not enabled. Playback still depends on the media origin and player.

Multiple sessions​

One P2PClient can manage multiple independent PlaybackSession instances. Use a separate session for each player. When changing content, release the old session and create a new one, or use the candidate session already created for preloading.

Media-origin authorization​

Use a stable contentId to identify an asset with a temporary signed URL. For origins that require header-based authorization, pass credentials through originHeaders. These headers are used only to access the media origin and are not sent to other peers.

P2PPlaybackOptions *options = [[P2PPlaybackOptions alloc] init];
options.contentId = @"movie-2026-001";
options.mimeType = @"m3u8";
options.originHeaders = @{ @"Authorization": [NSString stringWithFormat:@"Bearer %@", originToken] };

NSError *error = nil;
self.session = [self.client createPlaybackSessionWithURL:signedOriginURL
options:options
error:&error];
if (self.session != nil) {
AVPlayerItem *item = [AVPlayerItem playerItemWithURL:self.session.playbackUrl];
[self.player replaceCurrentItemWithPlayerItem:item];
[self.player play];
}

Manage tokens, cookies, and complete signed URLs according to the application's security policy. Remove this sensitive information from logs and analytics data.

Preload and content switching​

Explicit preload is an optional HLS/DASH warmup: it fetches the manifest and first media segment in the background, not the entire video. It may also start Tracker/Peer connections early, but a successful queue operation does not guarantee that peers or media are ready. An unplayed candidate session does not upload media to peers. MP4/MP3 direct files do not use this explicit preload path.

Keep the candidate session and reuse its playback URL when selected. Before closing a session, stop and drain its player-state updates and remove its event subscriptions; do not continue callbacks against a closed session. Preload does not prepare a decoder or render a frame.

Preloading is optional and supports feeds and sequential playback. Retain the candidate session in a PlaybackSession *nextSession property and reuse it when playback starts.

Prepare candidate content​

[self.nextSession close];
NSError *error = nil;
self.nextSession = [self.client createPlaybackSessionWithURL:nextURL error:&error];
if (self.nextSession != nil) {
[self.nextSession preload];
}

Switch to the candidate​

Release the current media item and session, promote the candidate session, and load its playback URL:

if (!self.nextSession) {
return;
}
[self.player pause];
[self.player replaceCurrentItemWithPlayerItem:nil];
[self.session close];
self.session = self.nextSession;
self.nextSession = nil;
AVPlayerItem *item = [AVPlayerItem playerItemWithURL:self.session.playbackUrl];
[self.player replaceCurrentItemWithPlayerItem:item];
[self.player play];

Cancel candidate content​

Close the candidate session and release its reference when the content is no longer needed:

[self.nextSession close];
self.nextSession = nil;

Preloading consumes network traffic. A successful return from preload means the request was accepted, not that downloading or first-frame rendering is complete.

Runtime controls​

Set acceleration state and read statistics​

[self.session setP2PEnabled:NO]; // Temporarily disable acceleration
[self.session setP2PEnabled:YES];
P2PStats *stats = [self.session statistics];

setP2PEnabled: changes the current session's P2P setting. Acceleration remains subject to console policy.

Events and monitoring​

@interface PlaybackObserver : NSObject <P2PEventListener>
@end

@implementation PlaybackObserver
- (void)onP2PReady { }
- (void)onP2PUnavailable:(P2PUnavailableReason)reason { }
- (void)onPeerCountChanged:(NSInteger)peerCount { }
- (void)onCdnFallbackWithBytes:(int64_t)bytes { }
- (void)onStatistics:(P2PStats *)stats { }
@end

Retain the event listener in a PlaybackObserver *observer property and register it in the playback manager:

self.observer = [[PlaybackObserver alloc] init];
[self.client addEventListener:self.observer];

When monitoring ends, remove the same registered instance and release its reference:

[self.client removeEventListener:self.observer];
self.observer = nil;

Use acceleration events and statistics to observe SDK state. The application manages playback state and control through the player APIs.

Verify P2P delivery
  1. Start with one device: verify playback, seeking for VOD, and normal playback with P2P disabled.
  2. Run two devices on the same content with a consistent contentId. For VOD, use overlapping playback positions; for live, play the same channel. Keep the media bytes and timeline consistent; do not reuse an ID for different assets or personalized manifests.
  3. Check that player updates use milliseconds and continue after the manifest loads. At position 60 seconds with continuous buffer ending at 70 seconds, the buffer value is 10,000 ms; refresh VOD position after a completed seek.
  4. Observe changes in P2P downloaded bytes and offload ratio over a playback interval. A connected peer alone does not prove that media was downloaded through P2P. Results depend on overlapping available segments, network conditions, and platform policy.
  5. Disable P2P and verify that playback continues through CDN. Then stop state updates and event subscriptions before closing the session, and verify that switching content creates no calls against the closed session.

Application and authorization configuration​

Use the SDK Key for the target platform and ensure the application's Bundle ID matches its console registration. The SDK reads the Bundle ID automatically; no additional service address is required. Client and session P2P settings remain subject to console policy. The application manages media-origin credentials.

Lifecycle management​

Resource cleanup​

  • Use a separate playback session for each player, with one media asset per session.
  • When playback ends, pause the player and detach the media item before closing the active session and any unused candidate sessions.
  • Call +[P2PSDK shutdown] to release global resources when the application no longer uses any SDK clients or sessions.

Background playback and Picture in Picture​

Configure background playback and Picture in Picture capabilities in the application and player. If the application manages Picture in Picture, call [session setPictureInPictureActive:YES] or NO from callbacks reporting its actual start and end.

Retain the player and session while background or Picture in Picture playback continues. SDK session state does not replace the background permissions or audio session configuration required by the operating system.

Compatibility and error handling​

The SDK provides media delivery acceleration. The player handles decoding, rendering, buffering, and playback errors. Third-party players use the session-provided playbackUrl. Media format, DRM, and background capabilities depend on the player, operating system, and application configuration.

P2PUnavailableReason indicates that acceleration is unavailable, not that media playback failed. Continue using the session's playback URL while the session remains valid. Use player errors and media-origin state to determine whether playback should retry or stop. Handle SDK Key authorization separately from media-origin authorization; an origin authorization failure requires credential renewal or error handling in the application.