• Skip to Search
  • Skip to Content
  • Skip to Side Navigation
Getting StartedSDK ReferenceGlossary
  • Home
  • Getting Started
  • SDK Reference
  • Portal
  • How-To
  • Troubleshooting
  • FAQs
  • Reference
  • Glossary
REST API
Web SDK
Android SDK
iOS SDK
Unity SDK
React Native SDK
EdgeAuth SDK
  • Overview
  • Express API
    • Channel
    • Room
    • PCast™
  • Low-Level API
    • Room
    • Chat
    • PCast™
  • Examples
  • Release Notes

PCast™ Express

The PCast™ Express extends the PCast™ API to provide a single-step configuration based API for:

  • Publishing local media
  • Publishing remote media (ingest)
  • Subscribing to published streams

This API is intended to be used as a supplement to the Room Express although it can be used to stream all on its own.

Initializing

Swift
1import PhenixSdk
2
3let pcastExpressOptions = PhenixPCastExpressFactory.createPCastExpressOptionsBuilder()
4 .withBackendUri("https://example.yourdomain.com/phenix/")
5 .buildPCastExpressOptions()
6
7let pcastExpress = PhenixPCastExpressFactory.createPCastExpress(pcastExpressOptions)

PhenixPCastExpressOptionsBuilder

NameTypeDefaultDescription
withBackendUri (required)NSStringUrl to your backend. We send requests here to authenticate and get streaming tokens.
withAuthenticationData (optional)NSStringYour authentication data for the user. On every request, this will be sent to your backend through a HTTP POST request and all its attributes would be accessible on the request body. Needs to be valid JSON.
withAuthenticationToken (optional)NSStringThe authentication token generated using the Phenix EdgeAuth library.
withUnrecoverableErrorCallback (optional)PhenixPCastExpressUnrecoverableErrorCallbackFunction to be called when authentication fails or a failure occurs that is unrecoverable.
withPCastUri (optional)NSStringAllows overriding default PCast™ URI.
withPCastInitializationOptions (optional)PhenixPCastInitializeOptionsUse custom options when initializing PCast™.
withAuthenticationRouteOverride (optional)NSStringauthAllows override of default route for authentication tokens
withStreamRouteOverride (optional)NSStringstreamAllows override of default route for stream tokens
buildPCastExpressOptionsnoneBuilds the PhenixPCastExpressOptions

Publishing Local Media

Publish local user media:

  • Camera
  • Microphone
Swift
1import PhenixSdk
2
3let pcastExpress: PhenixPCastExpress = ... // previously obtained
4
5let userMediaConstraints = PhenixUserMediaOptions()
6userMediaConstraints.video.enabled = true
7userMediaConstraints.video.capabilityConstraints[PhenixDeviceCapability.facingMode.rawValue] =
8 [PhenixDeviceConstraint.initWith(PhenixFacingMode.user)]
9userMediaConstraints.audio.enabled = true
10userMediaConstraints.audio.capabilityConstraints[PhenixDeviceCapability.audioEchoCancelationMode.rawValue] =
11 [PhenixDeviceConstraint.initWith(PhenixAudioEchoCancelationMode.on)]
12
13let publishOptions = PhenixPCastExpressFactory.createPublishOptionsBuilder()
14 .withCapabilities(["real-time"])
15 .withMediaConstraints(userMediaConstraints)
16 .buildPublishOptions()
17
18pcastExpress.publish(publishOptions) { (status: PhenixRequestStatus, publisher: PhenixExpressPublisher?) in
19 if status == .ok {
20 // Do something with publisher
21 } else {
22 // Handle error
23 }
24}
25
26
27// Create a publisher with an automatically started preview renderer
28let renderLayer: CALayer = ... // previously obtained
29let publishOptionsWithPreview = PhenixPCastExpressFactory.createPublishOptionsBuilder()
30 .withCapabilities(["real-time"])
31 .withMediaConstraints(userMediaConstraints)
32 .withPreviewRenderer(renderLayer)
33 .buildPublishOptions()
34
35pcastExpress.publish(withPreview: publishOptionsWithPreview) {
36 (status: PhenixRequestStatus, publisher: PhenixExpressPublisher?, preview: PhenixRenderer?) in
37 if status == .ok {
38 // Do something with publisher and preview renderer
39 } else {
40 // Handle error
41 }
42}

Notes:

  • The preview renderer will already have been started by the time it is received by your callback
  • The publisher will remain active for as long as you keep a reference to it

Publishing Local Media Parameters

NameTypeDescription
options (required)PhenixPublishOptionsPublish options
callback (required)functionCallback for error/success handling

PhenixPublishOptionsBuilder

NameTypeDefaultDescription
withMediaConstraints (required)PhenixUserMediaOptionsgetUserMedia options Constraints to get the user media.
withUserMedia (optional)PhenixUserMediaStreamalternative to withMediaConstraints - you can pass user media stream returned from getUserMedia.
withCapabilities (optional)NSArray of NSStringThe list of all capabilities to publish with. Default is empty array.
withPreviewRenderer (optional)CALayerRender layer on which to display local preview. If none of the withPreview... methods are called, no preview renderer will be instantiated.
withPreviewRenderer (optional)noneWill trigger instantiation of preview renderer. Useful for audio only type streams that do not require a render surface.
withPreviewRendererOptions (optional)PhenixRendererOptionsOptions passed to preview renderer. Will trigger instantiation of preview renderer.
withMonitor (optional)PhenixMonitorSetupFailedCallback, PhenixMonitorStreamEndedCallback, PhenixMonitorOptionsOptions for monitoring a publisher for failure.
withConnectOptions (optional)NSArray of NSStringsList of options for publishing.
withTags (optional)NSArray of NSStringsTags for the stream.
withStreamToken (optional)NSStringThe publish token generated using the Phenix EdgeAuth library.
buildPublishOptionsnoneBuilds the PhenixPublishOptions

Publishing Local Media Callback Arguments

NameTypeDescription
statusPhenixRequestStatusThe status of the operation
publisherPhenixExpressPublisherPhenix publisher object
previewRendererPhenixRendererOptionally provided if any of the withPreview... methods were called on the options builder and publish is invoked with withPreview.

PhenixExpressPublisher

Shares most methods with regular PhenixPublisher returned by PhenixPCast, see Publish a Stream.

NameSignatureReturnsDescription
stop()voidStops publisher. Subscribers will receive stream ended.
stop(reason)voidStops publisher with a custom reason. Subscribers will receive PhenixStreamEndedReasonCustom reason.
enableAudio()voidUnmutes audio.
disableAudio()voidMutes audio.
enableVideo()voidUnmutes video.
disableVideo()voidMutes video (black frames).
setDataQualityChangedCallback(callback)voidListen for Data Quality Feedback
limitBandwidth(bandwidthLimitInBps)PhenixDisposableTemporarily limit published video bitrate, see Limit Bandwidth
getStreamId()NSStringReturns stream ID of publisher
hasEnded()boolIndicates whether publisher has ended, e.g. by stop having been invoked

Publishing Remote Media (Ingest)

Publish from remote sources into the Phenix platform. This enables us to distribute your source media using the Phenix platform. After publishing users may subscribe to the stream using either pcast subscribe or express subscribe.

Swift
1import PhenixSdk
2
3let pcastExpress: PhenixPCastExpress = ... // previously obtained
4
5let publishRemoteOptions = PhenixPCastExpressFactory.createPublishRemoteOptionsBuilder()
6 .withStreamUri("http://mycdn.example.com/mystream.mp4")
7 .withCapabilities([""])
8 .buildPublishRemoteOptions()
9
10pcastExpress.publishRemote(publishRemoteOptions) { (status: PhenixRequestStatus, publisher: PhenixExpressPublisher?) in
11 if status == .ok {
12 // Do something with publisher
13 } else {
14 // Handle error
15 }
16}

Publishing Remote Media Parameters

NameTypeDescription
options (required)PhenixPublishRemoteOptionsPublish Remote options
callback (required)functionCallback for error/success handling

PhenixPublishRemoteOptionsBuilder

