Skip to content

Metrics

The Video Analyzer SDK provides comprehensive quality metrics for each analyzed video frame through the SingleFrameMetrics class. Please obtain the actual metric values through the getXXX() methods.

Available Metrics

Note

As this is still in beta, we may add or change metrics in future releases, and the value ranges may be adjusted.

Metric Name Type Value Range Description
getBlockiness() double 0-1 Multi-scale blockiness (0=none, 0.4=noticeable, 0.8 and above=severe)
getBlockinessNtia() double 0-? Blockiness using the NTIA method, raw score (typically 0-0.3)
getBlockinessVp9() double 0-? Blockiness using the VP9 method, raw score (typically 0-100)
getBlurriness() double 0-1 Blurriness using the NTIA method (0=sharp, 1=blurry)
getBlurrinessRaw() double 0-? Blurriness, raw score (approximately 0.5-3.2)
getBrightness() double 0-1 Average luma value
getChroma() double 0-1 Mean distance from grey in the U/V plane (colorfulness)
getContrast() double 0-1 Contrast by ratio of 1st and 99th percentile
getContrastMichelson() double 0-1 Michelson contrast
getSumOfHighFrequencies() double ? Sum of high frequencies based on radial profile
getNoise() double 0-? Noise in the flat areas of the luma plane (0=clean, typically below 10)
getWhiteLevel() double 0-1 Irregular white levels (higher is worse)
getBlackLevel() double 0-1 Irregular black levels (higher is worse)
getFineDetail() double 0-1 High details present (higher is worse)
getSceneScore() double 0-1 Scene change score, based on the luma SAD
getSadNormalized() double 0-1 SAD of the luma plane against the previous frame, normalized
getTemporalInformation() double 0-? Temporal complexity based on ITU-T P.910
getSpatialInformation() double 0-? Spatial complexity based on ITU-T P.910
getJerkiness() double 0-1 Jerkiness based on count of repeated frames in a group (luma SADs)
getBlackScreen() boolean true/false Whether this is a completely black screen
getFreezing() boolean true/false Whether the frame is frozen, based on the luma SAD
getSceneChange() boolean true/false Whether the scene changed, based on the luma SAD

All metrics except chroma are computed on the full-range luma (Y) plane of the frame.

Metric Details

Chroma

getChroma() is the mean distance from grey in the U/V plane, as a vectorscope shows it. For each chroma sample, the distance sqrt((U - 128)² + (V - 128)²) is divided by its largest possible value (128 * sqrt(2)), and the result is the mean over all chroma samples (a quarter of the number of luma samples for 4:2:0 video). U and V are in full range with 128 as the neutral value.

Grey pictures have a chroma of 0. Unlike the HSV saturation, chroma is not divided by the brightness, so dark scenes with little noise or a small color cast near black do not get a high value.

Chroma replaces the former saturation metric (the mean of the S channel of HSV), which scored dark scenes as strongly saturated.

Noise

getNoise() estimates the noise in the source, that is grain or sensor noise that was in the video before encoding. It uses the method of VIQET on the luma plane: the local standard deviation with a Gaussian window (the window size is 1/120 of the picture height), of which the mean of the lowest 0.5 % of the values above 0.00001 is returned. These values come from the flattest areas of the picture. The value is in units of 8-bit luma levels. A clean picture gives a value close to 0; a flat grey picture with FFmpeg's noise filter at strength 10, 20 and 40 gives about 1.2, 2.6 and 5.3. On clean pictures with very flat areas (for example graphics), the value is determined by the edges and small steps of the flattest areas instead of noise.

The metric is meant for sources and mezzanine files. On encoded video, it reports the noise that is left after encoding, which is usually lower than in the source, because encoders remove noise. It does not measure encoding artifacts such as mosquito noise, which appear next to edges and not in flat areas. Noise that is only in the chroma planes is not measured.

Temporal Metrics

The temporal metrics compare frames on the luma plane:

  • getSadNormalized() is the sum of absolute differences (SAD) of the luma planes of the frame and the previous frame, divided by the number of pixels and 255. Identical frames have a value of exactly 0.
  • getSceneScore() is the difference between the normalized SAD of the frame and that of the previous frame, but at most the normalized SAD of the frame.
  • getFreezing() is true if the normalized SAD is at most 0.00001, that is if the frame is identical or almost identical to the previous frame. Repeated frames in encoded video are often not bit-identical (the encoder codes them with small changes) and are then only flagged if the changes are very small. A higher threshold would flag static pictures with small moving parts, such as a slide with a running clock.
  • getSceneChange() is true if the scene score is at least 0.1.
  • getJerkiness() counts similar values among the z-normalized SADs between the frame and the previous frames.

Spatial and Temporal Information

getSpatialInformation() and getTemporalInformation() follow the legacy (non-HDR) SI/TI definition from ITU-T Rec. P.910, matching the reference implementation in siti-tools. Both metrics operate on the luma plane. The analyzer treats input as limited-range expanded to full, and the values match siti-tools in its limited-range legacy mode.

Checking Metric Availability

Not all metrics may be available for every frame. Always check availability before using metric values:

Method 1: Using Has Methods

public void processMetrics(SingleFrameMetrics metrics) {
    // Check availability before using
    if (metrics.hasBlurriness()) {
        double blur = metrics.getBlurriness();
        // use blur value
    }

    if (metrics.hasBrightness()) {
        double brightness = metrics.getBrightness();
        // use brightness value
    }

    if (metrics.hasTemporalInformation()) {
        double temporal = metrics.getTemporalInformation();
        // use temporal value
    }
}

Method 2: Checking for NaN Values

public void processMetrics(SingleFrameMetrics metrics) {
    // Metrics return NaN if not available
    double contrast = metrics.getContrast();
    if (!Double.isNaN(contrast)) {
        // use contrast value
    }

    double noise = metrics.getNoise();
    if (!Double.isNaN(noise)) {
        // use noise value
    }
}

Performance and Selective Metric Calculation

Processing all metrics for every frame can be resource-intensive. Consider:

  • Sampling frames (analyze every Nth frame)
  • Selective metric calculation based on use case (see below)
  • Adjusting analysis frequency based on device performance

The VideoAnalyzer SDK supports selective calculation of metrics to improve performance when you only need specific measurements. This can significantly reduce CPU usage and battery consumption on mobile devices.

Enabling Specific Features Only

To calculate only specific metrics, pass the names of the features to compute when creating the VideoAnalyzerManager (requires a version newer than 0.12.0):

import com.aveq.videoanalyzer.VideoAnalyzerManager;
import java.util.Arrays;

// Only these features will be calculated
VideoAnalyzerManager manager = new VideoAnalyzerManager(
    context,
    30.0, // fps
    Arrays.asList("blurriness", "blockiness", "brightness"),
    null  // no disabled features
);

Disabling Specific Features

To calculate all metrics except certain ones, pass the names of the features to skip instead:

import java.util.Arrays;

VideoAnalyzerManager manager = new VideoAnalyzerManager(
    context,
    30.0, // fps
    null, // all features
    Arrays.asList("noise", "radialprofile") // except these
);

VideoAnalyzerManager.getAvailableFeatures() returns the list of valid names. Unknown names throw an IllegalArgumentException.

The following feature names can be used for selective calculation:

  • blockiness: blockiness, blockiness_ntia, blockiness_vp9
  • blurriness: blurriness, blurriness_raw
  • brightness: brightness
  • blackscreen: black_screen
  • chroma: chroma
  • contrast: contrast, contrast_michelson
  • radialprofile: sum_of_high_frequencies
  • noise: noise
  • autoenhancement: white_level, black_level
  • finedetail: fine_detail
  • temporalchange: freezing, scene_change, scene_score, sad_normalized, temporal_information
  • spatialcomplexity: spatial_information
  • jerkiness: jerkiness