• 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

Release Notes

The most current release version is 2022.0.3

Release notes for this version are shown below, followed by notes from prior releases.

To get the Android SDK for a specific version, update the Phenix SDK version in build.gradle file to match the version number, e.g., 2021.0.11. Some versions require additional integration steps; these are called out in the version-specific release notes.

v2022.0.3 Release Notes

Release Date: 2022.07.27

Features/Improvements

  • Added support for using a different CDN domain for playlists.

  • Added support for PCastUri in tokens.

  • Added support for channel/room alias or ID in tokens.

  • Improved network usage.

  • Improved video performance and compatibility

Fixes

  • Fixed chat room's messages loss in case of network issues.

  • Fixed late PhenixChannelExpress.joinChannel callback call in case of network issues.

  • Updated third-party library dependencies, including update to address potential expat vulnerability

  • Removed hardcoded TLS certificate and RSA key

v2022.0.3 Notes

CDN Domain support

The SDK can now send HTTP requests to URLs that redirect to non-Phenix CDNs for replays or for VOD playlists.

To use alternate CDN domains, use the capability cdn-domain on viewing channels, with the CDN domain as its value. Do not include the protocol prefix (e.g., https://) in the value. For example: cdn-domain=mycdn.mycompany.com

The platform will replace the default streaming domain with the specified CDN domain in playlist URLs for the primary manifest of the content.

PCast™ URI in tokens

A PCast™ URI contained in the token will now be used instead of a URI passed as a parameter. Putting the URI in the token is now the preferred behavior, and passing in a PCast™ URI as a parameter is now deprecated. To include the URI in the token, add the uri capability as described in the EdgeAuth library documentation.

If the token contains a URI that differs from the one passed as a parameter, the URI from the token is used and a warning is written to the log.

Room/Channel ID/Alias in tokens

A room/channel ID or alias passed in the token will be used to join the respective room or channel. As with the PCast™ URI, putting the Room or Channel ID or Alias in the token is now the preferred behavior, and passing in that information as a parameter is now deprecated and will generate a deprecation warning in the log. To include the Room or Channel information in the token, add the roomId, channelId, roomAlias or channelAlias capability as described in the EdgeAuth library documentation.

If a value is provided both as a direct parameter and in the token, the values must match; otherwise the operation will fail.

Improved network usage

When using previous releases, Room members rejoining after network changes would sometimes cause zombie room members. This has been improved and the behavior in case of network changes is more consistent.

In addition, network usage is reduced when downloading stream replay segments.

Fixed chat room messages loss in case of network issues

Previously, any messages still cached by the SDK during reconnection after a network change were silently discarded. Now they are preserved and will be returned by the next call to GetLastMessages. In addition, an issue has been fixed where new messages were discarded instead of old ones when there were many cached and incoming messages.

Upon lost network connectivity, the SDK will now keep trying to reconnect instead of ceasing to retry after a few minutes.

v2021.0.15 Pre-release Notes

Release Date: 2021.08.18

Features/Improvements

No customer-impacting changes.

v2021.0.14 Pre-release Notes

Release Date: 2021.08.09

Features/Improvements

No customer-impacting changes.

v2021.0.15 Pre-release Notes

Release Date: 2021.08.18

Features/Improvements

No customer-impacting changes.

v2021.0.14 Pre-release Notes

Release Date: 2021.08.09

Features/Improvements

No customer-impacting changes.

v2021.0.11 Pre-release Notes

Release Date: 2021.06.08

Features/Improvements

  • Increased internal timeout when connecting to PCast™ platform to avoid SDK initialization failures on clients with lossy network connections

Fixes

  • Fixed memory leaks occurring when stopping a room publisher

v2021.0.8 Pre-release Notes

Release Date: 2021.05.14

Features/Improvements

  • User media stream instances will no longer get stopped because of network disruptions or switches so they can be retained for as long as needed by an app

Notes on Integrating the Android SDK

UserMediaStream on Android.

v2021.0.7 Pre-release Notes

Release Date: 2021.05.06

Features/Improvements

  • None

Issues addressed in this release

  • Fixed null pointer crash in AudioPlaybackJniAdapter

  • Fixed sporadic crashes

v2021.0.5 Pre-release Notes

Release Date: 2021.04.12

Features/Improvements

  • None

Issues addressed in this release

  • Fixed bug resulting in subscribers not getting audio

v2021.0.2 Pre-release Notes

Release Date: 2021.03.02

Features/Improvements

  • When no Admin API (e.g. backend) is provided, channel publisher wildcard tokens are now automatically disabled to avoid failures

Issues addressed in this release

  • Fixed audio only real-time stream rendering

  • Fixed missing callback invocation for PhenixRoomExpress.subscribeToMemberStream if member stream has ended already

  • Added missing API PhenixPublishToChannelOptionsBuilder.withoutWildcardTokens

v2021.0.0 Pre-release Notes

Release Date: 2021.01.07

Features/Improvements

  • Improved error handling when attempting to start subscribers and publishers with capabilities and edge stream tokens

  • Reduce occurrences of audio drop out and lip sync issues on Android

  • Publish and subscribe should fail when caller supplies a stream token with capabilities in conjunction with explicitly capabilities (withCapabilities) to the builder; either approach works independently but both simultaneously will fail

Issues addressed in this release

  • Fixed broken time shifts for very long running streams

v2020.1.76 Pre-release Notes

Release Date: 2020.12.22

Features/Improvements

  • PhenixTimeShiftOptions.chunkRetrievalTimeout property allows overriding the maximum amount of time the SDK will wait to download a chunk for time-shift playback

  • PhenixChannelExpress.joinChannel will now return with an "unauthorized" status (subscriber callback) when the stream token that was provided when the channel was joined is either invalid or has expired. The recourse for the app is to leave the channel (PhenixRoomService.leaveRoom()) and then re-join the channel with an updated stream token.

Issues addressed in this release

  • None

Notes on Integrating the Android SDK

Java
1// The current implementation of `TimeShift` leverages HLS chunks.
2// It is possible that retrieval of such chunks can take a very long time.
3// This will impact playback if the playback head catches up with the end
4// of the prefetch window, which will lead to a stall.
5// By default, a timeout of 10 seconds for each chunk retrieval is used
6// to avoid holding off playback for too long (worst case a chunk will be
7// skipped and playback may pause temporarily).
8// This timeout is configurable by setting the following option (it defaults
9// to 0, which indicates that we should use the internal default):
10var timeoutInMilliseconds = 5000L
11rendererOptions.timeShiftOptions.chunkRetrievalTimeoutInMilliseconds
12 = timeoutInMilliseconds

v2020.1.75 Pre-release Notes

Release Date: 2020.12.11

Features/Improvements

  • PhenixTimeShiftOptions via PhenixRendererOptions allows customization of rendition selection behavior

Issues addressed in this release

  • Fixed possible crash due race condition occurring when shutting down a renderer

  • Fixed resource leaks associated with time-shifts

Notes on Integrating the Android SDK

Java
1import com.phenixrts.common.Disposable;
2import com.phenixrts.pcast.Renderer;
3import com.phenixrts.pcast.TimeShift;
4
5import java.util.Date;
6
7// Renderer has been obtained from `MediaStream` or `ExpressSubscriber`:
8var renderer: Renderer = ...
9
10
11if (!renderer.isSeekable) {
12 // This stream does not support time shifting
13 return;
14}
15
16// Must be in UTC:
17var timePoint = Date(...)
18
19var timeShift = renderer.seek(timePoint)
20
21// Observe ready status and call `loop` once TimeShift is ready.
22// This ensures that when `loop` is called playback will start
23// instantly.
24
25// All observables return a `Disposable` object. This needs to be stored
26// in order to keep the observable subscription alive.
27// It is recommended to make this a member of the enclosing class
28var disposables = mutableListOf<Disposable>()
29
30timeShift.observableReadyForPlaybackStatus.subscribe { isReady ->
31 if (isReady) {
32 var loopDurationInMilliseconds = 30000L
33
34 timeShift.loop(loopDurationInMilliseconds)
35 }
36}.run{ disposables.add(this) }
37
38// When time shifted viewing is no longer desired:
39
40// Dispose the `TimeShift` object. It will no longer be useable
41// after this operation. A new instance can be obtained via `seek`
42timeShift.dispose() // <-- Playback will jump back to real-time head
43
44// It is also possible to stop a timeshift in progress so it can
45// be used again by calling `loop` later
46timeShift.stop() // <-- Playback will jump back to real-time head
47
48// After `stop()` the ready status will (briefly) switch to false, then
49// back to true when enough data has been re-cached.
50
51// `TimeShift` objects can fail, either during creating when passing in
52// an invalid timestamp to `Renderer.seek()` or any of the other `TimeShift`
53// method. Once a `TimeShift` has failed, it should be disposed and a new
54// one created.
55timeShift.observableFailure.subscribe { status ->
56 // a non-OK `RequestStatus` is returned here
57}.run { disposables.add(this) }
58
59// Pause playback
60timeShift.pause()
61
62// Resume playback after pause
63timeShift.play()
64
65// The current playback head can be observed. Each video frame will trigger
66// the observable. The head is reported as a `Date` object and represents UTC.
67timeShift.observablePlaybackHead.subscribe { playbackHead ->
68 // a `Date` object. Avoid blocking this thread and dispatch UI updates
69 // as needed.
70}.run { disposables.add(this) }
71
72// `TimeShift` supports seeking to any location within the current segment.
73// The segment is defined by:
74// Start: Time point passed into `Renderer.seek`
75// End : Start plus duration passed into `TimeShift.loop`
76
77// Seeking is only possible if the `TimeShift` is either stopped or paused.
78// Once `TimeShift` is ready for playback, the observable returned by `seek`
79// will return a status code. Call `play()` to start/resume playback if the
80// status is OK.
81var relativeSeekTimeInMillis = -10000L // Seeks back 10 seconds
82
83timeShift.seek(relativeSeekTimeInMillis).subscribe { status ->
84 if (status == RequestStatus.OK) {
85 timeShift.play()
86 } else {
87 // Handle error. In most cases the seek argument would have led to
88 // a location outside of the segment
89 }
90}.run { disposables.add(this) }
91
92// There is also a second version of `seek` available, which accepts a `Date`
93// as its argument representing an absolute time point in UTC (also has to
94// fall within the boundaries of the segment).
95
96
97// A `TimeShift` stream generally consists of several so called layers. Layers
98// have different bitrates, usually by varying resolution and framerate (lower
99// bitrate layers tend to have lower resolutions and/or framerates).
100
101// While a `TimeShift` is playing back content, it will automatically select
102// an appropriate layer based on the pixel resolution of the rendering
103// surface. The logic attempts to select a layer, whose resolution matches
104// that of the rendering surface as closely as possible.
105
106// Sometimes an app may want to further restrict the playback layer in order
107// to reduce battery usage for instance. This is possible via the
108// `TimeShift.limitBandwidth` API. It forces the `TimeShift` to only select
109// layers with an average bitrate less or equal to the value passed into
110// `limitBandwidth`.
111// The limitation will remain in effect for as long as the app holds on to
112// the `Disposable` object returned by the API.
113// This API can be called at any time: before and during playback.
114var bandwithLimitInBps = 400000L
115
116var limitBandwidthDisposable = timeShift?.limitBandwidth(bandwithLimitInBps)
117
118// Call `dispose()` on the `Disposable` object to release the bandwidth limit
119limitbandwidthDisposable?.dispose()
120
121
122// Certain behaviors of `TimeShift` can be changed by passing in
123// custom options when the `Renderer` is created:
124
125var rendererOptions = RendererOptions()
126
127// When calling `Renderer.seek` or `TimeShift.seek` the
128// bandwidth will be automatically limited to shorten the amount of time
129// it takes for the `TimeShift` object to become ready.
130// The downside of this approach is that once the playback starts, it will
131// do so on a lower bitrate rendition of the stream and it generally takes a
132// few seconds before the rendition switches to a higher bitrate.
133// This behavior is enabled by default, but can be disabled by setting the
134// following option to false:
135rendererOptions.timeShiftOptions.lowerBandwidthWhileSeekingEnabled = false
136
137// The size of the viewport will determine which rendition of the stream is
138// selected (the rendition whose height in pixels is closest to the current
139// height of the viewport). This selection process is continuous, which means
140// that as the viewport size changes, so does the selected rendition.
141// After a new rendition has been selected, it will not render frames
142// instantly. Instead, it will take up to about 5 seconds before it will
143// render frames.
144// This behavior is enabled by default, but can be disabled by setting the
145// following option to false:
146rendererOptions.timeShiftOptions.viewportSizeBasedRenditionSelectionEnabled
147 = false
148
149// The options object can be passed in directly to the `createRenderer`
150// method:
151var subscriber: ExpressSubscriber = ... // previously obtained
152
153var renderer = subscriber.createRenderer(rendererOptions)
154
155// Alternatively, it can be passed via various options builders, for example
156// for `joinChannel`:
157var joinChannelOptionsBuilder =
158 ChannelExpressFactory.createJoinChannelOptionsBuilder()
159
160joinChannelOptionsBuilder.withRendererOptions(rendererOptions)

v2020.1.73 Pre-release Notes

Release Date: 2020.12.01

Features/Improvements

  • Improved stability in the case where Bluetooth permission is missing

  • Improved audio stream reliability by increasing audio render buffer size

  • Reduced time taken for TimeShift playback to reach higher rendition

  • Improved TimeShift playback reliability

Issues addressed in this release

  • None

v2020.1.68 Pre-release Notes

Release Date: 2020.11.12

Features/Improvements

  • Shortened duration for TimeShift to become ready

  • Improved TimeShift playback reliability

  • Setting the RTP/UTC time base needs to use the correct DVR section start time

  • TimeShift seeking needs to prevent deadlocks on calling thread

  • Move callback handling in AndroidJavaAudioRenderDevice to a separate thread

  • Handle bluetooth headset connections and disconnections with AEC enabled on Android

  • Revert audio capture time-stamping logic back to using local timestamp

Issues addressed in this release

  • None

Notes on Integrating the Android SDK

In order to support BlueTooth functionality, add the following to the manifest:

<uses-permission android:name="android.permission.BLUETOOTH" />

v2020.1.61 Pre-release Notes

Release Date: 2020.09.22

Features/Improvements

  • Fix for occasional failures when creating RoomChatService. Extra delay before creating service is no longer needed.

  • Fix for failing TimeShift objects after calling Renderer.Seek for Live streams

Issues addressed in this release

  • None

v2020.1.60 Pre-release Notes

Release Date: 2020.09.16

IMPORTANT: We only recommend this update for the VOD applications (not Live). This release has an issue that affects Live timeshifts.

Features/Improvements

  • None

Issues addressed in this release

  • Fix for further potential deadlocks that may occur when calling Renderer.Seek

  • Fix for short DVR segments not looping

  • Fix for deadlock when calling Renderer.Seek

  • Improved VOD stream startup and seeking times and stability

  • Improved performance by avoiding pixel format conversions where possible

v2020.1.56 Pre-release Notes

Release Date: 2020.08.31

Features/Improvements

  • None

Issues addressed in this release

  • Added support for subscribing to messages based on mime-types

  • Fix to properly expose API in support for configurable sampling rate for BlueTooth SCO capability in Android

  • Added client side timeouts for member updates

Notes on Integrating the Android SDK

In order to support BlueTooth SCO headsets

  1. Configure the sample rate overrides for recording and playback to values that are required by SCO:
Java
1try {
2 Os.setenv("PHENIX_AUDIO_PLAYBACK_SAMPLE_RATE_OVERRIDE", "16000", true);
3 Os.setenv("PHENIX_AUDIO_RECORDING_SAMPLE_RATE_OVERRIDE", "8000", true);
4 } catch (ErrnoException e) {
5 // handle exception
6 }
  1. Enable SCO in the AudioManager (this example assumes the code is placed in your Application subclass):
Java
1AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
2
3 // call at appropriate time - detection of BT on
4 audioManager.startBluetoothSco();
5
6 // call at appropriate time - detection of BT off
7 audioManager.stopBluetoothSco();
  1. For both publishing and subscribing, make sure that audio echo cancellation is enabled in the respective options:
Java
1// publishing
2 final UserMediaOptions mediaConstraints = new UserMediaOptions();
3 mediaConstraints.getAudioOptions().capabilityConstraints.put(
4 DeviceCapability.AUDIO_ECHO_CANCELATION_MODE,
5 singletonList(new DeviceConstraint(AudioEchoCancelationMode.ON)));
6 PublishOptions publishOptions = PCastExpressFactory.createPublishOptionsBuilder()
7 .withMediaConstraints(mediaConstraints)
8 // add any other options
9 .buildPublishOptions();
10 // subscribing
11 final RendererOptions rendererOptions = new RendererOptions();
12 rendererOptions.audioEchoCancelationMode = AudioEchoCancelationMode.ON;
13 JoinChannelOptionsBuilder joinChannelOptionsBuilder = ChannelExpressFactory
14 .createJoinChannelOptionsBuilder()
15 .withRendererOptions(rendererOptions)
16 // add any other options
17 .buildJoinChannelOptions()
  1. Note that only mono streams are supported by SCO.

In order to subscribe to messages by mime-type

Java
1import com.phenixrts.chat.RoomChatServiceFactory;
2import com.phenixrts.room.RoomService;
3
4final int batchSize = ...
5final RoomService roomService = ...; // previously obtained
6
7final HashSet<String> wantedMimeTypes = new HashSet<String>();
8wantedMimeTypes.add(“text/javascript”);
9
10final RoomChatService chatService =
11 RoomChatServiceFactory.createRoomChatService(
12 roomService,
13 batchSize,
14 wantedMimeTypes
15 );
16
17// “chatService” retrieves only messages of “wantedMimeTypes”
18final Disposable subscriptionLastChatMessage =
19 chatService.getObservableLastChatMessage().subscribe((change) -> {
20 final ChatMessage message = (ChatMessage)change;
21 assert message.getObservableMimeType().getValue() == “text/javascript”;
22});
23
24final Disposable subscriptionChatMessages =
25 chatService.getObservableChatMessages().subscribe((change) -> {
26 final ChatMessage[] messages = (ChatMessage[])change;
27
28 for (int i = 0; i < messages.length; ++i) {
29 assert message.getObservableMimeType().getValue() ==
30 “text/javascript”;
31 }
32});
33
34chatService.getMessages(
35 batchSize,
36 afterMessageId,
37 beforeMessageId,
38 (RoomChatService service, ChatMessage[] messages, RequestStatus status) -> {
39 for (int i = 0; i < messages.length; ++i) {
40 assert message.getObservableMimeType().getValue() ==
41 “text/javascript”;
42 }
43});
44
45// send message with a specific MIME type
46// with just the message, MIME type defaults to “text/plain”:
47chatService.sendMessageToRoom("My First Message");
48
49// with message and MIME type, but using default callback
50chatService.sendMessageToRoom("My First Message", "text/javascript");
51
52// with message, MIME type, and callback
53chatService.sendMessageToRoom(
54 "My First Message",
55 "text/javascript",
56 (RequestStatus status, String message) -> { ... }
57);

v2020.1.52 Pre-release Notes

Release Date: 2020.08.27

Features/Improvements

  • None

Issues addressed in this release

  • Support for configurable sampling rate for BlueTooth SCO capability

  • Improvements on re-establishing connections after changing network type

  • Improved reliability of room member updates, which impacts for instance toggling audio/video muted states

  • Added support for obtaining beta iOS releases via pod spec

v2020.1.49 Pre-release Notes

Release Date: 2020.08.21

Features/Improvements

  • None

Issues addressed in this release

  • Stream restart on change in network type

  • Fix for the last message observable - improve reliability on new message arrival

  • Removed unnecessary animation (iOS)

Notes

To take advantage of the new functionality in support of stream restarts on change in network type, it works as follows:

  • App calls subscribeToMemberStream and passes a callback (last argument) to get notified when we successfully subscribed.

  • Once subscribed, the app's callback is invoked.

  • If there is a network switch, the SDK will start monitoring the stream and watch for data for about 5 seconds. If there is no (or very little) data, we consider the connection lost and the SDK will restart it.

  • If a stream is restarted due to a lack of data, the callback set by the app in subscribeToMemberStream will be invoked, to indicate the restart. This will provide the app with a new ExpressSubscriber (and Renderer if the app requested one).

Based on the options initially passed to subscribeToMemberStream, the app can either let the SDK create the renderer, or the app can create a renderer itself.

  • If the app is letting the SDK manage the renderer, the SDK will stop the renderer and create a new renderer when the stream needs to be restarted.

  • If the app manages the renderer, then the app must make sure to stop and dispose of the old renderer and before creating a new one once it receives a new ExpressSubscriber.

v2020.1.47 Pre-release Notes

Release Date: 2020.08.20

Features/Improvements

  • None

Issues addressed in this release

  • Added observable in RoomChatService that fires individually for each chat message as they come in

  • Android camera reconnection logic

  • Fixes for iOS renderers (includes detaching our render layers when we're done)

  • Other minor fixes to handle TimeShift.seek when time-shift is stopped

v2020.1.43 Pre-release Notes

Release Date: 2020.08.18

Features/Improvements

  • None

Issues addressed in this release

  • Frame-ready API needs to relay frames from time-shifted content when a TimeShift is playing

  • Various fixes

v2020.1.40 Pre-release Notes

Release Date: 2020.08.12

Features/Improvements

  • None

Issues addressed in this release

  • Fix for deadlock when layer resolution changes

  • LimitBandwidth API (on TimeShift).

v2020.1.38 Pre-release Notes

Release Date: 2020.08.07

Features/Improvements

  • None

Issues addressed in this release

  • Support for “click and seek” into a timeshift segment (details on usage below)

  • Timeshift observable playback head reports position in UTC time

  • Timeshift pause and play options

  • Timeshift observable failure report

v2020.1.33 Pre-release Notes

Release Date: 2020.07.16

Features/Improvements

  • None

Issues addressed in this release

  • Includes viewport based HLS layer selection

  • Prefetch window is updated based on layer bitrate for faster switching from very low bitrate layers

  • Includes a fix for iOS, which previously caused image corruption during time-shifted playback

v2020.1.30 Pre-release Notes

Release Date: 2020.07.08

Features/Improvements

  • None

Issues addressed in this release

  • Audio muted status needs to be honored when rendering time-shifted content

  • Add support for Automatic Gain Control

Page Content
    Copyright 2023 © Phenix RTS
    Privacy Policy | Terms of Service
    v2023-01-31T21:25:10