Commit 348b5802 by andrewlewis Committed by Oliver Woodman

Move underrun detection into AudioTrack.

This removes duplication from SimpleDecoderAudioRenderer and
MediaCodecAudioRenderer.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=139187254
parent 74383716
...@@ -23,7 +23,6 @@ import android.media.MediaFormat; ...@@ -23,7 +23,6 @@ import android.media.MediaFormat;
import android.media.PlaybackParams; import android.media.PlaybackParams;
import android.media.audiofx.Virtualizer; import android.media.audiofx.Virtualizer;
import android.os.Handler; import android.os.Handler;
import android.os.SystemClock;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
...@@ -43,7 +42,8 @@ import java.nio.ByteBuffer; ...@@ -43,7 +42,8 @@ import java.nio.ByteBuffer;
* Decodes and renders audio using {@link MediaCodec} and {@link AudioTrack}. * Decodes and renders audio using {@link MediaCodec} and {@link AudioTrack}.
*/ */
@TargetApi(16) @TargetApi(16)
public class MediaCodecAudioRenderer extends MediaCodecRenderer implements MediaClock { public class MediaCodecAudioRenderer extends MediaCodecRenderer implements MediaClock,
AudioTrack.Listener {
private final EventDispatcher eventDispatcher; private final EventDispatcher eventDispatcher;
private final AudioTrack audioTrack; private final AudioTrack audioTrack;
...@@ -55,9 +55,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media ...@@ -55,9 +55,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
private long currentPositionUs; private long currentPositionUs;
private boolean allowPositionDiscontinuity; private boolean allowPositionDiscontinuity;
private boolean audioTrackHasData;
private long lastFeedElapsedRealtimeMs;
/** /**
* @param mediaCodecSelector A decoder selector. * @param mediaCodecSelector A decoder selector.
*/ */
...@@ -136,7 +133,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media ...@@ -136,7 +133,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
int streamType) { int streamType) {
super(C.TRACK_TYPE_AUDIO, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys); super(C.TRACK_TYPE_AUDIO, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys);
audioSessionId = AudioTrack.SESSION_ID_NOT_SET; audioSessionId = AudioTrack.SESSION_ID_NOT_SET;
audioTrack = new AudioTrack(audioCapabilities, streamType); audioTrack = new AudioTrack(audioCapabilities, streamType, this);
eventDispatcher = new EventDispatcher(eventHandler, eventListener); eventDispatcher = new EventDispatcher(eventHandler, eventListener);
} }
...@@ -341,29 +338,17 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media ...@@ -341,29 +338,17 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
} else { } else {
audioTrack.initialize(audioSessionId); audioTrack.initialize(audioSessionId);
} }
audioTrackHasData = false;
} catch (AudioTrack.InitializationException e) { } catch (AudioTrack.InitializationException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex()); throw ExoPlaybackException.createForRenderer(e, getIndex());
} }
if (getState() == STATE_STARTED) { if (getState() == STATE_STARTED) {
audioTrack.play(); audioTrack.play();
} }
} else {
// Check for AudioTrack underrun.
boolean audioTrackHadData = audioTrackHasData;
audioTrackHasData = audioTrack.hasPendingData();
if (audioTrackHadData && !audioTrackHasData && getState() == STATE_STARTED) {
long elapsedSinceLastFeedMs = SystemClock.elapsedRealtime() - lastFeedElapsedRealtimeMs;
long bufferSizeMs = C.usToMs(audioTrack.getBufferSizeUs());
eventDispatcher.audioTrackUnderrun(audioTrack.getBufferSize(), bufferSizeMs,
elapsedSinceLastFeedMs);
}
} }
int handleBufferResult; int handleBufferResult;
try { try {
handleBufferResult = audioTrack.handleBuffer(buffer, bufferPresentationTimeUs); handleBufferResult = audioTrack.handleBuffer(buffer, bufferPresentationTimeUs);
lastFeedElapsedRealtimeMs = SystemClock.elapsedRealtime();
} catch (AudioTrack.WriteException e) { } catch (AudioTrack.WriteException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex()); throw ExoPlaybackException.createForRenderer(e, getIndex());
} }
...@@ -408,4 +393,11 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media ...@@ -408,4 +393,11 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
} }
} }
// AudioTrack.Listener implementation.
@Override
public void onUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
eventDispatcher.audioTrackUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs);
}
} }
...@@ -41,7 +41,8 @@ import com.google.android.exoplayer2.util.Util; ...@@ -41,7 +41,8 @@ import com.google.android.exoplayer2.util.Util;
/** /**
* Decodes and renders audio using a {@link SimpleDecoder}. * Decodes and renders audio using a {@link SimpleDecoder}.
*/ */
public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements MediaClock { public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements MediaClock,
AudioTrack.Listener {
private final boolean playClearSamplesWithoutKeys; private final boolean playClearSamplesWithoutKeys;
...@@ -67,9 +68,6 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements ...@@ -67,9 +68,6 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
private final AudioTrack audioTrack; private final AudioTrack audioTrack;
private int audioSessionId; private int audioSessionId;
private boolean audioTrackHasData;
private long lastFeedElapsedRealtimeMs;
public SimpleDecoderAudioRenderer() { public SimpleDecoderAudioRenderer() {
this(null, null); this(null, null);
} }
...@@ -122,7 +120,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements ...@@ -122,7 +120,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys;
eventDispatcher = new EventDispatcher(eventHandler, eventListener); eventDispatcher = new EventDispatcher(eventHandler, eventListener);
audioSessionId = AudioTrack.SESSION_ID_NOT_SET; audioSessionId = AudioTrack.SESSION_ID_NOT_SET;
audioTrack = new AudioTrack(audioCapabilities, streamType); audioTrack = new AudioTrack(audioCapabilities, streamType, this);
formatHolder = new FormatHolder(); formatHolder = new FormatHolder();
} }
...@@ -245,24 +243,12 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements ...@@ -245,24 +243,12 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
} else { } else {
audioTrack.initialize(audioSessionId); audioTrack.initialize(audioSessionId);
} }
audioTrackHasData = false;
if (getState() == STATE_STARTED) { if (getState() == STATE_STARTED) {
audioTrack.play(); audioTrack.play();
} }
} else {
// Check for AudioTrack underrun.
boolean audioTrackHadData = audioTrackHasData;
audioTrackHasData = audioTrack.hasPendingData();
if (audioTrackHadData && !audioTrackHasData && getState() == STATE_STARTED) {
long elapsedSinceLastFeedMs = SystemClock.elapsedRealtime() - lastFeedElapsedRealtimeMs;
long bufferSizeMs = C.usToMs(audioTrack.getBufferSizeUs());
eventDispatcher.audioTrackUnderrun(audioTrack.getBufferSize(), bufferSizeMs,
elapsedSinceLastFeedMs);
}
} }
int handleBufferResult = audioTrack.handleBuffer(outputBuffer.data, outputBuffer.timeUs); int handleBufferResult = audioTrack.handleBuffer(outputBuffer.data, outputBuffer.timeUs);
lastFeedElapsedRealtimeMs = SystemClock.elapsedRealtime();
// If we are out of sync, allow currentPositionUs to jump backwards. // If we are out of sync, allow currentPositionUs to jump backwards.
if ((handleBufferResult & AudioTrack.RESULT_POSITION_DISCONTINUITY) != 0) { if ((handleBufferResult & AudioTrack.RESULT_POSITION_DISCONTINUITY) != 0) {
...@@ -493,4 +479,11 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements ...@@ -493,4 +479,11 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
} }
} }
// AudioTrack.Listener implementation.
@Override
public void onUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
eventDispatcher.audioTrackUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs);
}
} }
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