1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.android.exoplayer2.decoder; 17 18 /** 19 * Maintains decoder event counts, for debugging purposes only. 20 * <p> 21 * Counters should be written from the playback thread only. Counters may be read from any thread. 22 * To ensure that the counter values are made visible across threads, users of this class should 23 * invoke {@link #ensureUpdated()} prior to reading and after writing. 24 */ 25 public final class DecoderCounters { 26 27 /** 28 * The number of times a decoder has been initialized. 29 */ 30 public int decoderInitCount; 31 /** 32 * The number of times a decoder has been released. 33 */ 34 public int decoderReleaseCount; 35 /** 36 * The number of queued input buffers. 37 */ 38 public int inputBufferCount; 39 /** 40 * The number of skipped input buffers. 41 * <p> 42 * A skipped input buffer is an input buffer that was deliberately not sent to the decoder. 43 */ 44 public int skippedInputBufferCount; 45 /** 46 * The number of rendered output buffers. 47 */ 48 public int renderedOutputBufferCount; 49 /** 50 * The number of skipped output buffers. 51 * <p> 52 * A skipped output buffer is an output buffer that was deliberately not rendered. 53 */ 54 public int skippedOutputBufferCount; 55 /** 56 * The number of dropped buffers. 57 * <p> 58 * A dropped buffer is an buffer that was supposed to be decoded/rendered, but was instead 59 * dropped because it could not be rendered in time. 60 */ 61 public int droppedBufferCount; 62 /** 63 * The maximum number of dropped buffers without an interleaving rendered output buffer. 64 * <p> 65 * Skipped output buffers are ignored for the purposes of calculating this value. 66 */ 67 public int maxConsecutiveDroppedBufferCount; 68 /** 69 * The number of times all buffers to a keyframe were dropped. 70 * <p> 71 * Each time buffers to a keyframe are dropped, this counter is increased by one, and the dropped 72 * buffer counters are increased by one (for the current output buffer) plus the number of buffers 73 * dropped from the source to advance to the keyframe. 74 */ 75 public int droppedToKeyframeCount; 76 /** 77 * The sum of video frame processing offset samples in microseconds. 78 * 79 * <p>Video frame processing offset measures how early a video frame was processed by a video 80 * renderer compared to the player's current position. 81 * 82 * <p>Note: Use {@link #addVideoFrameProcessingOffsetSample(long)} to update this field instead of 83 * updating it directly. 84 */ 85 public long totalVideoFrameProcessingOffsetUs; 86 /** 87 * The number of video frame processing offset samples added. 88 * 89 * <p>Note: Use {@link #addVideoFrameProcessingOffsetSample(long)} to update this field instead of 90 * updating it directly. 91 */ 92 public int videoFrameProcessingOffsetCount; 93 94 /** 95 * Should be called to ensure counter values are made visible across threads. The playback thread 96 * should call this method after updating the counter values. Any other thread should call this 97 * method before reading the counters. 98 */ ensureUpdated()99 public synchronized void ensureUpdated() { 100 // Do nothing. The use of synchronized ensures a memory barrier should another thread also 101 // call this method. 102 } 103 104 /** 105 * Merges the counts from {@code other} into this instance. 106 * 107 * @param other The {@link DecoderCounters} to merge into this instance. 108 */ merge(DecoderCounters other)109 public void merge(DecoderCounters other) { 110 decoderInitCount += other.decoderInitCount; 111 decoderReleaseCount += other.decoderReleaseCount; 112 inputBufferCount += other.inputBufferCount; 113 skippedInputBufferCount += other.skippedInputBufferCount; 114 renderedOutputBufferCount += other.renderedOutputBufferCount; 115 skippedOutputBufferCount += other.skippedOutputBufferCount; 116 droppedBufferCount += other.droppedBufferCount; 117 maxConsecutiveDroppedBufferCount = Math.max(maxConsecutiveDroppedBufferCount, 118 other.maxConsecutiveDroppedBufferCount); 119 droppedToKeyframeCount += other.droppedToKeyframeCount; 120 121 addVideoFrameProcessingOffsetSamples( 122 other.totalVideoFrameProcessingOffsetUs, other.videoFrameProcessingOffsetCount); 123 } 124 125 /** 126 * Adds a video frame processing offset sample to {@link #totalVideoFrameProcessingOffsetUs} and 127 * increases {@link #videoFrameProcessingOffsetCount} by one. 128 * 129 * <p>Convenience method to ensure both fields are updated when adding a sample. 130 * 131 * @param sampleUs The sample in microseconds. 132 */ addVideoFrameProcessingOffsetSample(long sampleUs)133 public void addVideoFrameProcessingOffsetSample(long sampleUs) { 134 addVideoFrameProcessingOffsetSamples(sampleUs, /* count= */ 1); 135 } 136 addVideoFrameProcessingOffsetSamples(long sampleUs, int count)137 private void addVideoFrameProcessingOffsetSamples(long sampleUs, int count) { 138 totalVideoFrameProcessingOffsetUs += sampleUs; 139 videoFrameProcessingOffsetCount += count; 140 } 141 } 142