The CONNECT Player for Android SDK 5.x (SDK5) is NAGRA’s latest player product for Android. Although the architecture has changed, the API remains similar to the previous version (Nagra Media Player SDK for Android 4.x* (SDK4).
Internally, the main difference in the architecture is the use of ExoPlayer as the basic player instead of a native player.
Along with this document which highlights the differences, we advise you to follow the Android SDK 5 Example Code Quick Start guide and try to build some of the example code demos.

Integration differences

Many of the API changes are in the naming of the packages, classes and methods. Although there are still two main classes providing access to a CONNECT player instance - OTVVideoView and OTVMediaPlayer, there are some other differences you should be aware of.

Area of difference SDK4 SDK5
SDK Name NMPSDK OTVSDK
SDK library type .jar .aar
Public classes and method names NMPXxx OTVXxx
Package root name nagra.nmp.sdk nagra.otv.sdk
Supported OS Versions 4.4+ 5.0+
Android SDK API 23: Android 6.0 (Marshmallow) API 28: Android 9.0 (Pie)
Java compiler 1.8.0 1.8.0
Android Plugin version 2.2.2 Latest (3.5.0)
Gradle Plugin version 2.14.1 Latest (5.5.1)
DRM Widevine
PRM
Widevine
PlayReady
PRM (non-silent mode)
Multi-instance No Yes*
AndroidX dependency No Yes
Room persistence library dependency No Yes

*Some device hardware does not support decoding of multi-instance encrypted content.

SDK5 uses different external modules to those used by SDK4. Those modules are brought into the build project by declaring the dependencies in the Gradle files. See the Android SDK 5 Integration Guide and the package release notes for full details of those dependencies.

Setting the OTVVideoView

Unlike SDK4, the OTVVideoView can and should be created dynamically, not during the creation of the Activity. This allows OTVVideoView to be attached to a UI frame and also enables you to make use of multiple player instances (e.g. for PiP).

Setting up playback

 String STREAM_URI = "https://path-to-stream/manifest.mpd";
FrameLayout theFrame = findViewById(R.id.frame);
OTVVideoView theView = new OTVVideoView(this);

// Loading the SDK and validating licence
OTVSDK.load(this);

// Set-up player and UI
theView.setVideoPath(STREAM_URI);
theFrame.addView(theView);

// Start/resume playback
theView.start();

 

The OTVVideoView lifespan is therefore aligned with that of the player. Also, when zapping, setVideoPath() can be called rather than destroying a view and replacing it with a new one.

Main UI thread for capturing events

Except for the naming conventions described above, events sent from the SDK and registering for listeners, are performed in a similar way as for SDK4. However, to ensure all events are captured, setting-up of the listeners must be done from the main UI thread. This should not be an issue in normal circumstances where the listeners are set-up during an Activity’s onCreate(), or following an interaction with the user via the UI.

Example of setting-up a listener

 public class MainActivity extends Activity {
  ...
  @Override
  protected void onCreate(Bundle savedInstanceState) {
  ...
  OTVSDK.load(this);
  
  // inside onCreate()
  OTVVideoView theView = new OTVVideoView(this);
  ...
  // Setting up a listener for onCompletion
  theView.setOnCompletionListener(mp -> {
    Toast.makeText(this,"PLAYBACK END",
                    Toast.LENGTH_LONG).show();
  });
  ...
  // Set-up URL and start playback
  ...
  }
...

 

DRM - Widevine

Use of Widevine DRM is simplified; you now only need to implement the OTVMediaDrmCallback interface and provide a licence server URL. SDK5 also provides a default implementation of the OTVMediaDrmCallback interface: OTVHttpMediaDrmCallback.

When creating the OTVMediaDrmCallback interface implementation, the application passes the licence server URI in the constructor. Extra parameters can then be passed to this object in key-value pairs, using the setKeyRequestProperty(String name, String value) method, such as Content-Type or Accept. The callback class object can be instantiated once for each player, and some properties can be changed whenever a new asset with its own credentials needs to be played.

Example: See the encrypted playback example code provided in the SDK5 package.
If the callbacks provided by the SDK do not meet the requirements for a specific server, you can create a customised version of the callback class.

Example: See the customised encrypted playback example code provided in the SDK5 package.

DRM - PlayReady

PlayReady support is introduced in SDK5 (version 5.5.0). Set-up for playback with PlayReady is very similar to the one for Widevine; the same OTVHttpMediaDrmCallback callback implementation can be used. Within this implementation, some configuration is slightly different to the one for Widevine.

Example: See the encrypted playback example code for PlayReady provided in the SDK5 package.

Offline support for PlayReady streams is not yet supported.

DRM - PRM

Nagra provides two flavours of the SDK library: One that supports PRM and another without this support.

Similar to Widevine, you now only need to implement the OTVPRMNonSilentCallback interface and provide licence server credentials. SDK5 provides a default implementation of the OTVPRMNonSilentCallback interface- OTVSSPPRMNonSilentCallback for communication with SSP licence servers (NAGRA’s Secure Service Platform) in Non-silent Direct Mode. Alternatively, you may implement the callback interface for your own licence server and portal in Non-silent Indirect mode.

Non-silent Direct mode, where both licences and keys are fetched by PAK is no longer supported.

For specific details see the Nagra PRM-protected playback integration page.
Example: See the encrypted playback example code provided in the SDK5 package.

Lifecycle

As SDK5 supports multiple instances, static objects (apart from some string constants) have been removed. When zapping, you have the choice of either recycling the player instance, or passing a new stream URL (and with encrypted content, updating the DRM callback class).

Certain situations such as rotation, move to the background and back etc, may cause the activity to be destroyed with onDestroy() event and re-created with onCreate() event. In such cases, when resuming, playback would start from the beginning of the asset rather than from where playback was interrupted. However, this is not the desired behaviour; the solution to this is listening to configuration changes (onConfigurationChanged()) and handling the configuration changes in the activity. When implementing the onConfigurationChanged() override, detach the player from its parent (which is going to be destroyed) and attach it to a new view.

  1. In the application manifest (AndroidManifest.xml) add a configChanges setting for the activity owning the player:

     ...
    <activity android:name=".MainActivity"
        android:configChanges="orientation|screenSize">
    ...
    
     
  2. In the activity controlling the player, add an overriding onConfigurationChanged() as per the code below.

       @Override
      public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (mOTVVideoView.getParent() != null) {
          ViewGroup parent = (ViewGroup) mOTVVideoView.getParent();
          parent.removeView(mOTVVideoView);
        }
        mFrame.addView(mOTVVideoView);
      }
    
     

An example of this implementation can be found in the example code for basic playback provided in this package.
See also Handling the configuration change yourself in the Android Developers site.

getSeekableRangeInfo() in Live streams

getSeekableRangeInfo() provides a pair of long integers indicating the start and end time of playable content in the stream to which a seekTo() operation can be performed. The range for VoD is usually between 0 and the duration. In SDK4 the Live stream range is between a negative number (past) and zero (current live point); whereas in SDK5, the range values are always positive, and 0 signifies the earliest time available to seek back to.

setVolume()

In SDK4, setVolume() used to set the system volume. As SDK5 now supports multiple instances, setVolume() sets the playback volume for the specific player instance.

Subtitle rendering settings (nagra.nmp.sdk.subtitle.settings package)

The entire nagra.nmp.sdk.subtitle.settings package has been deprecated. System-wide settings for the device now control subtitles appearance (colours, size, style).

Setting debug levels for logs

The method setDebugLogs() in OTVVideoView has been deprecated. For setting log levels, please use OTVLog.setLogLevel(int logLevel) and OTVLog.logLevel(). The log level options are:

  • LOG_LEVEL_INFO (default for production versions of the library)
  • LOG_LEVEL_DEBUG
  • LOG_LEVEL_VERBOSE (default for integration versions of the library)

Warning and Critical/Error logs are always produced from the SDK, along with some support critical messages.

Resolution/bitrate capping

A new cap applied while a stream is already playing is applied immediately (as opposed to a cap only on future downloaded segments). The playback buffers are flushed, and data is downloaded again, causing a slight interruption in playback.

Advertising with Google IMA

Users of IMA on SDK4 should note these subtle differences when migrating:

  • There is no longer any need for the IMAWrapperSettingsBuilder class due to adopting a later IMA version with an API deprecation.
  • There is no need for the allowance of the video view in the layout as its created dynamically.

Offline playback (Download to Go)

SDK5 maintains the same approach as SDK4 with regards to offline playback steps:

  • After user selection, a stream is analysed until it is PREPARED
  • A video bitrate to download is selected, and that video (along with all other tracks) is downloaded
  • Decryption keys are fetched at the start of the download
  • Downloading can be paused and resumes after the start of the download
  • Playback of the downloaded content can start after sufficient data is downloaded

Additional capabilities introduced in SDK5:

  • Support for offline playback of encrypted DASH streams
  • Download can be done in the background as a service

Due to the different architecture of SDK5, assets that have been marked for download and are in the PREPARED state (where the bitrate has not yet been selected and actual download not started) will not persist. If the application terminates and restarts, the PREPARED downloads will be removed. Although preparing and starting downloads are separate steps, we recommend that the application combines the two into a single step. See, for example, the offline-service example code.

Examples: See the various example code snippets provided for implementation of offline playback for DASH+Widevine, HLS+PRM, and Downloading content in an Android Service.

Offline playback for PlayReady-encrypted streams is not yet supported. Also, streams with multiple decryption keys are not currently supported (only one key is stored per stream).

The Offline feature has been completely revised. The internal structure of stored content in SDK5 is different from SDK4. Content already downloaded with SDK4 is not playable with SDK5. Moreover, to maintain storage integrity, an application moving from SDK4 to SDK5 must remove the old stored content. On the other hand, there is now support for storing offline content of both HLS streams with PRM protection and DASH streams with Widevine DRM (PlayReady not yet supported).

  • Although OTVDownloadManager is not a singleton, it is not necessary to instantiate it more than once. A listener implementing OTVDownloadListener must be provided when instantiating OTVDownloadManager.
  • Multiple downloads can now run concurrently
  • Download continues when the application is in the background
  • Multiple subtitles and audio tracks are stored for each content for future playback
  • Thumbnails are not available in offline playback

External Subtitles

In SDK4 external SRT subtitles can be added to a playing stream anytime; with SDK5 such subtitles should be added to the player as soon as the playback URL is set (adding them later will reset playback to the beginning).

Subtitles’ text configuration

In SDK4, the configuration of text-based subtitles ( colour, typeface, size, etc.) is configurable via the SDK; SDK5 uses the device’s system configuration to align with other services and applications.

Summary of feature differences

With the new SDK, some features are not yet implemented (and some are implemented only for the newer product). The table below compares the two versions’ features and will be updated for each release.

Feature SDK4 SDK5
HLS Streaming Yes (+PRM) Yes (+PRM)
DASH Streaming No Yes (+Widevine, PlayReady)
DRM Security Levels No Yes
HEVC decoding Yes Yes
Multi-instance/PiP No Yes*
Multiple audio tracks (HLS) Yes Yes**
Multiple audio tracks (DASH) Yes Yes
Multiple video tracks (DASH) No Yes
Subtitles (HLS) CC608
CC708
WebVTT
SMPTE-TT over ID3
SRT
CC608
CC708
WebVTT
SMPTE-TT
SRT
Subtitles (DASH) CC608
CC708
WebVTT
SMPTE-TT over ID3
SRT
CC608
CC708
WebVTT
SMPTE-TT
SRT
Hardware/Software decoding Both Device supported codecs only
NexGuard Forensic Watermarking Yes (1.1.5) Yes (1.1.5)
Insight Analytics Yes Yes
Advertising with Google IMA Yes Yes
Offline playback HLS Only DASH (+Widevine)***
HLS (+PRM)
Resolution/bitrate capping Yes Yes
Device Calibration Yes Future
Output Control Yes Future
Thumbnail previews Yes (vtt) Yes (DASH-IF)
Scale-with-crop video Yes Yes
Playback startup and zapping metrics No Yes

*Some device hardware decoders will prevent concurrent playback of multiple video streams. There are also limitations on simultaneous playback of multiple HLS+PRM streams.
**If multi-audio tracks are on same MPEG2 TS with video, then only the default track can be selected.
*** Offline playback for PlayReady streams not yet available.