Commit 632ccc6c by Oliver Woodman

Simplify passthrough playback rate calculation.

This change also fixes pre-M DTS HD passthrough playback on NVIDIA Shield.
parent b8e7e107
...@@ -160,8 +160,8 @@ public class EventLogger implements DemoPlayer.Listener, DemoPlayer.InfoListener ...@@ -160,8 +160,8 @@ public class EventLogger implements DemoPlayer.Listener, DemoPlayer.InfoListener
} }
@Override @Override
public void onAudioTrackUnderrun(long audioTrackBufferSizeMs, long elapsedSinceLastFeedMs) { public void onAudioTrackUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
printInternalError("audioTrackUnderrun [" + audioTrackBufferSizeMs + ", " printInternalError("audioTrackUnderrun [" + bufferSize + ", " + bufferSizeMs + ", "
+ elapsedSinceLastFeedMs + "]", null); + elapsedSinceLastFeedMs + "]", null);
} }
......
...@@ -105,7 +105,7 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi ...@@ -105,7 +105,7 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi
void onRendererInitializationError(Exception e); void onRendererInitializationError(Exception e);
void onAudioTrackInitializationError(AudioTrack.InitializationException e); void onAudioTrackInitializationError(AudioTrack.InitializationException e);
void onAudioTrackWriteError(AudioTrack.WriteException e); void onAudioTrackWriteError(AudioTrack.WriteException e);
void onAudioTrackUnderrun(long audioTrackBufferSizeMs, long elapsedSinceLastFeedMs); void onAudioTrackUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs);
void onDecoderInitializationError(DecoderInitializationException e); void onDecoderInitializationError(DecoderInitializationException e);
void onCryptoError(CryptoException e); void onCryptoError(CryptoException e);
void onLoadError(int sourceId, IOException e); void onLoadError(int sourceId, IOException e);
...@@ -483,9 +483,9 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi ...@@ -483,9 +483,9 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi
} }
@Override @Override
public void onAudioTrackUnderrun(long audioTrackBufferSizeMs, long elapsedSinceLastFeedMs) { public void onAudioTrackUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
if (internalErrorListener != null) { if (internalErrorListener != null) {
internalErrorListener.onAudioTrackUnderrun(audioTrackBufferSizeMs, elapsedSinceLastFeedMs); internalErrorListener.onAudioTrackUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs);
} }
} }
......
...@@ -59,10 +59,13 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem ...@@ -59,10 +59,13 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem
/** /**
* Invoked when an {@link AudioTrack} underrun occurs. * Invoked when an {@link AudioTrack} underrun occurs.
* *
* @param audioTrackBufferSizeMs The size of the {@link AudioTrack}'s buffer, in milliseconds. * @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. -1 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. * @param elapsedSinceLastFeedMs The time since the {@link AudioTrack} was last fed data.
*/ */
void onAudioTrackUnderrun(long audioTrackBufferSizeMs, long elapsedSinceLastFeedMs); void onAudioTrackUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs);
} }
...@@ -355,7 +358,9 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem ...@@ -355,7 +358,9 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem
audioTrackHasData = audioTrack.hasPendingData(); audioTrackHasData = audioTrack.hasPendingData();
if (audioTrackHadData && !audioTrackHasData && getState() == TrackRenderer.STATE_STARTED) { if (audioTrackHadData && !audioTrackHasData && getState() == TrackRenderer.STATE_STARTED) {
long elapsedSinceLastFeedMs = SystemClock.elapsedRealtime() - lastFeedElapsedRealtimeMs; long elapsedSinceLastFeedMs = SystemClock.elapsedRealtime() - lastFeedElapsedRealtimeMs;
notifyAudioTrackUnderrun(audioTrack.getBufferSizeUs() / 1000, elapsedSinceLastFeedMs); long bufferSizeUs = audioTrack.getBufferSizeUs();
long bufferSizeMs = bufferSizeUs == C.UNKNOWN_TIME_US ? -1 : bufferSizeUs / 1000;
notifyAudioTrackUnderrun(audioTrack.getBufferSize(), bufferSizeMs, elapsedSinceLastFeedMs);
} }
} }
...@@ -425,13 +430,13 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem ...@@ -425,13 +430,13 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem
} }
} }
private void notifyAudioTrackUnderrun(final long audioTrackBufferSizeMs, private void notifyAudioTrackUnderrun(final int bufferSize, final long bufferSizeMs,
final long elapsedSinceLastFeedMs) { final long elapsedSinceLastFeedMs) {
if (eventHandler != null && eventListener != null) { if (eventHandler != null && eventListener != null) {
eventHandler.post(new Runnable() { eventHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
eventListener.onAudioTrackUnderrun(audioTrackBufferSizeMs, elapsedSinceLastFeedMs); eventListener.onAudioTrackUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs);
} }
}); });
} }
......
...@@ -17,19 +17,41 @@ package com.google.android.exoplayer.util; ...@@ -17,19 +17,41 @@ package com.google.android.exoplayer.util;
import com.google.android.exoplayer.MediaFormat; import com.google.android.exoplayer.MediaFormat;
import java.nio.ByteBuffer;
/** /**
* Utility methods for parsing AC-3 headers. * Utility methods for parsing AC-3 headers.
*/ */
public final class Ac3Util { public final class Ac3Util {
/** Sample rates, indexed by fscod. */ /**
* The number of new samples per (E-)AC-3 audio block.
*/
private static final int SAMPLES_PER_AUDIO_BLOCK = 256;
/**
* Each syncframe has 6 blocks that provide 256 new samples. See ETSI TS 102 366 subsection 4.1.
*/
private static final int AC3_SAMPLES_PER_SYNCFRAME = 6 * SAMPLES_PER_AUDIO_BLOCK;
/**
* Number of audio blocks per E-AC-3 sync frame, indexed by numblkscod.
*/
private static final int[] AUDIO_BLOCKS_PER_SYNCFRAME_BY_NUMBLKSCOD = new int[] {1, 2, 3, 6};
/**
* Sample rates, indexed by fscod.
*/
private static final int[] SAMPLE_RATES = new int[] {48000, 44100, 32000}; private static final int[] SAMPLE_RATES = new int[] {48000, 44100, 32000};
/** Channel counts, indexed by acmod. */ /**
* Channel counts, indexed by acmod.
*/
private static final int[] CHANNEL_COUNTS = new int[] {2, 1, 2, 3, 3, 4, 4, 5}; private static final int[] CHANNEL_COUNTS = new int[] {2, 1, 2, 3, 3, 4, 4, 5};
/** Nominal bitrates in kbps, indexed by bit_rate_code. */ /**
* Nominal bitrates in kbps, indexed by bit_rate_code.
*/
private static final int[] BITRATES = new int[] {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, private static final int[] BITRATES = new int[] {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192,
224, 256, 320, 384, 448, 512, 576, 640}; 224, 256, 320, 384, 448, 512, 576, 640};
/** 16-bit words per sync frame, indexed by frmsizecod / 2. (See ETSI TS 102 366 table 4.13.) */ /**
* 16-bit words per sync frame, indexed by frmsizecod / 2. (See ETSI TS 102 366 table 4.13.)
*/
private static final int[] FRMSIZECOD_TO_FRAME_SIZE_44_1 = new int[] {69, 87, 104, 121, 139, 174, private static final int[] FRMSIZECOD_TO_FRAME_SIZE_44_1 = new int[] {69, 87, 104, 121, 139, 174,
208, 243, 278, 348, 417, 487, 557, 696, 835, 975, 1114, 1253, 1393}; 208, 243, 278, 348, 417, 487, 557, 696, 835, 975, 1114, 1253, 1393};
...@@ -161,6 +183,31 @@ public final class Ac3Util { ...@@ -161,6 +183,31 @@ public final class Ac3Util {
return (unscaledBitrate + divisor / 2) / divisor; return (unscaledBitrate + divisor / 2) / divisor;
} }
/**
* Returns the number of samples per AC-3 syncframe.
*/
public static int getAc3SamplesPerSyncframe() {
return AC3_SAMPLES_PER_SYNCFRAME;
}
/**
* Returns the number of samples per syncframe for the E-AC-3 frame in {@code buffer}.
*
* @param buffer The frame to parse.
* @return The number of samples per syncframe.
*/
public static int parseEac3SamplesPerSyncframe(ByteBuffer buffer) {
// See ETSI TS 102 366 subsection E.1.2.2.
int audioBlocks;
if (((buffer.get(buffer.position() + 4) & 0xC0) >> 6) == 0x03) { // fscod
audioBlocks = 6;
} else {
int numblkscod = (buffer.get(buffer.position() + 4) & 0x30) >> 4;
audioBlocks = AUDIO_BLOCKS_PER_SYNCFRAME_BY_NUMBLKSCOD[numblkscod] * 256;
}
return audioBlocks * SAMPLES_PER_AUDIO_BLOCK;
}
private Ac3Util() { private Ac3Util() {
// Prevent instantiation. // Prevent instantiation.
} }
......
...@@ -105,9 +105,9 @@ public final class LogcatLogger implements ExoPlayer.Listener, ...@@ -105,9 +105,9 @@ public final class LogcatLogger implements ExoPlayer.Listener,
} }
@Override @Override
public void onAudioTrackUnderrun(long audioTrackBufferSizeMs, long elapsedSinceLastFeedMs) { public void onAudioTrackUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
Log.e(tag, "Audio track underrun (" + audioTrackBufferSizeMs + ", " + elapsedSinceLastFeedMs Log.e(tag, "Audio track underrun (" + bufferSize + ", " + bufferSizeMs + ", "
+ ")"); + elapsedSinceLastFeedMs + ")");
} }
@Override @Override
......
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