NameTypeDefaultDescription
withCapabilities (required)NSArray of NSStringThe list of all capabilities to publish with.
withStreamUri (required)NSStringLink to remote media (mp4, rtmp, etc.)
withStreamToken (optional)NSStringThe publish token generated using the Phenix EdgeAuth library.
withConnectOptions (optional)NSArray of NSStringsList of options for publishing from a remote source.
withTags (optional)NSArray of NSStringsTags for the stream
withMaximumFrameRateConstraint (optional)doubleMaximum frame rate constraint.
withExactFrameRateConstraint (optional)doubleExact frame rate constraint.
withPrerollSkipDuration (optional)NSTimeInterval500The amount of time to skip at the beginning of the media.
buildPublishRemoteOptionsnoneBuilds the PhenixPublishRemoteOptions

Publishing Remote Media Callback Arguments

NameTypeDescription
statusPhenixRequestStatusThe status of the operation.
publisherPhenixExpressPublisherPhenix publisher object

Subscribing to Published Media

Subscribe to streams published with the Phenix platform

Swift
1import PhenixSdk
2
3let pcastExpress: PhenixPCastExpress = ... // previously obtained
4let renderLayer: CALayer = ... // previously obtained
5
6let subscribeOptions = PhenixPCastExpressFactory.createSubscribeOptionsBuilder()
7 .withStreamId("us-west#us-west1-b.zzzzzzzz.20000000.xxxxxxxx")
8 .withCapabilities(["real-time"])
9 .withRenderer(renderLayer)
10 .buildSubscribeOptions()
11
12pcastExpress.subscribe(subscribeOptions) { (status: PhenixRequestStatus, subscriber: PhenixExpressSubscriber?, renderer: PhenixRenderer?) in
13 if status == .ok {
14 // Do something with subscriber
15
16 if let renderer = renderer {
17 // Returned if `withRenderer...` option was enabled - Do something with renderer
18 }
19 } else {
20 // Handle error
21 }
22}

Notes:

  • The renderer will already have been started by the time it is received by your callback
  • If a renderer is provided, your PhenixExpressSubscriber will be kept alive for as long as you are referencing that renderer. There is no need to also store a reference to the subscriber in that case
  • Once subscriber and renderer references have been released, the renderer and subscription will automatically be stopped

Subscribe Parameters

NameTypeDescription
options (required)PhenixSubscribeOptionsSubscribe options
callback (required)functionCallback for error/success handling

Subscribe Options

NameTypeDefaultDescription
withStreamId (required)NSStringThe stream ID of the published stream
withCapabilities (required)NSArray of NSStringThe list of all capabilities to subscribe with.
withStreamToken (optional)NSStringThe subscribe token generated using the Phenix EdgeAuth library.
withRenderer (optional)CALayerRender layer on which to display stream. If none of the withRenderer... methods are called, no renderer will be instantiated.
withRenderer (optional)noneWill trigger instantiation of renderer. Useful for audio only type streams that do not require a render surface.
withRendererOptions (optional)PhenixRendererOptionsOptions passed to renderer. Will trigger instantiation of renderer.
withMonitor (optional)PhenixMonitorSetupFailedCallback, PhenixMonitorStreamEndedCallback, PhenixMonitorOptionsOptions for monitoring a subscriber for failure.
withConnectOptions (optional)NSArray of NSStringsList of options for subscribing.
withTags (optional)NSArray of NSStringsTags for the stream
buildSubscribeOptionsnoneBuilds the PhenixSubscribeOptions

PhenixExpressSubscriber

Shares most methods with regular PhenixMediaStream returned by PhenixPCast, see Subscribe to a Stream.

NameSignatureReturnsDescription
createRenderer()PhenixRendererCreates a new renderer. This should only be called if none of the withRenderer... builder methods were invoked.
createRenderer(PhenixRendererOptions)PhenixRendererCreates a new renderer with PhenixRendererOptions. This should only be called if none of the withRenderer... builder methods were invoked.
getAudioTracks()NSArray of PhenixMediaStreamTrackReturns all associated audio tracks of this stream
getVideoTracks()NSArray of PhenixMediaStreamTrackReturns all associated video tracks of this stream
getTracks()NSArray of PhenixMediaStreamTrackReturns all associated tracks of this stream
stop()voidStops subscription. This will trigger the stream ended event.
disableAudio()voidMutes audio.
enableVideo()voidUnmutes video.
disableVideo()voidMutes video (black frames).

Monitor

Note: On iOS, the monitor options are currently ignored, but the callbacks for stream setup and stream ended will be triggered.

