PCast™ Express
The PCast™ Express extends the PCast™ API to provide a single-step configuration based API for:
- Publishing local media
- 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
1import android.content.Context;23import com.phenixrts.common.RequestStatus;4import com.phenixrts.environment.android.AndroidContext;5import com.phenixrts.express.PCastExpress;6import com.phenixrts.express.PCastExpressFactory;7import com.phenixrts.express.PCastExpressOptions;8import com.phenixrts.pcast.PCastInitializeOptions;910// IMPORTANT: Before accessing any of the static factories, make sure the context is passed to Phenix:11final Context context = ...; // e.g. Activity.getApplication();12AndroidContext.setContext(context);1314final PCastExpressOptions pcastExpressOptions =15 PCastExpressFactory.createPCastExpressOptionsBuilder()16 .withAuthenticationToken("DIGEST:eyJhc...")17 .withUnrecoverableErrorCallback((RequestStatus status, String description) -> {18 // Best to restart app, or attempt to re-create PCastExpress19 })20 .buildPCastExpressOptions();2122final PCastExpress pcastExpress = PCastExpressFactory.createPCastExpress(pcastExpressOptions);
PCastExpressOptionsBuilder
Name | Type | Default | Description |
---|---|---|---|
withAuthenticationToken (required) | String | The authentication token generated using the Phenix EdgeAuth library. | |
withUnrecoverableErrorCallback (optional) | PCastExpressOptions.UnrecoverableErrorCallback | Function to be called when authentication fails or a failure occurs that is unrecoverable. | |
withPCastUri (optional) | String | Allows overriding default PCast™ URI. | |
withPCastInitializationOptions (optional) | PCastInitializeOptions | Use custom options when initializing PCast™. | |
buildPCastExpressOptions | none | Builds the PCastExpressOptions |
Publishing Local Media
Publish local user media:
- Camera
- Microphone
- Screen (on supported devices)
1import android.view.SurfaceView;2import com.phenixrts.common.RequestStatus;3import com.phenixrts.express.ExpressPublisher;4import com.phenixrts.express.PCastExpress;5import com.phenixrts.express.PCastExpressFactory;6import com.phenixrts.express.PublishOptions;7import com.phenixrts.pcast.AudioEchoCancelationMode;8import com.phenixrts.pcast.DeviceCapability;9import com.phenixrts.pcast.DeviceConstraint;10import com.phenixrts.pcast.FacingMode;11import com.phenixrts.pcast.Renderer;12import com.phenixrts.pcast.UserMediaOptions;13import com.phenixrts.pcast.android.AndroidVideoRenderSurface;14import java.util.Arrays;1516final PCastExpress pcastExpress = ...; // previously obtained1718final UserMediaOptions userMediaConstraints = new UserMediaOptions();1920userMediaConstraints.getVideoOptions().enabled = true;21userMediaConstraints.getVideoOptions().capabilityConstraints.put(22 DeviceCapability.FACING_MODE,23 Arrays.asList(new DeviceConstraint(FacingMode.USER)));2425userMediaConstraints.getAudioOptions().enabled = true;26userMediaConstraints.getAudioOptions().capabilityConstraints.put(27 DeviceCapability.AUDIO_ECHO_CANCELATION_MODE,28 Arrays.asList(new DeviceConstraint(AudioEchoCancelationMode.ON)));2930final PublishOptions publishOptions = PCastExpressFactory.createPublishOptionsBuilder()31 .withStreamToken("DIGEST:eyJhc...")32 .withMediaConstraints(userMediaConstraints)33 .buildPublishOptions();3435pcastExpress.publish(publishOptions, (RequestStatus status, ExpressPublisher publisher) -> {36 if (status == RequestStatus.OK) {37 // Do something with publisher38 } else {39 // Handle error40 }41});424344// Create a publisher with an automatically started preview renderer45final SurfaceView view = ...; // previously obtained46final AndroidVideoRenderSurface renderSurface = new AndroidVideoRenderSurface(view.getHolder());4748final PublishOptions publishOptionsWithPreview = PCastExpressFactory.createPublishOptionsBuilder()49 .withStreamToken("DIGEST:eyJhc...")50 .withMediaConstraints(userMediaConstraints)51 .withPreviewRenderer(renderSurface)52 .buildPublishOptions();5354pcastExpress.publish(55 publishOptions, (RequestStatus status, ExpressPublisher publisher, Renderer preview) -> {56 if (status == RequestStatus.OK) {57 // Do something with publisher and preview renderer58 } else {59 // Handle error60 }61});
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
- You can force release of the publisher by invoking
close
on it
Publisher Parameters
Name | Type | Description |
---|---|---|
options (required) | PublishOptions | Publish options |
callback (required) | PCastExpress.PublishCallback or PCastExpress.PublishWithPreviewCallback | Callback for error/success handling |
PublishOptionsBuilder
Name | Type | Default | Description |
---|---|---|---|
withMediaConstraints (required) | UserMediaOptions | getUserMedia options Constraints to get the user media. | |
withUserMedia (optional) | UserMediaStream | alternative to withMediaConstraints - you can pass user media stream returned from getUserMedia. | |
withPreviewRenderer (optional) | AndroidVideoRenderSurface | Render layer on which to display local preview. If none of the withPreview... methods are called, no preview renderer will be instantiated. | |
withPreviewRenderer (optional) | none | Will trigger instantiation of preview renderer. Useful for audio only type streams that do not require a render surface. | |
withPreviewRendererOptions (optional) | RendererOptions | Options passed to preview renderer. Will trigger instantiation of preview renderer. | |
withMonitor (optional) | MonitorOptions.SetupFailedCallback, MonitorOptions.StreamEndedCallback, MonitorOptions | Options for monitoring a publisher for failure. | |
withTags (optional) | Strings[] | Tags for the stream. | |
withStreamToken (required) | String | The publish token generated using the Phenix EdgeAuth library. | |
buildPublishOptions | none | Builds the PublishOptions |
ExpressPublisher Callback Arguments
Name | Type | Description |
---|---|---|
status | RequestStatus | The status of the operation |
publisher | ExpressPublisher | Publisher object |
previewRenderer | Renderer | Optionally provided if any of the withPreview... methods were called on the options builder and publish is invoked with withPreview . |
ExpressPublisher
Shares most methods with regular Publisher returned by PCast™, see Publish a Stream.
Name | Signature | Returns | Description |
---|---|---|---|
stop | () | void | Stops publisher. Subscribers will receive stream ended. |
stop | (reason) | void | Stops publisher with a custom reason. Subscribers will receive StreamEndedReason.CUSTOM reason. |
enableAudio | () | void | Unmutes audio. |
disableAudio | () | void | Mutes audio. |
enableVideo | () | void | Unmutes video. |
disableVideo | () | void | Mutes video (black frames). |
setDataQualityChangedCallback | (callback) | void | Listen for Data Quality Feedback |
limitBandwidth | (bandwidthLimitInBps) | Disposable | Temporarily limit published video bitrate, see Limit Bitrate |
getStreamId | () | String | Returns stream ID of publisher |
hasEnded | () | bool | Indicates whether publisher has ended, e.g. by stop having been invoked |
Subscribing to Published Media
Subscribe to streams published with the Phenix platform
1import android.view.SurfaceView;2import com.phenixrts.common.RequestStatus;3import com.phenixrts.express.ExpressSubscriber;4import com.phenixrts.express.PCastExpress;5import com.phenixrts.express.PCastExpressFactory;6import com.phenixrts.express.SubscribeOptions;7import com.phenixrts.pcast.Renderer;8import com.phenixrts.pcast.android.AndroidVideoRenderSurface;910final PCastExpress pcastExpress = ...; // previously obtained11final SurfaceView view = ...; // previously obtained1213final AndroidVideoRenderSurface renderSurface = new AndroidVideoRenderSurface(view.getHolder());1415final SubscribeOptions subscribeOptions = PCastExpressFactory.createSubscribeOptionsBuilder()16 .withStreamId("us-west#us-west1-b.zzzzzzzz.20000000.xxxxxxxx")17 .withStreamToken("DIGEST:eyJhc...")18 .withRenderer(renderSurface)19 .buildSubscribeOptions();2021pcastExpress.subscribe(22 subscribeOptions,23 (RequestStatus status, ExpressSubscriber subscriber, Renderer renderer) -> {24 if (status == RequestStatus.OK) {25 // Do something with subscriber2627 if (renderer != null) {28 // Returned if `withRenderer...` option was enabled - Do something with renderer29 }30 } else {31 // Handle error32 }33});
Notes:
- The renderer will already have been started by the time it is received by your callback
- If a renderer is provided, your ExpressSubscriber 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
- To force release renderer or subscriber, you can invoke
close
, which will dispose the underlying resources
Subscribe Parameters
Name | Type | Description |
---|---|---|
options (required) | SubscribeOptions | Subscribe options |
callback (required) | PCastExpress.SubscribeCallback | Callback for error/success handling |
Subscribe Options
Name | Type | Default | Description |
---|---|---|---|
withStreamId (required) | String | The stream ID of the published stream | |
withStreamToken (required) | String | The subscribe token generated using the Phenix EdgeAuth library. | |
withRenderer (optional) | AndroidVideoRenderSurface | Render layer on which to display stream. If none of the withRenderer... methods are called, no renderer will be instantiated. | |
withRenderer (optional) | none | Will trigger instantiation of renderer. Useful for audio only type streams that do not require a render surface. | |
withRendererOptions (optional) | RendererOptions | Options passed to renderer. Will trigger instantiation of renderer. | |
withMonitor (optional) | MonitorOptions.SetupFailedCallback, MonitorOptions.StreamEndedCallback, MonitorOptions | Options for monitoring a subscriber for failure. | |
withTags (optional) | NSString[] | Tags for the stream | |
buildSubscribeOptions | none | Builds the SubscribeOptions |
ExpressSubscriber
Shares most methods with regular MediaStream returned by PCast™, see Subscribe to a Stream.
Name | Signature | Returns | Description |
---|---|---|---|
createRenderer | () | Renderer | Creates a new renderer. This should only be called if none of the withRenderer... builder methods were invoked. |
createRenderer | (RendererOptions) | Renderer | Creates a new renderer with RendererOptions. This should only be called if none of the withRenderer... builder methods were invoked. |
getAudioTracks | () | MediaStreamTrack[] | Returns all associated audio tracks of this stream |
getVideoTracks | () | MediaStreamTrack[] | Returns all associated video tracks of this stream |
getTracks | () | MediaStreamTrack[] | Returns all associated tracks of this stream |
stop | () | void | Stops subscription. This will trigger the stream ended event. |
disableAudio | () | void | Mutes audio. |
enableVideo | () | void | Unmutes video. |
disableVideo | () | void | Mutes video (black frames). |
Monitor
Note: On Android, 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 OptionalAction 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 should call dismiss
on the retry action to dismiss it, close
has the same effect. You also may defer invoking the retry action.
Example Monitor for subscribing
1import com.phenixrts.common.OptionalAction;2import com.phenixrts.common.RequestStatus;3import com.phenixrts.express.ExpressSubscriber;4import com.phenixrts.express.MonitorOptions;5import com.phenixrts.express.PCastExpressFactory;6import com.phenixrts.express.SubscribeOptions;7import com.phenixrts.pcast.StreamEndedReason;89final MonitorOptions monitorOptions = PCastExpressFactory.createMonitorOptionsBuilder()10 .buildMonitorOptions();1112final SubscribeOptions subscribeOptions = PCastExpressFactory.createSubscribeOptionsBuilder()13 .withStreamId("us-west#us-west1-b.zzzzzzzz.20000000.xxxxxxxx")14 .withStreamToken("DIGEST:eyJhc...")15 .withMonitor(16 (RequestStatus status, OptionalAction retry) -> {17 if (retry.isPresent()) {18 if (shouldRetry()) { // <- Your logic goes here19 retry.perform();20 } else {21 retry.dismiss();22 }23 }24 },25 (StreamEndedReason reason, String description, OptionalAction retry) -> {26 if (retry.isPresent()) {27 if (reason == StreamEndedReason.FAILED) { // <- Just an example28 retry.perform();29 } else {30 retry.dismiss();31 }32 }33 },34 monitorOptions)35 .buildSubscribeOptions();
OptionalAction
Name | Signature | Returns | Description |
---|---|---|---|
perform | () | void | Performs the action. This will cause a failure if isPresent is false. |
dismiss | () | void | Dismisses the action (if any). Can be called multiple times, will result in isPresent to return false. Invoking close has same effect. |
isPresent | () | boolean | Indicates whether an action can be performed. |
MonitorSetupFailedCallback Callback Arguments
Name | Type | Description |
---|---|---|
status | RequestStatus | The status of the operation. |
retry | OptionalAction | Optionally allow retrying the failed stream. |
MonitorStreamEndedCallback Callback Arguments
Name | Type | Description |
---|---|---|
reason | StreamEndedReason | Reason for stream ended. |
description | String | Optional additional ended reason description. Carries custom message. |
retry | OptionalAction | Optionally 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.
1import com.phenixrts.common.RequestStatus;2import com.phenixrts.express.PCastExpress;3import com.phenixrts.pcast.UserMediaOptions;4import com.phenixrts.pcast.UserMediaStream;56final PCastExpress pcastExpress = ...; // previously obtained78final UserMediaOptions userMediaOptions = new UserMediaOptions();910pcastExpress.getUserMedia(userMediaOptions, (RequestStatus status, UserMediaStream userMedia) -> {11 if (status == RequestStatus.OK) {12 // Do something with user media stream13 } else {14 // Handle error15 }16});
Express Get User Media Parameters
Name | Type | Description |
---|---|---|
options (required) | UserMediaOptions | User media options |
callback (required) | PCastExpress.GetUserMediaCallback | Callback for error/success handling |
Express Get User Media Callback Arguments
Name | Type | Description |
---|---|---|
status | RequestStatus | The status of the operation. |
userMedia | UserMediaStream | User media stream |
Get PCast
Get the underlying instance of the PCast™. This is preferred to creating another instance as this will introduce more overhead.
1import com.phenixrts.express.PCastExpress;2import com.phenixrts.pcast.PCast;34final PCastExpress pcastExpress = ...; // previously obtained56final PCast pcast = pcastExpress.getPCast();
Clean up
Subscribers and publishers are kept alive for as long as they are being referenced in your app. To force SDK objects to release their resources, you can call close
on them . PCastExpress will only shutdown once it is no longer being referenced or close
has been called on it.