Android Examples
GitHub Examples
You can find our Android examples on GitHub:
Override Playout Delay
Example Code for overriding the playout delay via a MediaStream object
import com.phenixrts.common.Disposable;
import com.phenixrts.pcast.MediaStream;
import com.phenixrts.pcast.Renderer;
class SomeClass {
private Disposable currentRendererPlayoutDelayOverride;
private Renderer currentRenderer;
private void setPlayoutDelayOverrideFor10Seconds() {
final MediaStream mediaStream = ...; // Previously obtained
this.currentRenderer = mediaStream.createRenderer();
// Override playout delay to 900ms for 10 seconds
final long playoutDelayInMilliseconds = 900
this.currentRendererPlayoutDelayOverride = this.currentRenderer.overridePlayoutDelay(playoutDelayInMilliseconds);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
SomeClass.this.currentRendererPlayoutDelayOverride.dispose();
SomeClass.this.currentRendererPlayoutDelayOverride = null;
}
}, 10000);
}
}
Example Code for limiting video bandwidth with a ExpressSubscriber object
import com.phenixrts.common.Disposable;
import com.phenixrts.express.ExpressSubscriber;
import com.phenixrts.pcast.Renderer;
class SomeClass {
private Disposable currentRendererPlayoutDelayOverride;
private Renderer currentRenderer;
private void setPlayoutDelayOverrideFor10Seconds() {
final ExpressSubscriber subscriber = ...; // Previously obtained
this.currentRenderer = subscriber.createRenderer();
// Override playout delay to 900ms for 10 seconds
final long playoutDelayInMilliseconds = 900
this.currentRendererPlayoutDelayOverride = this.currentRenderer.overridePlayoutDelay(playoutDelayInMilliseconds);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
SomeClass.this.currentRendererPlayoutDelayOverride.dispose();
SomeClass.this.currentRendererPlayoutDelayOverride = null;
}
}, 10000);
}
}
The playout delay represents the amount of time by which audio and video are delayed when content is rendered by a subscriber; i.e. it works as a buffer. The delay adds to the overall end-to-end latency experienced by the user (on top of capture, encoding, and network latencies). It is necessary to handle network-related fluctuations (such as jitter or data loss). By default, the playout delay for real-time streams is set to 230ms. The following API allows app developers to override this default value.
In order to access the API, a reference to a Renderer
is needed. It can be obtained either by creating it from
MediaStream
or ExpressSubscriber
, or via several of the Express APIs, which can return renderers
(joinChannel,
subscribeToMemberStream,
subscribe).
The returned disposable allows control over how long the override should stay in effect; it therefore needs to be held onto via a strong reference. If overridePlayoutDelay
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. Releasing any of the disposables from earlier overridePlayoutDelay
calls will have no effect.
Notes:
- The override represents an absolute value, not a delta.
- If an override increases the playout delay, it will result in content being paused. Example: changing a delay of 1 second to 5 seconds will cause the content to be paused for roughly 4 seconds.
- If an override decreases the playout delay, it will cause a jump where some of the content will be skipped.
- Very large override values will increase the amount of memory consumed. It is generally recommended to stay below 10 seconds.
Parameters
Name | Type | Description |
---|---|---|
desiredPlayoutDelayInMilliseconds (required) | long | Desired playout delay |
Returns
Type | Description |
---|---|
Disposable | Ensures override is kept in effect for as long as a strong reference is held |
Set Camera Focus Position
In addition to the information below, see API details for Focus Modes and Focus Target.
When publishing from the device camera, the focal length can be configured by using focus modes.
Configure a focus target to set an area for the camera focus. A focus target is expressed in
video source frame coordinates.
Obtain the video source coordinates by calling Renderer.convertRenderPreviewCoordinatesToSourceCoordinates
with the renderer
currently showing the video preview.
A focus target is specified in relative frame coordinates, which range from 0 to 1 on both the X and Y axis. For example, a (x, y) coordinate focus target of (0.5, 0.5) would specify the camera to focus in the middle of the captured source frame.
Set the focus target by updating the DeviceCapabilities of the UserMedia used in the application.
The AUTO_FOCUS_TARGET
constraint can be set only if the AUTO_FOCUS_MODE
constraint has been
set to AUTO_THEN_LOCKED
or MACRO
.
When using touch on a mobile screen, the SDK offers a helper function to translate from touch coordinates to frame relative coordinates (x and y):
val relativeCoordinates = renderer.convertRenderPreviewCoordinatesToSourceCoordinates(com.phenixrts.pcast.Point(x, y))
Once a focus target has been set, the focus distance will be locked until changed. To reset the focus distance, either set a new target or change the focus mode.
// X and Y must be the coordinates in pixels relative to the surface being rendered.
val x = // From touch event handler
val y = // From touch event handler
// Make relative coordinates using the current renderer.
val relativeCoordinates = renderer.convertRenderPreviewCoordinatesToSourceCoordinates(com.phenixrts.pcast.Point(x, y))
// Update the current user media options
// It is recommended to make a copy of the options. This way, the focus can be reset easily by restoring the previous options.
var userMediaOptions = // Copy of currently active options
userMediaOptions.videoOptions.capabilityConstraints[DeviceCapability.AUTO_FOCUS_MODE] = listOf(DeviceConstraint(AutoFocusMode.AUTO_THEN_LOCKED))
userMediaOptions.videoOptions.capabilityConstraints[DeviceCapability.AUTO_FOCUS_TARGET] = listOf(DeviceConstraint(relativeCoordinates))
// Apply the options
val status = userMediaStream.applyOptions(userMediaOptions)
// Verify the status
// Setting a focus target can fail for example when:
// - The current focus mode does not support setting a focus target.
// - The current video capture device does not support setting a focus target.
// - The coordinates were invalid (e.g. outside of the render surface)
if (status == RequestStatus.OK) {
// For example, show a visual indication of where the focus was set.
}
[...]
// Reset the focus mode to keep the video in focus for example if the device moved.
var userMediaOptions = // Currently active options
userMediaOptions.videoOptions.capabilityConstraints[DeviceCapability.AUTO_FOCUS_MODE] = listOf(DeviceConstraint(AutoFocusMode.AUTOMATIC))
userMediaStream.applyOptions(userMediaOptions)