mirror of
https://github.com/samsonjs/media.git
synced 2026-03-26 09:35:47 +00:00
Simplify AudioTrack.handleBuffer's return value.
Position discontinuities are notified via AudioTrack.Listener. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=144202048
This commit is contained in:
parent
444811c010
commit
2906a2ea09
3 changed files with 87 additions and 110 deletions
|
|
@ -63,6 +63,19 @@ public final class AudioTrack {
|
|||
*/
|
||||
public interface Listener {
|
||||
|
||||
/**
|
||||
* Called when the audio track has been initialized with the specified {@code audioSessionId}.
|
||||
*
|
||||
* @param audioSessionId The audio session id.
|
||||
*/
|
||||
void onAudioSessionId(int audioSessionId);
|
||||
|
||||
/**
|
||||
* Called when the audio track handles a buffer whose timestamp is discontinuous with the last
|
||||
* buffer handled since it was reset.
|
||||
*/
|
||||
void onPositionDiscontinuity();
|
||||
|
||||
/**
|
||||
* Called when the audio track underruns.
|
||||
*
|
||||
|
|
@ -74,13 +87,6 @@ public final class AudioTrack {
|
|||
*/
|
||||
void onUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs);
|
||||
|
||||
/**
|
||||
* Called when the audio track has been initialized with the specified {@code audioSessionId}.
|
||||
*
|
||||
* @param audioSessionId The audio session id.
|
||||
*/
|
||||
void onAudioSessionId(int audioSessionId);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -144,15 +150,6 @@ public final class AudioTrack {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returned in the result of {@link #handleBuffer} if the buffer was discontinuous.
|
||||
*/
|
||||
public static final int RESULT_POSITION_DISCONTINUITY = 1;
|
||||
/**
|
||||
* Returned in the result of {@link #handleBuffer} if the buffer can be released.
|
||||
*/
|
||||
public static final int RESULT_BUFFER_CONSUMED = 2;
|
||||
|
||||
/**
|
||||
* Returned by {@link #getCurrentPositionUs} when the position is not set.
|
||||
*/
|
||||
|
|
@ -591,24 +588,21 @@ public final class AudioTrack {
|
|||
* Attempts to write data from a {@link ByteBuffer} to the audio track, starting from its current
|
||||
* position and ending at its limit (exclusive). The position of the {@link ByteBuffer} is
|
||||
* advanced by the number of bytes that were successfully written.
|
||||
* {@link Listener#onPositionDiscontinuity()} will be called if {@code presentationTimeUs} is
|
||||
* discontinuous with the last buffer handled since the track was reset.
|
||||
* <p>
|
||||
* Returns a bit field containing {@link #RESULT_BUFFER_CONSUMED} if the data was written in full,
|
||||
* and {@link #RESULT_POSITION_DISCONTINUITY} if the buffer was discontinuous with previously
|
||||
* written data.
|
||||
* <p>
|
||||
* If the data was not written in full then the same {@link ByteBuffer} must be provided to
|
||||
* subsequent calls until it has been fully consumed, except in the case of an interleaving call
|
||||
* to {@link #configure} or {@link #reset}.
|
||||
* Returns whether the data was written in full. If the data was not written in full then the same
|
||||
* {@link ByteBuffer} must be provided to subsequent calls until it has been fully consumed,
|
||||
* except in the case of an interleaving call to {@link #reset()} (or an interleaving call to
|
||||
* {@link #configure(String, int, int, int, int)} that caused the track to be reset).
|
||||
*
|
||||
* @param buffer The buffer containing audio data to play back.
|
||||
* @param presentationTimeUs Presentation timestamp of the next buffer in microseconds.
|
||||
* @return A bit field with {@link #RESULT_BUFFER_CONSUMED} if the buffer can be released, and
|
||||
* {@link #RESULT_POSITION_DISCONTINUITY} if the buffer was not contiguous with previously
|
||||
* written data.
|
||||
* @return Whether the buffer was consumed fully.
|
||||
* @throws InitializationException If an error occurs initializing the track.
|
||||
* @throws WriteException If an error occurs writing the audio data.
|
||||
*/
|
||||
public int handleBuffer(ByteBuffer buffer, long presentationTimeUs)
|
||||
public boolean handleBuffer(ByteBuffer buffer, long presentationTimeUs)
|
||||
throws InitializationException, WriteException {
|
||||
if (!isInitialized()) {
|
||||
initialize();
|
||||
|
|
@ -623,12 +617,12 @@ public final class AudioTrack {
|
|||
long elapsedSinceLastFeedMs = SystemClock.elapsedRealtime() - lastFeedElapsedRealtimeMs;
|
||||
listener.onUnderrun(bufferSize, C.usToMs(bufferSizeUs), elapsedSinceLastFeedMs);
|
||||
}
|
||||
int result = writeBuffer(buffer, presentationTimeUs);
|
||||
boolean result = writeBuffer(buffer, presentationTimeUs);
|
||||
lastFeedElapsedRealtimeMs = SystemClock.elapsedRealtime();
|
||||
return result;
|
||||
}
|
||||
|
||||
private int writeBuffer(ByteBuffer buffer, long presentationTimeUs) throws WriteException {
|
||||
private boolean writeBuffer(ByteBuffer buffer, long presentationTimeUs) throws WriteException {
|
||||
boolean isNewSourceBuffer = currentSourceBuffer == null;
|
||||
Assertions.checkState(isNewSourceBuffer || currentSourceBuffer == buffer);
|
||||
currentSourceBuffer = buffer;
|
||||
|
|
@ -637,7 +631,7 @@ public final class AudioTrack {
|
|||
// An AC-3 audio track continues to play data written while it is paused. Stop writing so its
|
||||
// buffer empties. See [Internal: b/18899620].
|
||||
if (audioTrack.getPlayState() == PLAYSTATE_PAUSED) {
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// A new AC-3 audio track's playback position continues to increase from the old track's
|
||||
|
|
@ -645,7 +639,7 @@ public final class AudioTrack {
|
|||
// head position actually returns to zero.
|
||||
if (audioTrack.getPlayState() == PLAYSTATE_STOPPED
|
||||
&& audioTrackUtil.getPlaybackHeadPosition() != 0) {
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -656,7 +650,7 @@ public final class AudioTrack {
|
|||
if (!currentSourceBuffer.hasRemaining()) {
|
||||
// The buffer is empty.
|
||||
currentSourceBuffer = null;
|
||||
return RESULT_BUFFER_CONSUMED;
|
||||
return true;
|
||||
}
|
||||
|
||||
useResampledBuffer = targetEncoding != sourceEncoding;
|
||||
|
|
@ -689,7 +683,7 @@ public final class AudioTrack {
|
|||
// number of bytes submitted.
|
||||
startMediaTimeUs += (presentationTimeUs - expectedPresentationTimeUs);
|
||||
startMediaTimeState = START_IN_SYNC;
|
||||
result |= RESULT_POSITION_DISCONTINUITY;
|
||||
listener.onPositionDiscontinuity();
|
||||
}
|
||||
}
|
||||
if (Util.SDK_INT < 21) {
|
||||
|
|
@ -739,9 +733,9 @@ public final class AudioTrack {
|
|||
submittedEncodedFrames += framesPerEncodedSample;
|
||||
}
|
||||
currentSourceBuffer = null;
|
||||
result |= RESULT_BUFFER_CONSUMED;
|
||||
return true;
|
||||
}
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -228,29 +228,26 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||
}
|
||||
|
||||
/**
|
||||
* Called when the audio session id becomes known. Once the id is known it will not change (and
|
||||
* hence this method will not be called again) unless the renderer is disabled and then
|
||||
* subsequently re-enabled.
|
||||
* <p>
|
||||
* The default implementation is a no-op. One reason for overriding this method would be to
|
||||
* instantiate and enable a {@link Virtualizer} in order to spatialize the audio channels. For
|
||||
* this use case, any {@link Virtualizer} instances should be released in {@link #onDisabled()}
|
||||
* (if not before).
|
||||
* Called when the audio session id becomes known. The default implementation is a no-op. One
|
||||
* reason for overriding this method would be to instantiate and enable a {@link Virtualizer} in
|
||||
* order to spatialize the audio channels. For this use case, any {@link Virtualizer} instances
|
||||
* should be released in {@link #onDisabled()} (if not before).
|
||||
*
|
||||
* @param audioSessionId The audio session id.
|
||||
* @see AudioTrack.Listener#onAudioSessionId(int)
|
||||
*/
|
||||
protected void onAudioSessionId(int audioSessionId) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an {@link AudioTrack} underrun occurs.
|
||||
*
|
||||
* @param bufferSize The size of the {@link AudioTrack}'s buffer, in bytes.
|
||||
* @param bufferSizeMs The size of the {@link AudioTrack}'s buffer, in milliseconds, if it is
|
||||
* configured for PCM output. {@link C#TIME_UNSET} if it is configured for passthrough output,
|
||||
* as the buffered media can have a variable bitrate so the duration may be unknown.
|
||||
* @param elapsedSinceLastFeedMs The time since the {@link AudioTrack} was last fed data.
|
||||
* @see AudioTrack.Listener#onPositionDiscontinuity()
|
||||
*/
|
||||
protected void onAudioTrackPositionDiscontinuity() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AudioTrack.Listener#onUnderrun(int, long, long)
|
||||
*/
|
||||
protected void onAudioTrackUnderrun(int bufferSize, long bufferSizeMs,
|
||||
long elapsedSinceLastFeedMs) {
|
||||
|
|
@ -335,26 +332,15 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||
return true;
|
||||
}
|
||||
|
||||
int handleBufferResult;
|
||||
try {
|
||||
handleBufferResult = audioTrack.handleBuffer(buffer, bufferPresentationTimeUs);
|
||||
if (audioTrack.handleBuffer(buffer, bufferPresentationTimeUs)) {
|
||||
codec.releaseOutputBuffer(bufferIndex, false);
|
||||
decoderCounters.renderedOutputBufferCount++;
|
||||
return true;
|
||||
}
|
||||
} catch (AudioTrack.InitializationException | AudioTrack.WriteException e) {
|
||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
||||
}
|
||||
|
||||
// If we are out of sync, allow currentPositionUs to jump backwards.
|
||||
if ((handleBufferResult & AudioTrack.RESULT_POSITION_DISCONTINUITY) != 0) {
|
||||
handleAudioTrackDiscontinuity();
|
||||
allowPositionDiscontinuity = true;
|
||||
}
|
||||
|
||||
// Release the buffer if it was consumed.
|
||||
if ((handleBufferResult & AudioTrack.RESULT_BUFFER_CONSUMED) != 0) {
|
||||
codec.releaseOutputBuffer(bufferIndex, false);
|
||||
decoderCounters.renderedOutputBufferCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -363,10 +349,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||
audioTrack.handleEndOfStream();
|
||||
}
|
||||
|
||||
protected void handleAudioTrackDiscontinuity() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(int messageType, Object message) throws ExoPlaybackException {
|
||||
switch (messageType) {
|
||||
|
|
@ -388,19 +370,25 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||
|
||||
private final class AudioTrackListener implements AudioTrack.Listener {
|
||||
|
||||
@Override
|
||||
public void onUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
|
||||
eventDispatcher.audioTrackUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs);
|
||||
MediaCodecAudioRenderer.this.onAudioTrackUnderrun(bufferSize, bufferSizeMs,
|
||||
elapsedSinceLastFeedMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAudioSessionId(int audioSessionId) {
|
||||
eventDispatcher.audioSessionId(audioSessionId);
|
||||
MediaCodecAudioRenderer.this.onAudioSessionId(audioSessionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPositionDiscontinuity() {
|
||||
onAudioTrackPositionDiscontinuity();
|
||||
// We are out of sync so allow currentPositionUs to jump backwards.
|
||||
MediaCodecAudioRenderer.this.allowPositionDiscontinuity = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
|
||||
eventDispatcher.audioTrackUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs);
|
||||
onAudioTrackUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,29 +183,26 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
|
|||
}
|
||||
|
||||
/**
|
||||
* Called when the audio session id becomes known. Once the id is known it will not change (and
|
||||
* hence this method will not be called again) unless the renderer is disabled and then
|
||||
* subsequently re-enabled.
|
||||
* <p>
|
||||
* The default implementation is a no-op. One reason for overriding this method would be to
|
||||
* instantiate and enable a {@link Virtualizer} in order to spatialize the audio channels. For
|
||||
* this use case, any {@link Virtualizer} instances should be released in {@link #onDisabled()}
|
||||
* (if not before).
|
||||
* Called when the audio session id becomes known. The default implementation is a no-op. One
|
||||
* reason for overriding this method would be to instantiate and enable a {@link Virtualizer} in
|
||||
* order to spatialize the audio channels. For this use case, any {@link Virtualizer} instances
|
||||
* should be released in {@link #onDisabled()} (if not before).
|
||||
*
|
||||
* @param audioSessionId The audio session id.
|
||||
* @see AudioTrack.Listener#onAudioSessionId(int)
|
||||
*/
|
||||
protected void onAudioSessionId(int audioSessionId) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an {@link AudioTrack} underrun occurs.
|
||||
*
|
||||
* @param bufferSize The size of the {@link AudioTrack}'s buffer, in bytes.
|
||||
* @param bufferSizeMs The size of the {@link AudioTrack}'s buffer, in milliseconds, if it is
|
||||
* configured for PCM output. {@link C#TIME_UNSET} if it is configured for passthrough output,
|
||||
* as the buffered media can have a variable bitrate so the duration may be unknown.
|
||||
* @param elapsedSinceLastFeedMs The time since the {@link AudioTrack} was last fed data.
|
||||
* @see AudioTrack.Listener#onPositionDiscontinuity()
|
||||
*/
|
||||
protected void onAudioTrackPositionDiscontinuity() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AudioTrack.Listener#onUnderrun(int, long, long)
|
||||
*/
|
||||
protected void onAudioTrackUnderrun(int bufferSize, long bufferSizeMs,
|
||||
long elapsedSinceLastFeedMs) {
|
||||
|
|
@ -271,15 +268,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
|
|||
audioTrackNeedsConfigure = false;
|
||||
}
|
||||
|
||||
int handleBufferResult = audioTrack.handleBuffer(outputBuffer.data, outputBuffer.timeUs);
|
||||
|
||||
// If we are out of sync, allow currentPositionUs to jump backwards.
|
||||
if ((handleBufferResult & AudioTrack.RESULT_POSITION_DISCONTINUITY) != 0) {
|
||||
allowPositionDiscontinuity = true;
|
||||
}
|
||||
|
||||
// Release the buffer if it was consumed.
|
||||
if ((handleBufferResult & AudioTrack.RESULT_BUFFER_CONSUMED) != 0) {
|
||||
if (audioTrack.handleBuffer(outputBuffer.data, outputBuffer.timeUs)) {
|
||||
decoderCounters.renderedOutputBufferCount++;
|
||||
outputBuffer.release();
|
||||
outputBuffer = null;
|
||||
|
|
@ -563,19 +552,25 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
|
|||
|
||||
private final class AudioTrackListener implements AudioTrack.Listener {
|
||||
|
||||
@Override
|
||||
public void onUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
|
||||
eventDispatcher.audioTrackUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs);
|
||||
SimpleDecoderAudioRenderer.this.onAudioTrackUnderrun(bufferSize, bufferSizeMs,
|
||||
elapsedSinceLastFeedMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAudioSessionId(int audioSessionId) {
|
||||
eventDispatcher.audioSessionId(audioSessionId);
|
||||
SimpleDecoderAudioRenderer.this.onAudioSessionId(audioSessionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPositionDiscontinuity() {
|
||||
onAudioTrackPositionDiscontinuity();
|
||||
// We are out of sync so allow currentPositionUs to jump backwards.
|
||||
SimpleDecoderAudioRenderer.this.allowPositionDiscontinuity = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
|
||||
eventDispatcher.audioTrackUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs);
|
||||
onAudioTrackUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue