Commit 25a53265 by Oliver Woodman

Optimize some CodecCounter inefficiency.

1. Use ints rather than longs.
2. Remove some counters that dont seem hugely useful.
3. Replace use of volatile with explicit method calls that
   cause a memory barrier. This is a lot more efficient than
   using volatile because it can be invoked only once per
   doSomeWork.
parent 9a124120
...@@ -17,54 +17,41 @@ package com.google.android.exoplayer; ...@@ -17,54 +17,41 @@ package com.google.android.exoplayer;
/** /**
* Maintains codec event counts, for debugging purposes only. * Maintains codec event counts, for debugging purposes only.
* <p>
* Counters should be written from the playback thread only. Counters may be read from any thread.
* To ensure that the counter values are correctly reflected between threads, users of this class
* should invoke {@link #ensureUpdated()} prior to reading and after writing.
*/ */
public final class CodecCounters { public final class CodecCounters {
public volatile long codecInitCount; public int codecInitCount;
public volatile long codecReleaseCount; public int codecReleaseCount;
public volatile long outputFormatChangedCount; public int outputFormatChangedCount;
public volatile long outputBuffersChangedCount; public int outputBuffersChangedCount;
public volatile long queuedInputBufferCount; public int renderedOutputBufferCount;
public volatile long inputBufferWaitingForSampleCount; public int skippedOutputBufferCount;
public volatile long keyframeCount; public int droppedOutputBufferCount;
public volatile long queuedEndOfStreamCount;
public volatile long renderedOutputBufferCount;
public volatile long skippedOutputBufferCount;
public volatile long droppedOutputBufferCount;
public volatile long discardedSamplesCount;
/** /**
* Resets all counts to zero. * Should be invoked from the playback thread after the counters have been updated. Should also
* be invoked from any other thread that wishes to read the counters, before reading. These calls
* ensure that counter updates are made visible to the reading threads.
*/ */
public void zeroAllCounts() { public synchronized void ensureUpdated() {
codecInitCount = 0; // Do nothing. The use of synchronized ensures a memory barrier should another thread also
codecReleaseCount = 0; // call this method.
outputFormatChangedCount = 0;
outputBuffersChangedCount = 0;
queuedInputBufferCount = 0;
inputBufferWaitingForSampleCount = 0;
keyframeCount = 0;
queuedEndOfStreamCount = 0;
renderedOutputBufferCount = 0;
skippedOutputBufferCount = 0;
droppedOutputBufferCount = 0;
discardedSamplesCount = 0;
} }
public String getDebugString() { public String getDebugString() {
ensureUpdated();
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("cic(").append(codecInitCount).append(")"); builder.append("cic(").append(codecInitCount).append(")");
builder.append("crc(").append(codecReleaseCount).append(")"); builder.append("crc(").append(codecReleaseCount).append(")");
builder.append("ofc(").append(outputFormatChangedCount).append(")"); builder.append("ofc(").append(outputFormatChangedCount).append(")");
builder.append("obc(").append(outputBuffersChangedCount).append(")"); builder.append("obc(").append(outputBuffersChangedCount).append(")");
builder.append("qib(").append(queuedInputBufferCount).append(")");
builder.append("wib(").append(inputBufferWaitingForSampleCount).append(")");
builder.append("kfc(").append(keyframeCount).append(")");
builder.append("qes(").append(queuedEndOfStreamCount).append(")");
builder.append("ren(").append(renderedOutputBufferCount).append(")"); builder.append("ren(").append(renderedOutputBufferCount).append(")");
builder.append("sob(").append(skippedOutputBufferCount).append(")"); builder.append("sob(").append(skippedOutputBufferCount).append(")");
builder.append("dob(").append(droppedOutputBufferCount).append(")"); builder.append("dob(").append(droppedOutputBufferCount).append(")");
builder.append("dsc(").append(discardedSamplesCount).append(")");
return builder.toString(); return builder.toString();
} }
......
...@@ -60,7 +60,7 @@ import java.util.List; ...@@ -60,7 +60,7 @@ import java.util.List;
private static final int IDLE_INTERVAL_MS = 1000; private static final int IDLE_INTERVAL_MS = 1000;
private final Handler handler; private final Handler handler;
private final HandlerThread internalPlayerThread; private final HandlerThread internalPlaybackThread;
private final Handler eventHandler; private final Handler eventHandler;
private final MediaClock mediaClock; private final MediaClock mediaClock;
private final boolean[] rendererEnabledFlags; private final boolean[] rendererEnabledFlags;
...@@ -100,7 +100,7 @@ import java.util.List; ...@@ -100,7 +100,7 @@ import java.util.List;
mediaClock = new MediaClock(); mediaClock = new MediaClock();
enabledRenderers = new ArrayList<TrackRenderer>(rendererEnabledFlags.length); enabledRenderers = new ArrayList<TrackRenderer>(rendererEnabledFlags.length);
internalPlayerThread = new HandlerThread(getClass().getSimpleName() + ":Handler") { internalPlaybackThread = new HandlerThread(getClass().getSimpleName() + ":Handler") {
@Override @Override
public void run() { public void run() {
// Note: The documentation for Process.THREAD_PRIORITY_AUDIO that states "Applications can // Note: The documentation for Process.THREAD_PRIORITY_AUDIO that states "Applications can
...@@ -109,12 +109,12 @@ import java.util.List; ...@@ -109,12 +109,12 @@ import java.util.List;
super.run(); super.run();
} }
}; };
internalPlayerThread.start(); internalPlaybackThread.start();
handler = new Handler(internalPlayerThread.getLooper(), this); handler = new Handler(internalPlaybackThread.getLooper(), this);
} }
public Looper getPlaybackLooper() { public Looper getPlaybackLooper() {
return internalPlayerThread.getLooper(); return internalPlaybackThread.getLooper();
} }
public int getCurrentPosition() { public int getCurrentPosition() {
...@@ -179,7 +179,7 @@ import java.util.List; ...@@ -179,7 +179,7 @@ import java.util.List;
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }
} }
internalPlayerThread.quit(); internalPlaybackThread.quit();
} }
} }
......
...@@ -382,6 +382,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { ...@@ -382,6 +382,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
while (feedInputBuffer()) {} while (feedInputBuffer()) {}
} }
} }
codecCounters.ensureUpdated();
} catch (IOException e) { } catch (IOException e) {
throw new ExoPlaybackException(e); throw new ExoPlaybackException(e);
} }
...@@ -403,7 +404,6 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { ...@@ -403,7 +404,6 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
if (!sampleHolder.decodeOnly) { if (!sampleHolder.decodeOnly) {
currentPositionUs = sampleHolder.timeUs; currentPositionUs = sampleHolder.timeUs;
} }
codecCounters.discardedSamplesCount++;
} else if (result == SampleSource.FORMAT_READ) { } else if (result == SampleSource.FORMAT_READ) {
onInputFormatChanged(formatHolder); onInputFormatChanged(formatHolder);
} }
...@@ -476,7 +476,6 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { ...@@ -476,7 +476,6 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
} }
if (result == SampleSource.NOTHING_READ) { if (result == SampleSource.NOTHING_READ) {
codecCounters.inputBufferWaitingForSampleCount++;
return false; return false;
} }
if (result == SampleSource.DISCONTINUITY_READ) { if (result == SampleSource.DISCONTINUITY_READ) {
...@@ -505,7 +504,6 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { ...@@ -505,7 +504,6 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
try { try {
codec.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); codec.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
inputIndex = -1; inputIndex = -1;
codecCounters.queuedEndOfStreamCount++;
} catch (CryptoException e) { } catch (CryptoException e) {
notifyCryptoError(e); notifyCryptoError(e);
throw new ExoPlaybackException(e); throw new ExoPlaybackException(e);
...@@ -545,10 +543,6 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { ...@@ -545,10 +543,6 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
} else { } else {
codec.queueInputBuffer(inputIndex, 0 , bufferSize, presentationTimeUs, 0); codec.queueInputBuffer(inputIndex, 0 , bufferSize, presentationTimeUs, 0);
} }
codecCounters.queuedInputBufferCount++;
if ((sampleHolder.flags & MediaExtractor.SAMPLE_FLAG_SYNC) != 0) {
codecCounters.keyframeCount++;
}
inputIndex = -1; inputIndex = -1;
codecReconfigurationState = RECONFIGURATION_STATE_NONE; codecReconfigurationState = RECONFIGURATION_STATE_NONE;
} catch (CryptoException e) { } catch (CryptoException e) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment