MediaCodecTrackRenderer: Avoid excessive garbage generation

Looking up a long in a HashSet<Long> auto boxes the long and leaves
it for the GC. As decodeOnly is relatively infrequent it's much
better to do a simple linear search in a List<Long>. That way
we can avoid boxing every incoming time stamp value. In the general
case this will be linear searching in an empty list, a very fast
operation.

Signed-off-by: Jonas Larsson <jonas@hallerud.se>
This commit is contained in:
Jonas Larsson 2014-11-14 16:13:13 -08:00
parent cb06845976
commit 255c3b27f6

View File

@ -30,7 +30,8 @@ import android.os.SystemClock;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.HashSet; import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@ -141,7 +142,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
private final SampleSource source; private final SampleSource source;
private final SampleHolder sampleHolder; private final SampleHolder sampleHolder;
private final MediaFormatHolder formatHolder; private final MediaFormatHolder formatHolder;
private final HashSet<Long> decodeOnlyPresentationTimestamps; private final List<Long> decodeOnlyPresentationTimestamps;
private final MediaCodec.BufferInfo outputBufferInfo; private final MediaCodec.BufferInfo outputBufferInfo;
private final EventListener eventListener; private final EventListener eventListener;
protected final Handler eventHandler; protected final Handler eventHandler;
@ -191,7 +192,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
codecCounters = new CodecCounters(); codecCounters = new CodecCounters();
sampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_DISABLED); sampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_DISABLED);
formatHolder = new MediaFormatHolder(); formatHolder = new MediaFormatHolder();
decodeOnlyPresentationTimestamps = new HashSet<Long>(); decodeOnlyPresentationTimestamps = new ArrayList<Long>();
outputBufferInfo = new MediaCodec.BufferInfo(); outputBufferInfo = new MediaCodec.BufferInfo();
} }
@ -738,12 +739,11 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
return false; return false;
} }
boolean decodeOnly = decodeOnlyPresentationTimestamps.contains( int decodeOnlyIdx = getDecodeOnlyIndex(outputBufferInfo.presentationTimeUs);
outputBufferInfo.presentationTimeUs);
if (processOutputBuffer(positionUs, elapsedRealtimeUs, codec, outputBuffers[outputIndex], if (processOutputBuffer(positionUs, elapsedRealtimeUs, codec, outputBuffers[outputIndex],
outputBufferInfo, outputIndex, decodeOnly)) { outputBufferInfo, outputIndex, decodeOnlyIdx >= 0)) {
if (decodeOnly) { if (decodeOnlyIdx >= 0) {
decodeOnlyPresentationTimestamps.remove(outputBufferInfo.presentationTimeUs); decodeOnlyPresentationTimestamps.remove(decodeOnlyIdx);
} else { } else {
currentPositionUs = outputBufferInfo.presentationTimeUs; currentPositionUs = outputBufferInfo.presentationTimeUs;
} }
@ -794,4 +794,13 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
} }
} }
private int getDecodeOnlyIndex(long presentationTimeUs) {
final int size = decodeOnlyPresentationTimestamps.size();
for (int i = 0; i < size; i++) {
if (decodeOnlyPresentationTimestamps.get(i).longValue() == presentationTimeUs) {
return i;
}
}
return -1;
}
} }