Monitor callbacks and options can be passed to subscribe and publish options builders. The first callback gets invoked only when we internally fail to setup a stream. The second callback gets invoked whenever a stream ends, whether it is due to failure or not. The retry PhenixOptionalAction allows you to retry publishing or subscribing the failed stream. You must test first whether there is a retry action present by calling isPresent as it may not be possible to retry the stream (example: a stream that ended normally cannot be retried). You may call dismiss on the retry action, but you do not have to (the action is automatically dismissed when no longer referenced). You also may defer invoking the retry action.

Example Monitor for subscribing

Swift
1import PhenixSdk
2
3let monitorOptions = PhenixPCastExpressFactory.createMonitorOptionsBuilder().buildMonitorOptions();
4
5let subscribeOptions = PhenixPCastExpressFactory.createSubscribeOptionsBuilder()
6 .withStreamId("us-west#us-west1-b.zzzzzzzz.20000000.xxxxxxxx")
7 .withCapabilities(["real-time"])
8 .withMonitor({ (status: PhenixRequestStatus, retry: PhenixOptionalAction?) in
9 // Stream failed to setup, check if retry is a possibility:
10 if let retry = retry, retry.isPresent() {
11 if determineWhetherToRetry() {
12 retry.perform()
13 } else {
14 // Not technically necessary, but here for clarity
15 retry.dismiss()
16 }
17 }
18 },
19 { (reason: PhenixStreamEndedReason, description: String?, retry: PhenixOptionalAction?) in
20 // Stream has ended, check if due to failure
21 if let retry = retry, retry.isPresent() {
22 if reason == .failed {
23 retry.perform()
24 } else {
25 // Not technically necessary, but here for clarity
26 retry.dismiss()
27 }
28 }
29 },
30 monitorOptions)
31 .buildSubscribeOptions()

PhenixOptionalAction

NameSignatureReturnsDescription
perform()voidPerforms the action. This will cause a failure if isPresent is false.
dismiss()voidDismisses the action (if any). Can be called multiple times, will result in isPresent to return false. Dropping reference to PhenixOptionsAction has same effect.
isPresent()boolIndicates whether an action can be performed.

PhenixMonitorSetupFailedCallback Callback Arguments

NameTypeDescription
statusPhenixRequestStatusThe status of the operation.
retryPhenixOptionalActionOptionally allow retrying the failed stream.

PhenixMonitorStreamEndedCallback Callback Arguments

NameTypeDescription
reasonPhenixStreamEndedReasonReason for stream ended.
descriptionNSStringOptional additional ended reason description. Carries custom message.
retryPhenixOptionalActionOptionally allow retrying the failed stream. For normally ended streams isPresent will always return false.

Express Get User Media

Get local user media. For now this is merely a wrapper around Get Local User Media.

Swift
1import PhenixSdk
2
3let pcastExpress: PhenixPCastExpress = ... // previously obtained
4
5let userMediaOptions = PhenixUserMediaOptions()
6
7pcastExpress.getUserMedia(userMediaOptions) { (status: PhenixRequestStatus, userMedia: PhenixUserMediaStream?) in
8 if status == .ok {
9 // Do something with user media stream
10 } else {
11 // Handle error
12 }
13}

Express Get User Media Parameters

NameTypeDescription
options (required)PhenixUserMediaOptionsUser media options
callback (required)functionCallback for error/success handling

Express Get User Media Callback Arguments

NameTypeDescription
statusPhenixRequestStatusThe status of the operation.
userMediaPhenixUserMediaStreamUser media stream

Get PCast™

Get the underlying instance of the PCast™. This is preferred to creating another instance as this will introduce more overhead.

Swift
1import PhenixSdk
2
3let pcastExpress: PhenixPCastExpress = ... // previously obtained
4
5let pcast = pcastExpress.pcast

Clean up

Subscribers and publishers are kept alive for as long as they are being referenced in your app. PhenixPCastExpress will only shutdown once it is no longer being referenced.

Process Raw Frames with Frame Ready API

The Frame Ready API allows access to raw unencoded audio and video frames on the publisher as well as subscriber side. This enables use cases such as the following:

  • Injection of raw frames from a custom source
  • Composition of raw frames (e.g. for applying watermarks, or stickers)
  • Application of effects (e.g. changing audio volume, applying video filters)
  • Controlling playback (e.g. temporary slow-motion, pause)

Please note: Any processing needs to keep up with the incoming frame rate; otherwise some of the incoming frames will be dropped to compensate.

Process Raw Frames Publisher side

The API is attached to PhenixUserMediaStream and called setFrameReadyCallback. A track needs to be passed in to indicate for which frames to receive notifications.

PhenixUserMediaStream (via its contained PhenixMediaStream) provides access to the currently available tracks via getVideoTracks and getAudioTracks.

Example Code for processing video raw frames

Swift
1import PhenixSdk
2
3let userMediaStream: PhenixUserMediaStream = ... // previously obtained
4
5// Assume there is at least one video track:
6let videoTrack = userMediaStream.mediaStream.getVideoTracks()[0]
7
8// 1) Example showing how read incoming video frame and produce and outgoing one:
9userMediaStream.setFrameReadyCallback(videoTrack) { (frameNotification: PhenixFrameNotification?) in
10 frameNotification?.read { (inputFrame: CMSampleBuffer?) in
11 let pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(inputFrame!)!
12
13 // Process, manipulate pixel buffer
14 // ...
15
16 // Assume we generate an output CVPixelBuffer, which may or may not be based
17 // on the incoming frame:
18 let outputPixelBuffer: CVPixelBuffer = ...
19
20 // Assemble an output frame using the same timestamps as the input sample buffer:
21 let presentationTimeStamp = CMSampleBufferGetPresentationTimeStamp(inputFrame!)
22 let duration = CMSampleBufferGetDuration(inputFrame!)
23
24 var sampleTimingInfo = CMSampleTimingInfo.init(
25 duration: duration,
26 presentationTimeStamp: presentationTimeStamp,
27 decodeTimeStamp: CMTime.invalid)
28
29 var formatDescription: CMFormatDescription? = nil
30 CMVideoFormatDescriptionCreateForImageBuffer(
31 allocator: kCFAllocatorDefault,
32 imageBuffer: outputPixelBuffer,
33 formatDescriptionOut: &formatDescription)
34
35 var outputFrame: CMSampleBuffer? = nil
36 CMSampleBufferCreateReadyWithImageBuffer(
37 allocator: kCFAllocatorDefault,
38 imageBuffer: outputPixelBuffer,
39 formatDescription: formatDescription!,
40 sampleTiming: &sampleTimingInfo,
41 sampleBufferOut: &outputFrame)
42
43 frameNotification?.write(outputFrame)
44 }
45}
46
47// 2) Example showing how we can just directly write output frames from a custom source without the need to
48// read the incoming frame:
49userMediaStream.setFrameReadyCallback(videoTrack) { (frameNotification: PhenixFrameNotification?) in
50 // Assume we have a custom source that is able to provide CMSampleBuffer:
51 let outputFrame: CMSampleBuffer? = ...
52
53 frameNotification?.write(outputFrame)
54}
55
56// 3) Example showing how we can stop frames from getting propagated by instructing the notification
57// to drop them:
58userMediaStream.setFrameReadyCallback(videoTrack) { (frameNotification: PhenixFrameNotification?) in
59 // We want to prevent frames from getting propagated further:
60 frameNotification?.drop()
61}
62
63// 4) Example showing how to read and convert incoming frames to a specific pixel format:
64userMediaStream.setFrameReadyCallback(videoTrack) { (frameNotification) in
65 frameNotification?.read(with: .BGRA) { (inputFrame: CMSampleBuffer?) in
66 let bgraPixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(inputFrame!)!
67
68 // ...
69 }
70}

Example Code for processing audio raw frames

Swift
1import PhenixSdk
2
3let userMediaStream: PhenixUserMediaStream = ... // previously obtained
4
5// Assume there is at least one audio track:
6let audioTrack = userMediaStream.mediaStream.getAudioTracks()[0]
7
8// 1) Example showing how read incoming audio frame and produce and outgoing one:
9userMediaStream.setFrameReadyCallback(audioTrack) { (frameNotification: PhenixFrameNotification?) in
10 frameNotification?.read { (inputFrame: CMSampleBuffer?) in
11 let blockBuffer = CMSampleBufferGetDataBuffer(inputFrame!)
12
13 var totalLength = Int()
14 var lengthAtOffset = Int()
15 var dataPointer: UnsafeMutablePointer<Int8>? = nil
16
17 guard CMBlockBufferGetDataPointer(
18 blockBuffer!,
19 atOffset: 0,
20 lengthAtOffsetOut: &lengthAtOffset,
21 totalLengthOut: &totalLength,
22 dataPointerOut: &dataPointer) == kCMBlockBufferNoErr && lengthAtOffset == totalLength else {
23 // Handle error, unexpected buffer length
24 return
25 }
26
27 // Verify audio format:
28 guard let formatDescription: CMAudioFormatDescription =
29 CMSampleBufferGetFormatDescription(inputFrame!) else {
30 return
31 }
32 guard let audioStreamBasicDescription =
33 CMAudioFormatDescriptionGetStreamBasicDescription(formatDescription) else {
34 return
35 }
36 guard (audioStreamBasicDescription.pointee.mFormatFlags & kAudioFormatFlagIsSignedInteger)
37 == kAudioFormatFlagIsSignedInteger &&
38 audioStreamBasicDescription.pointee.mBitsPerChannel == 16 else {
39 return
40 }
41
42 // Raw samples are contained in `dataPointer` as Int16 values
43 ...
44
45 // Assume we generate an output CMBlockBuffer, which may or may not be based
46 // on the incoming audio frame, and which as the same audio format and same
47 // length as the incoming frame:
48 let outputAudioBuffer: CMBlockBuffer = ...
49
50 let presentationTimeStamp = CMSampleBufferGetPresentationTimeStamp(inputFrame!)
51 let numberOfSamples =
52 totalLength /
53 Int(audioStreamBasicDescription.pointee.mChannelsPerFrame * audioStreamBasicDescription.pointee.mBitsPerChannel / 8)
54
55 var outputFrame: CMSampleBuffer? = nil
56 CMAudioSampleBufferCreateReadyWithPacketDescriptions(
57 allocator: kCFAllocatorDefault,
58 dataBuffer: outputAudioBuffer,
59 formatDescription: formatDescription,
60 sampleCount: numberOfSamples,
61 presentationTimeStamp: presentationTimeStamp,
62 packetDescriptions: nil,
63 sampleBufferOut: &outputFrame)
64
65 frameNotification?.write(outputFrame)
66 }
67}
68
69// Other examples would look very similar to video

Frame Ready Callback Arguments

This callback gets invoked for each frame that is passing through.

NameTypeDescription
frameNotificationPhenixFrameNotificationObject representing the current frame

Frame Notification

Represents the current frame. Allows for reading, writing, and dropping.

NameSignatureReturnsDescription
read(ReadFrameCallback)voidRetrieves current raw frame in form of a CMSampleBufferRef
readWithFormat(PhenixMediaFormat, ReadFrameCallback)voidRetrieves current raw frame in form of a CMSampleBufferRef
write(CMSampleBufferRef)voidWrites back a processed or newly generated frame. The frame can have a different resolution and timestamps (the buffer attributes are expected to be set correctly)
drop()voidInstructs stream to drop the current frame

Read Frame Callback Arguments

Receives the current raw frame.

NameTypeDescription
frameCMSampleBufferRefThe raw audio or video frame

Media Format

StrategyDescription
PhenixMediaFormatI420FourCC planar pixel format YUV-I420, corresponds to Apple kCVPixelFormatType_420YpCbCr8Planar
PhenixMediaFormatNV12FourCC planar pixel format YUV-NV12, corresponds to Apple kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
PhenixMediaFormatBGRAFourCC pixel format RGB-ARGB, corresponds to Apple kCVPixelFormatType_32BGRA

Process Raw Frames Subscriber side

The Frame Ready API on the subscriber side can be accessed via the renderer, which offers an analoguous setFrameReadyCallback method to the Publisher Side.

When using the Express API, you can access the stream tracks directly via the Express Subscriber. Otherwise, tracks can be accessed via the PhenixMediaStream object.

The example code is somewhat abbreviated as the contents of the Frame Ready callbacks would look the same as for the Publisher Side.

Example Code for hooking up frame-ready callback with a PhenixMediaStream object

Swift
1import PhenixSdk
2
3let mediaStream: PhenixMediaStream = ... // previously obtained
4let renderer: PhenixRenderer = ... // previously obtained
5
6// Assume there is at least one video track:
7let videoTrack = mediaStream.getVideoTracks()[0]
8
9renderer.setFrameReadyCallback(videoTrack, ...
10// Remainder of code identical to Publish Side

Example Code for hooking up frame-ready callback with a PhenixExpressSubscriber object

Swift
1import PhenixSdk
2
3let expressSubscriber: PhenixExpressSubscriber = ... // previously obtained
4let renderer: PhenixRenderer = ... // previously obtained
5
6// Assume there is at least one video track:
7let videoTrack = expressSubscriber.getVideoTracks()[0]
8
9renderer.setFrameReadyCallback(videoTrack, ...
10// Remainder of code identical to Publish Side

Limit Bandwidth

The outgoing or incoming video bandwidth can be limited on the publisher and subscriber side.

Limit Bandwidth Publisher side

The published video bitrate can be limited temporarily if needed. The returned disposable allows to control for how long the limitation should stay in effect. If limitBandwidth is called multiple times before any of the previous disposables are released, then only the most recent override will remain in effect until its disposable is released. Relasing any of the disposables from earlier limitBandwidth calls will have no effect.

Example Code for limiting video bandwidth with a PhenixPublisher object

Swift
1import PhenixSdk
2
3// Previously obtained
4let publisher: PhenixPublisher = ...
5
6// Limit video bitrate to 200kbps for 10 seconds
7var disposable = publisher.limitBandwidth(200000)
8
9DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
10 // Dropping the disposable will undo the bandwidth limitation
11 disposable = nil
12}

Example Code for limiting video bandwidth with a PhenixExpressPublisher object

Swift
1import PhenixSdk
2
3// Previously obtained
4let expressPublisher: PhenixExpressPublisher = ...
5
6// Limit video bitrate to 200kbps for 10 seconds
7var disposable = expressPublisher.limitBandwidth(200000)
8
9DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
10 // Dropping the disposable will undo the bandwidth limitation
11 disposable = nil
12}

Parameters

NameTypeDescription
bandwidthLimitInBps (required)UInt64Maximum bitrate limit in bps for video

Limit Bandwidth Subscriber side

Invoking limitBandwidth on a subscriber will inform the publishing side to lower the video bandwidth to try to match the requested value. The API is attached to PhenixMediaStreamTrack. The semantics with regards to the disposable returned by the API are identical to the publisher side.

Notes:

  • Whether a publisher is able to meet the requested bandwidth also depends on the stream capabilities for the given publisher. For MBR (multi-bitrate publisher capability enabled) the publisher will be able to fairly closely match the requested bitrate. With SBR (without multi-bitrate capability) the bit rate received by the subscriber may not match as well.
  • The video bitrate will not immediately change after limitBandwidth has been invoked. Similarly, once the disposable has been released, it may take several seconds for the bitrate to recover.

Example Code for limiting video bandwidth with a PhenixMediaStream object

Swift
1import PhenixSdk
2
3// Previously obtained
4let subscriber: PhenixMediaStream = ...
5
6// Limit video bitrate to 200kbps for 10 seconds
7// We assume there is at least one video track on this stream
8var disposable = subscriber.getVideoTracks()[0].limitBandwidth(200000)
9
10DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
11 // Dropping the disposable will undo the bandwidth limitation
12 disposable = nil
13}

Example Code for limiting video bandwidth with a PhenixExpressSubscriber object

Swift
1import PhenixSdk
2
3// Previously obtained
4let subscriber: PhenixExpressSubscriber = ...
5
6// Limit video bitrate to 200kbps for 10 seconds
7// We assume there is at least one video track on this stream
8var disposable = subscriber.getVideoTracks()[0].limitBandwidth(200000)
9
10DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
11 // Dropping the disposable will undo the bandwidth limitation
12 disposable = nil
13}

Parameters

NameTypeDescription
bandwidthLimitInBps (required)UInt64Maximum bitrate limit in bps for video
Page Content
    Copyright 2023 © Phenix RTS
    Privacy Policy | Terms of Service
    v2023-01-31T21:25:10