summaryrefslogtreecommitdiffstats
path: root/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/audio/ChannelMappingAudioProcessor.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/audio/ChannelMappingAudioProcessor.java')
-rw-r--r--mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/audio/ChannelMappingAudioProcessor.java99
1 files changed, 99 insertions, 0 deletions
diff --git a/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/audio/ChannelMappingAudioProcessor.java b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/audio/ChannelMappingAudioProcessor.java
new file mode 100644
index 0000000000..e8496d4608
--- /dev/null
+++ b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/audio/ChannelMappingAudioProcessor.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.mozilla.thirdparty.com.google.android.exoplayer2.audio;
+
+import androidx.annotation.Nullable;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.C;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.util.Assertions;
+import java.nio.ByteBuffer;
+
+/**
+ * An {@link AudioProcessor} that applies a mapping from input channels onto specified output
+ * channels. This can be used to reorder, duplicate or discard channels.
+ */
+@SuppressWarnings("nullness:initialization.fields.uninitialized")
+/* package */ final class ChannelMappingAudioProcessor extends BaseAudioProcessor {
+
+ @Nullable private int[] pendingOutputChannels;
+ @Nullable private int[] outputChannels;
+
+ /**
+ * Resets the channel mapping. After calling this method, call {@link #configure(AudioFormat)} to
+ * start using the new channel map.
+ *
+ * @param outputChannels The mapping from input to output channel indices, or {@code null} to
+ * leave the input unchanged.
+ * @see AudioSink#configure(int, int, int, int, int[], int, int)
+ */
+ public void setChannelMap(@Nullable int[] outputChannels) {
+ pendingOutputChannels = outputChannels;
+ }
+
+ @Override
+ public AudioFormat onConfigure(AudioFormat inputAudioFormat)
+ throws UnhandledAudioFormatException {
+ @Nullable int[] outputChannels = pendingOutputChannels;
+ if (outputChannels == null) {
+ return AudioFormat.NOT_SET;
+ }
+
+ if (inputAudioFormat.encoding != C.ENCODING_PCM_16BIT) {
+ throw new UnhandledAudioFormatException(inputAudioFormat);
+ }
+
+ boolean active = inputAudioFormat.channelCount != outputChannels.length;
+ for (int i = 0; i < outputChannels.length; i++) {
+ int channelIndex = outputChannels[i];
+ if (channelIndex >= inputAudioFormat.channelCount) {
+ throw new UnhandledAudioFormatException(inputAudioFormat);
+ }
+ active |= (channelIndex != i);
+ }
+ return active
+ ? new AudioFormat(inputAudioFormat.sampleRate, outputChannels.length, C.ENCODING_PCM_16BIT)
+ : AudioFormat.NOT_SET;
+ }
+
+ @Override
+ public void queueInput(ByteBuffer inputBuffer) {
+ int[] outputChannels = Assertions.checkNotNull(this.outputChannels);
+ int position = inputBuffer.position();
+ int limit = inputBuffer.limit();
+ int frameCount = (limit - position) / inputAudioFormat.bytesPerFrame;
+ int outputSize = frameCount * outputAudioFormat.bytesPerFrame;
+ ByteBuffer buffer = replaceOutputBuffer(outputSize);
+ while (position < limit) {
+ for (int channelIndex : outputChannels) {
+ buffer.putShort(inputBuffer.getShort(position + 2 * channelIndex));
+ }
+ position += inputAudioFormat.bytesPerFrame;
+ }
+ inputBuffer.position(limit);
+ buffer.flip();
+ }
+
+ @Override
+ protected void onFlush() {
+ outputChannels = pendingOutputChannels;
+ }
+
+ @Override
+ protected void onReset() {
+ outputChannels = null;
+ pendingOutputChannels = null;
+ }
+
+}