Audio improvements.

This commit is contained in:
Oliver Woodman 2014-12-03 18:33:36 +00:00
parent 2e1f9897e7
commit 6652f864bd
2 changed files with 29 additions and 4 deletions

View File

@ -40,7 +40,7 @@ public final class AudioCapabilitiesReceiver {
}
/** Default to stereo PCM on SDK <= 21 and when HDMI is unplugged. */
/** Default to stereo PCM on SDK < 21 and when HDMI is unplugged. */
private static final AudioCapabilities DEFAULT_AUDIO_CAPABILITIES =
new AudioCapabilities(new int[] {AudioFormat.ENCODING_PCM_16BIT}, 2);

View File

@ -19,6 +19,7 @@ import com.google.android.exoplayer.C;
import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.Util;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.media.AudioFormat;
import android.media.AudioManager;
@ -96,6 +97,9 @@ public final class AudioTrack {
*/
private static final long MAX_LATENCY_US = 10 * C.MICROS_PER_SECOND;
/** Value for ac3Bitrate before the bitrate has been calculated. */
private static final int UNKNOWN_AC3_BITRATE = 0;
private static final int START_NOT_SET = 0;
private static final int START_IN_SYNC = 1;
private static final int START_NEED_SYNC = 2;
@ -138,6 +142,11 @@ public final class AudioTrack {
private int temporaryBufferOffset;
private int temporaryBufferSize;
private boolean isAc3;
/** Bitrate measured in kilobits per second, if {@link #isAc3} is true. */
private int ac3Bitrate;
/** Constructs an audio track using the default minimum buffer size multiplier. */
public AudioTrack() {
this(DEFAULT_MIN_BUFFER_MULTIPLICATION_FACTOR);
@ -276,6 +285,7 @@ public final class AudioTrack {
* @param bufferSize The total size of the playback buffer in bytes. Specify 0 to use a buffer
* size based on the minimum for format.
*/
@SuppressLint("InlinedApi")
public void reconfigure(MediaFormat format, int encoding, int bufferSize) {
int channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
int channelConfig;
@ -299,8 +309,9 @@ public final class AudioTrack {
int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
// TODO: Does channelConfig determine channelCount?
boolean isAc3 = encoding == AudioFormat.ENCODING_AC3 || encoding == AudioFormat.ENCODING_E_AC3;
if (audioTrack != null && this.sampleRate == sampleRate
&& this.channelConfig == channelConfig) {
&& this.channelConfig == channelConfig && !this.isAc3 && !isAc3) {
// We already have an existing audio track with the correct sample rate and channel config.
return;
}
@ -314,7 +325,8 @@ public final class AudioTrack {
bufferSize == 0 ? (int) (minBufferMultiplicationFactor * minBufferSize) : bufferSize;
this.sampleRate = sampleRate;
this.channelConfig = channelConfig;
this.isAc3 = isAc3;
ac3Bitrate = UNKNOWN_AC3_BITRATE; // Calculated on receiving the first buffer if isAc3 is true.
frameSize = 2 * channelCount; // 2 bytes per 16 bit sample * number of channels.
}
@ -352,6 +364,14 @@ public final class AudioTrack {
int result = 0;
if (temporaryBufferSize == 0 && size != 0) {
if (isAc3 && ac3Bitrate == UNKNOWN_AC3_BITRATE) {
// Each AC-3 buffer contains 1536 frames of audio, so the AudioTrack playback position
// advances by 1536 per buffer (32 ms at 48 kHz). Calculate the bitrate in kbit/s.
int unscaledAc3Bitrate = size * 8 * sampleRate;
int divisor = 1000 * 1536;
ac3Bitrate = (unscaledAc3Bitrate + divisor / 2) / divisor;
}
// This is the first time we've seen this {@code buffer}.
// Note: presentationTimeUs corresponds to the end of the sample, not the start.
long bufferStartTime = presentationTimeUs - framesToDurationUs(bytesToFrames(size));
@ -615,11 +635,16 @@ public final class AudioTrack {
}
private long framesToBytes(long frameCount) {
// This method is unused on SDK >= 21.
return frameCount * frameSize;
}
private long bytesToFrames(long byteCount) {
return byteCount / frameSize;
if (isAc3) {
return byteCount * 8 * sampleRate / (1000 * ac3Bitrate);
} else {
return byteCount / frameSize;
}
}
private long framesToDurationUs(long frameCount) {