mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Plumbing to enable tunneling on AudioTrack from renderers
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=144223539
This commit is contained in:
parent
3547c9034e
commit
cd42434719
3 changed files with 48 additions and 24 deletions
|
|
@ -39,9 +39,9 @@ import java.nio.ByteOrder;
|
||||||
* <p>
|
* <p>
|
||||||
* Before starting playback, specify the input format by calling
|
* Before starting playback, specify the input format by calling
|
||||||
* {@link #configure(String, int, int, int, int)}. Optionally call {@link #setAudioSessionId(int)},
|
* {@link #configure(String, int, int, int, int)}. Optionally call {@link #setAudioSessionId(int)},
|
||||||
* {@link #setTunnelingEnabledV21(boolean)} and {@link #setStreamType(int)} to configure audio
|
* {@link #setStreamType(int)}, {@link #enableTunnelingV21(int)} and {@link #disableTunneling()}
|
||||||
* playback. These methods may be called after writing data to the track, in which case it will be
|
* to configure audio playback. These methods may be called after writing data to the track, in
|
||||||
* reinitialized as required.
|
* which case it will be reinitialized as required.
|
||||||
* <p>
|
* <p>
|
||||||
* Call {@link #handleBuffer(ByteBuffer, long)} to write data, and {@link #handleDiscontinuity()}
|
* Call {@link #handleBuffer(ByteBuffer, long)} to write data, and {@link #handleDiscontinuity()}
|
||||||
* when the data being fed is discontinuous. Call {@link #play()} to start playing the written data.
|
* when the data being fed is discontinuous. Call {@link #play()} to start playing the written data.
|
||||||
|
|
@ -64,9 +64,9 @@ public final class AudioTrack {
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the audio track has been initialized with the specified {@code audioSessionId}.
|
* Called when the audio track has been initialized with a newly generated audio session id.
|
||||||
*
|
*
|
||||||
* @param audioSessionId The audio session id.
|
* @param audioSessionId The newly generated audio session id.
|
||||||
*/
|
*/
|
||||||
void onAudioSessionId(int audioSessionId);
|
void onAudioSessionId(int audioSessionId);
|
||||||
|
|
||||||
|
|
@ -275,7 +275,6 @@ public final class AudioTrack {
|
||||||
private int bufferSize;
|
private int bufferSize;
|
||||||
private long bufferSizeUs;
|
private long bufferSizeUs;
|
||||||
|
|
||||||
private boolean useHwAvSync;
|
|
||||||
private ByteBuffer avSyncHeader;
|
private ByteBuffer avSyncHeader;
|
||||||
private int bytesUntilNextAvSync;
|
private int bytesUntilNextAvSync;
|
||||||
|
|
||||||
|
|
@ -520,8 +519,7 @@ public final class AudioTrack {
|
||||||
// initialization of the audio track to fail.
|
// initialization of the audio track to fail.
|
||||||
releasingConditionVariable.block();
|
releasingConditionVariable.block();
|
||||||
|
|
||||||
useHwAvSync = tunneling;
|
if (tunneling) {
|
||||||
if (useHwAvSync) {
|
|
||||||
audioTrack = createHwAvSyncAudioTrackV21(sampleRate, channelConfig, targetEncoding,
|
audioTrack = createHwAvSyncAudioTrackV21(sampleRate, channelConfig, targetEncoding,
|
||||||
bufferSize, audioSessionId);
|
bufferSize, audioSessionId);
|
||||||
} else if (audioSessionId == C.AUDIO_SESSION_ID_UNSET) {
|
} else if (audioSessionId == C.AUDIO_SESSION_ID_UNSET) {
|
||||||
|
|
@ -716,7 +714,7 @@ public final class AudioTrack {
|
||||||
buffer.position(buffer.position() + bytesWritten);
|
buffer.position(buffer.position() + bytesWritten);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bytesWritten = useHwAvSync
|
bytesWritten = tunneling
|
||||||
? writeNonBlockingWithAvSyncV21(audioTrack, buffer, bytesRemaining, presentationTimeUs)
|
? writeNonBlockingWithAvSyncV21(audioTrack, buffer, bytesRemaining, presentationTimeUs)
|
||||||
: writeNonBlockingV21(audioTrack, buffer, bytesRemaining);
|
: writeNonBlockingV21(audioTrack, buffer, bytesRemaining);
|
||||||
}
|
}
|
||||||
|
|
@ -771,13 +769,12 @@ public final class AudioTrack {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the stream type for audio track. If the stream type has changed and if the audio track
|
* Sets the stream type for audio track. If the stream type has changed and if the audio track
|
||||||
* is not configured for use with video tunneling, then the audio track is reset and will be
|
* is not configured for use with tunneling, then the audio track is reset and the audio session
|
||||||
* reinitialized on the next call to {@link #handleBuffer(ByteBuffer, long)}. An audio session
|
* id is cleared.
|
||||||
* cannot be reused after a change of stream type, so the audio session identifier will be reset.
|
|
||||||
* <p>
|
* <p>
|
||||||
* If the audio track is configured for use with video tunneling then the stream type is ignored
|
* If the audio track is configured for use with tunneling then the stream type is ignored, the
|
||||||
* and the audio track is not reset. The passed stream type will be used if the audio track is
|
* audio track is not reset and the audio session id is not cleared. The passed stream type will
|
||||||
* later re-configured into non-tunneled mode.
|
* be used if the audio track is later re-configured into non-tunneled mode.
|
||||||
*
|
*
|
||||||
* @param streamType The {@link C.StreamType} to use for audio output.
|
* @param streamType The {@link C.StreamType} to use for audio output.
|
||||||
*/
|
*/
|
||||||
|
|
@ -786,7 +783,7 @@ public final class AudioTrack {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.streamType = streamType;
|
this.streamType = streamType;
|
||||||
if (useHwAvSync) {
|
if (tunneling) {
|
||||||
// The stream type is ignored in tunneling mode, so no need to reset.
|
// The stream type is ignored in tunneling mode, so no need to reset.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -795,7 +792,7 @@ public final class AudioTrack {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the audio session id, and resets the audio track if the audio session id has changed.
|
* Sets the audio session id. The audio track is reset if the audio session id has changed.
|
||||||
*/
|
*/
|
||||||
public void setAudioSessionId(int audioSessionId) {
|
public void setAudioSessionId(int audioSessionId) {
|
||||||
if (this.audioSessionId != audioSessionId) {
|
if (this.audioSessionId != audioSessionId) {
|
||||||
|
|
@ -805,16 +802,29 @@ public final class AudioTrack {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether tunneling is enabled. Enabling tunneling requires platform API version 21 onwards.
|
* Enables tunneling. The audio track is reset if tunneling was previously disabled or if the
|
||||||
* Resets the audio track if tunneling was enabled/disabled.
|
* audio session id has changed. Enabling tunneling requires platform API version 21 onwards.
|
||||||
*
|
*
|
||||||
* @param tunneling Whether the audio track will be used with tunneling video playback.
|
* @param tunnelingAudioSessionId The audio session id to use.
|
||||||
* @throws IllegalStateException Thrown if enabling tunneling on platform API version < 21.
|
* @throws IllegalStateException Thrown if enabling tunneling on platform API version < 21.
|
||||||
*/
|
*/
|
||||||
public void setTunnelingEnabledV21(boolean tunneling) {
|
public void enableTunnelingV21(int tunnelingAudioSessionId) {
|
||||||
if (this.tunneling != tunneling) {
|
Assertions.checkState(Util.SDK_INT >= 21);
|
||||||
Assertions.checkState(Util.SDK_INT >= 21);
|
if (!tunneling || audioSessionId != tunnelingAudioSessionId) {
|
||||||
this.tunneling = tunneling;
|
tunneling = true;
|
||||||
|
audioSessionId = tunnelingAudioSessionId;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables tunneling. If tunneling was previously enabled then the audio track is reset and the
|
||||||
|
* audio session id is cleared.
|
||||||
|
*/
|
||||||
|
public void disableTunneling() {
|
||||||
|
if (tunneling) {
|
||||||
|
tunneling = false;
|
||||||
|
audioSessionId = C.AUDIO_SESSION_ID_UNSET;
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,13 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
||||||
protected void onEnabled(boolean joining) throws ExoPlaybackException {
|
protected void onEnabled(boolean joining) throws ExoPlaybackException {
|
||||||
super.onEnabled(joining);
|
super.onEnabled(joining);
|
||||||
eventDispatcher.enabled(decoderCounters);
|
eventDispatcher.enabled(decoderCounters);
|
||||||
|
// TODO: Allow this to be set.
|
||||||
|
int tunnelingAudioSessionId = C.AUDIO_SESSION_ID_UNSET;
|
||||||
|
if (tunnelingAudioSessionId != C.AUDIO_SESSION_ID_UNSET) {
|
||||||
|
audioTrack.enableTunnelingV21(tunnelingAudioSessionId);
|
||||||
|
} else {
|
||||||
|
audioTrack.disableTunneling();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -406,6 +406,13 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
|
||||||
protected void onEnabled(boolean joining) throws ExoPlaybackException {
|
protected void onEnabled(boolean joining) throws ExoPlaybackException {
|
||||||
decoderCounters = new DecoderCounters();
|
decoderCounters = new DecoderCounters();
|
||||||
eventDispatcher.enabled(decoderCounters);
|
eventDispatcher.enabled(decoderCounters);
|
||||||
|
// TODO: Allow this to be set.
|
||||||
|
int tunnelingAudioSessionId = C.AUDIO_SESSION_ID_UNSET;
|
||||||
|
if (tunnelingAudioSessionId != C.AUDIO_SESSION_ID_UNSET) {
|
||||||
|
audioTrack.enableTunnelingV21(tunnelingAudioSessionId);
|
||||||
|
} else {
|
||||||
|
audioTrack.disableTunneling();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue