Skip to main content
Skip table of contents

Forensic watermarking

The NexGuard library forensic watermarking tool Quickmark embeds a unique, invisible serial number onto video/audio content.

The minimum Android API for using the watermarking feature is 21 (Lollipop 5.0).
Watermark requires Android System Webview Version 42 or higher to be installed on the device.
Having any UI element rendered over the OTVVideoView  may prevent the watermark from working properly.

Prerequisites

A working watermark requires the following parameters to work correctly:

  • A context to call OTVWatermark constructor
  • A valid OTVVideoView to bind the watermark to
  • A valid customer/system generated token of type String
  • A valid URL of type String
  • A valid Tenant name of type String

The last optional value is to set the ApiKey which is also of type String; this parameter is not mandatory. If these values available, a working QuickMarkView can be created.
The core class of the watermarking function is Watermark. Its purpose is to take the above parameters passed by the user to create a new object of the QuickMarkView class and bind it to the provided OTVVideoView before starting the watermark playback. The class is also responsible for handling error message events and starting and stopping the QuickMarkView whenever video is played or paused.

Dependencies

The Quickmark library (current version 1.1.5) is embedded within the SDK .aar library: there is no need to include or import additional libraries to your project.

Example code

Attaching a watermark is quite simple if you have the five parameters above. Since OTVVideoView is required to bind and unbind the QuickMarkView, we recommend you tie the watermark lifecycle to the OTVVideoView lifecycle. A simple example of implementing the watermark feature is shown below.

Create/bind watermark

JAVA
...
import nagra.otv.sdk.OTVLog;
import nagra.otv.sdk.OTVSDK;
import nagra.otv.sdk.OTVVideoView;
import nagra.otv.sdk.Watermarking.Watermark;
import nagra.otv.sdk.Watermarking.WatermarkErrorId;
import nagra.otv.sdk.Watermarking.WatermarkErrorListener;
import nagra.otv.sdk.Watermarking.WatermarkMessageListener;
...
    private static String TAG = "Watermarking";

    private static String TOKEN      = "TOKEN";
    private static String API_KEY    = "API_KEY";
    private static String TENANT_ID  = "TENANT_ID";
    private static String SERVER_URL = "SERVER_URL";

    private OTVideoView mVideoView = null;
    private Watermark mWatermark


    // your function that creates/initialises your video view.
    // Once the video view is setup you can call watermark to bind it to the player
    private void initVideoView() {
        // The OTVSDK.load() method must be called before the SDK can be used
        // You may wish to do this in an application class
        // OTVSDK expects to find the player licence as an opy_licence in the res/raw directory
        OTVSDK.load(getActivity());
        ...
        mVideoView = (OTVVideoView) xView.findViewById(R.id.otvVideoView);
        //some video view initialising code
        ...
        startWatermark();
    }

    private void startWatermark() {
        mWatermark = new Watermark(getContext());
        mWatermark.addErrorListener(mErrorListener);
        mWatermark.addMessageListener(mMessageListener);
        mWatermark.setToken(TOKEN);
        mWatermark.setApiKey(API_KEY);
        mWatermark.setTenant(TENANT_ID);
        mWatermark.setUrl(SERVER_URL);
        mWatermark.bind(mVideoView);
    }

    /*
    *Create a watermark error listener to react to server watermark responses
    */
    private WatermarkErrorListener mErrorListener = new WatermarkErrorListener() {
        @Override
        public void onError(WatermarkErrorId watermarkErrorId, String s) {
            switch (watermarkErrorId) {
            case INVALID_TOKEN:
            case INVALID_URL:
            case INVALID_SERVER_ANSWER:
            case CANNOT_CONTACT_SERVER:
                yourErrorHandlingFunction(s);
                break;
            case NO_ERROR:
            default:
                noErrorFunction();
            }
        }
    };

    private WatermarkMessageListener mMessageListener = new WatermarkMessageListener() {
        @Override
        public void onMessage(String s) {
            OTVLog.d(TAG, "watermark message: " + s);
            yourMessageHandler(s);
        }
    };

All mWatermark configuration must be set prior to the binding call.

Destroy/unbind watermark

Assuming that the watermark has been constructed as referenced above then the code below should be run when the OTVVideoView is being destroyed to keep the watermark lifecycle matching with the video lifecycle.

JAVA
    private void destroyVideoView() {
      //some video view destruction code
      ...
      stopWatermark();
      mWatermark = null;
    }

    /*
    * stop the watermark view and remove all listeners then unbind the OTVVideoView.
    */
    private void stopWatermark(){
      if(mWatermark != null && mWatermark.boundPlayer() == mVideoView) {
        mWatermark.removeErrorListener(mErrorListener);
        mWatermark.removeMessageListener(mMessageListener);
        mWatermark.unbind(mVideoView);
      }
    }
JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.