# 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.3.2'
        ...
    }

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:

> - `PlayerStateChart`. Shows a horizontal player state graph.

> - `PlayerMetricChart`. Shows a line graph displaying one or more Metrics.

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