Commit 0c0c5942 by andrewlewis Committed by Oliver Woodman

Fix incorrect channel configuration for 8 ch pre-M

AudioTrack checks the channel configuration against a mask of allowed channels.
Before Android M the check in getMinBufferSize would always fail for 8 channel
output.

For Android L constants are available to build the required channel
configuration for a conventional 7.1 setup and these constants are part of the
allowed channels mask, so switch to using them.

Before Android L the constants for 7.1 aren't in the allowed channels mask, so
discard channels to give a 5.1 stream.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=206307892
parent 30fecb71
...@@ -194,13 +194,6 @@ public final class C { ...@@ -194,13 +194,6 @@ public final class C {
public static final int ENCODING_DOLBY_TRUEHD = AudioFormat.ENCODING_DOLBY_TRUEHD; public static final int ENCODING_DOLBY_TRUEHD = AudioFormat.ENCODING_DOLBY_TRUEHD;
/** /**
* @see AudioFormat#CHANNEL_OUT_7POINT1_SURROUND
*/
@SuppressWarnings("deprecation")
public static final int CHANNEL_OUT_7POINT1_SURROUND = Util.SDK_INT < 23
? AudioFormat.CHANNEL_OUT_7POINT1 : AudioFormat.CHANNEL_OUT_7POINT1_SURROUND;
/**
* Stream types for an {@link android.media.AudioTrack}. * Stream types for an {@link android.media.AudioTrack}.
*/ */
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
......
...@@ -416,6 +416,16 @@ public final class DefaultAudioSink implements AudioSink { ...@@ -416,6 +416,16 @@ public final class DefaultAudioSink implements AudioSink {
@C.Encoding int encoding = inputEncoding; @C.Encoding int encoding = inputEncoding;
boolean processingEnabled = isInputPcm && inputEncoding != C.ENCODING_PCM_FLOAT; boolean processingEnabled = isInputPcm && inputEncoding != C.ENCODING_PCM_FLOAT;
canApplyPlaybackParameters = processingEnabled && !shouldConvertHighResIntPcmToFloat; canApplyPlaybackParameters = processingEnabled && !shouldConvertHighResIntPcmToFloat;
if (Util.SDK_INT < 21 && channelCount == 8 && outputChannels == null) {
// AudioTrack doesn't support 8 channel output before Android L. Discard the last two (side)
// channels to give a 6 channel stream that is supported.
outputChannels = new int[6];
for (int i = 0; i < outputChannels.length; i++) {
outputChannels[i] = i;
}
}
if (processingEnabled) { if (processingEnabled) {
trimmingAudioProcessor.setTrimFrameCount(trimStartFrames, trimEndFrames); trimmingAudioProcessor.setTrimFrameCount(trimStartFrames, trimEndFrames);
channelMappingAudioProcessor.setChannelMap(outputChannels); channelMappingAudioProcessor.setChannelMap(outputChannels);
...@@ -433,55 +443,9 @@ public final class DefaultAudioSink implements AudioSink { ...@@ -433,55 +443,9 @@ public final class DefaultAudioSink implements AudioSink {
} }
} }
int channelConfig; int channelConfig = getChannelConfig(channelCount, isInputPcm);
switch (channelCount) { if (channelConfig == AudioFormat.CHANNEL_INVALID) {
case 1: throw new ConfigurationException("Unsupported channel count: " + channelCount);
channelConfig = AudioFormat.CHANNEL_OUT_MONO;
break;
case 2:
channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
break;
case 3:
channelConfig = AudioFormat.CHANNEL_OUT_STEREO | AudioFormat.CHANNEL_OUT_FRONT_CENTER;
break;
case 4:
channelConfig = AudioFormat.CHANNEL_OUT_QUAD;
break;
case 5:
channelConfig = AudioFormat.CHANNEL_OUT_QUAD | AudioFormat.CHANNEL_OUT_FRONT_CENTER;
break;
case 6:
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
break;
case 7:
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1 | AudioFormat.CHANNEL_OUT_BACK_CENTER;
break;
case 8:
channelConfig = C.CHANNEL_OUT_7POINT1_SURROUND;
break;
default:
throw new ConfigurationException("Unsupported channel count: " + channelCount);
}
// Workaround for overly strict channel configuration checks on nVidia Shield.
if (Util.SDK_INT <= 23 && "foster".equals(Util.DEVICE) && "NVIDIA".equals(Util.MANUFACTURER)) {
switch (channelCount) {
case 7:
channelConfig = C.CHANNEL_OUT_7POINT1_SURROUND;
break;
case 3:
case 5:
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
break;
default:
break;
}
}
// Workaround for Nexus Player not reporting support for mono passthrough.
// (See [Internal: b/34268671].)
if (Util.SDK_INT <= 25 && "fugu".equals(Util.DEVICE) && !isInputPcm && channelCount == 1) {
channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
} }
if (!flush if (!flush
...@@ -1170,6 +1134,25 @@ public final class DefaultAudioSink implements AudioSink { ...@@ -1170,6 +1134,25 @@ public final class DefaultAudioSink implements AudioSink {
: toIntPcmAvailableAudioProcessors; : toIntPcmAvailableAudioProcessors;
} }
private static int getChannelConfig(int channelCount, boolean isInputPcm) {
// Workaround for overly strict channel configuration checks on nVidia Shield.
if (Util.SDK_INT <= 23 && "foster".equals(Util.DEVICE) && "NVIDIA".equals(Util.MANUFACTURER)) {
if (channelCount == 7) {
channelCount = 8;
} else if (channelCount == 3 || channelCount == 5) {
channelCount = 6;
}
}
// Workaround for Nexus Player not reporting support for mono passthrough.
// (See [Internal: b/34268671].)
if (Util.SDK_INT <= 25 && "fugu".equals(Util.DEVICE) && !isInputPcm && channelCount == 1) {
channelCount = 2;
}
return Util.getAudioTrackChannelConfig(channelCount);
}
private static int getFramesPerEncodedSample(@C.Encoding int encoding, ByteBuffer buffer) { private static int getFramesPerEncodedSample(@C.Encoding int encoding, ByteBuffer buffer) {
if (encoding == C.ENCODING_DTS || encoding == C.ENCODING_DTS_HD) { if (encoding == C.ENCODING_DTS || encoding == C.ENCODING_DTS_HD) {
return DtsUtil.parseDtsAudioSampleCount(buffer); return DtsUtil.parseDtsAudioSampleCount(buffer);
......
...@@ -25,6 +25,7 @@ import android.content.pm.PackageInfo; ...@@ -25,6 +25,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Point; import android.graphics.Point;
import android.media.AudioFormat;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.Uri; import android.net.Uri;
...@@ -1159,6 +1160,47 @@ public final class Util { ...@@ -1159,6 +1160,47 @@ public final class Util {
} }
/** /**
* Returns the audio track channel configuration for the given channel count, or {@link
* AudioFormat#CHANNEL_INVALID} if output is not poossible.
*
* @param channelCount The number of channels in the input audio.
* @return The channel configuration or {@link AudioFormat#CHANNEL_INVALID} if output is not
* possible.
*/
public static int getAudioTrackChannelConfig(int channelCount) {
switch (channelCount) {
case 1:
return AudioFormat.CHANNEL_OUT_MONO;
case 2:
return AudioFormat.CHANNEL_OUT_STEREO;
case 3:
return AudioFormat.CHANNEL_OUT_STEREO | AudioFormat.CHANNEL_OUT_FRONT_CENTER;
case 4:
return AudioFormat.CHANNEL_OUT_QUAD;
case 5:
return AudioFormat.CHANNEL_OUT_QUAD | AudioFormat.CHANNEL_OUT_FRONT_CENTER;
case 6:
return AudioFormat.CHANNEL_OUT_5POINT1;
case 7:
return AudioFormat.CHANNEL_OUT_5POINT1 | AudioFormat.CHANNEL_OUT_BACK_CENTER;
case 8:
if (Util.SDK_INT >= 23) {
return AudioFormat.CHANNEL_OUT_7POINT1_SURROUND;
} else if (Util.SDK_INT >= 21) {
// Equal to AudioFormat.CHANNEL_OUT_7POINT1_SURROUND, which is hidden before Android M.
return AudioFormat.CHANNEL_OUT_5POINT1
| AudioFormat.CHANNEL_OUT_SIDE_LEFT
| AudioFormat.CHANNEL_OUT_SIDE_RIGHT;
} else {
// 8 ch output is not supported before Android L.
return AudioFormat.CHANNEL_INVALID;
}
default:
return AudioFormat.CHANNEL_INVALID;
}
}
/**
* Returns the frame size for audio with {@code channelCount} channels in the specified encoding. * Returns the frame size for audio with {@code channelCount} channels in the specified encoding.
* *
* @param pcmEncoding The encoding of the audio data. * @param pcmEncoding The encoding of the audio data.
......
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