Player Debugging

Player Debugging

This chapter covers some details related to the DebugPlugin, a module that attaches to the PlayerController and logs relevant information that helps troubleshoot stream issues.

Adding to the project

The plugin is distributed with the SDK and you can add it as a dependency in your gradle file:

dependencies {
    ...
    compile 'com.castlabs.player:debug-plugin:4.2.0'
    ...
}

Once added you can register it with the SDK. The DebugPlugin must be created with its builder.

public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        PlayerSDK.register(new DebugPlugin.Builder().logAll(true).get());
        PlayerSDK.init(getApplicationContext());
    }
}

Note that here we are enabling all the debugging options. You can also pick whatever debug options you desire with the same Builder. Please refer to the Javadocs for more info.

Graphics

This plugin also provides debugging views that will graph player metrics. There’s a default debugging overlay which can be enabled in the DebugPlugin with the debugOverlay method.

You can also optionally build your own layout and choose what information to display. This is explained in the following section.

Charts

The DebugPlugin provides two charts:

These two Graphs can be used as common Android Views in an xml file.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <com.castlabs.sdk.debug.view.PlayerStateChart
        android:id="@+id/stateChart"
        android:layout_alignParentTop="true"
        android:layout_width="match_parent"
        android:layout_height="50dp"/>
    <com.castlabs.sdk.debug.view.PlayerMetricChart
        android:layout_below="@id/stateChart"
        android:id="@+id/metricChart"
        android:layout_width="match_parent"
        android:layout_height="300dp"/>
</RelativeLayout>

Then, the charts must be configured and provided with a PlayerController.

// State plot
stateChart = chartsView.findViewById(R.id.stateChart);

// Metric plot, will show bandwidth estimation and player buffer
metricChart = chartsView.findViewById(R.id.metricChart);
metricChart.enableMetrics(PlayerMetricChart.METRIC_ABR_BANDWIDTH_ESTIMATION
        | PlayerMetricChart.METRIC_BUFFER_AHEAD);

// Bind to PlayerController
stateChart.setPlayerController(playerController);
metricChart.setPlayerController(playerController);

When the host view is not visible anymore, you should unbind the Charts from the PlayerController

stateChart.unsetPlayerController();
metricChart.unsetPlayerController();

PlayerMetricChart and Metrics

PlayerMetricChart is a powerful class that can plot the outputs of any Metric.

A Metric provides the required underlying infrastructure to interact with the PlayerMetricChart and the necessary data to it. You can create additional Metrics by extending this class.

In order to enable a set of desired metrics in the PlayerMetricChart you can use the enableMetrics passing one or more of the PlayerMetricChart.METRIC_* constants.

// Metric plot, will show bandwidth estimation and player buffer
metricChart.enableMetrics(PlayerMetricChart.METRIC_ABR_BANDWIDTH_ESTIMATION
        | PlayerMetricChart.METRIC_BUFFER_AHEAD);

If you want more control over how such Metric``s are displayed, you can create them yourself and add them to the ``PlayerMetricChart.

metricChart.addMetric(new BandwidthMetric(Color.BLUE, YAxis.AxisDependency.LEFT));
metricChart.addMetric(new PlayingQualityMetric(Color.BLUE, YAxis.AxisDependency.LEFT));
metricChart.addMetric(new ChunkDownloadTimeMetric(Color.BLUE, YAxis.AxisDependency.RIGHT, ChunkDownloadTimeMetric.MODE_VIDEO));

You can add any number of Metric to the chart.

Metric creation

You can also create your own Metric for a PlayerMetricChart to display.

To do this, you should extend the Metric class and override its abstract methods.

In addition to the abstract methods, you have access to the following:

  • addTimedDataPoint(float). Main data input. Use this method to add a data point to this metric.

  • dataSet. You can use this protected property to modify the underlying dataSet, right after calling the super constructor.

  • Configuration overridable methods, replicateLastValue(), keepLastDroppedValue() and extendToRightEdge().

Please refer to the appropriate Javadocs to get more details about Metric creation.

AV Sync

Plugin can measure AV sync values and calculate streaming mean and standard deviation values of it.

Consider audio component having aPTS that should be rendered at System time aSysTime and video component having vPTS and vSysTime. Assume AV components are encoded correctly i.e. when aPTS and vPTS have the same value then rendering at the same time does not produce any UX AV sync issues. In reality, aSysTime and vSysTime are always different, even if scheduled to be the same. The delta is considered to be AV sync value and is usually within the duration of 1-2 video frames.

Plugin measures AV sync per each video frame and calculates scheduled and actual (released) values. Scheduled means the calculated or desired render time and actual is when the video and audio frames are actually rendered. The following AV sync values are logged:

  • Calculated value per video frame

  • Min and max values

  • Streaming (accumulated) mean and

  • Streaming (accumulated) standard deviation

public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        long logAVSyncThresholdUs = 1000000L;          // log AVsync values exceeding 1sec, per video frame
        long logMeanAndDeviationPeriodUs = 1000000L;   // log min, max, mean and deviation every 1sec

        PlayerSDK.register(new DebugPlugin.Builder()
            .logVideoFrameMetadata(true, logAVSyncThresholdUs, logMeanAndDeviationPeriodUs)
            .get()
        );

        PlayerSDK.init(getApplicationContext());
    }
}

Generic Logging in Builds

The Log level of the SDK can be configured using the following API in the PlayerSDK to one of the following values,

android.util.Log#VERBOSE android.util.Log#DEBUG android.util.Log#INFO android.util.Log#WARN android.util.Log#ERROR android.util.Log#ASSERT

public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        PlayerSDK.setLogLevel(sdkLogLevel)
    }
}

Known Compatibility Issues

When using the OKHTTPClient logger, the configuration HttpLoggingInterceptor.Level.BODY <https://square.github.io/okhttp/3.x/logging-interceptor/okhttp3/logging/HttpLoggingInterceptor.Level.html> interferes with the Bandwidth estimation algorithm of the SDK thereby causing rendition switches to malfunction and therefore must be avoided.

Third party acknowledgement

The DebugPlugin uses and distributes a copy of the MPAndroidChart library which is under the Apache License 2.0.

Previous topic: Extensions and Plugins
Next topic: Example Projects