mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Add GVR spatial audio rendering extension.
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=148658631
This commit is contained in:
parent
b3cfeaa17b
commit
1120e10273
16
extensions/gvr/src/main/AndroidManifest.xml
Normal file
16
extensions/gvr/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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.
|
||||
-->
|
||||
<manifest package="com.google.android.exoplayer2.ext.gvr"/>
|
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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 com.google.android.exoplayer2.ext.gvr;
|
||||
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.audio.BufferProcessor;
|
||||
import com.google.vr.sdk.audio.GvrAudioSurround;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
/**
|
||||
* Buffer processor that uses {@code GvrAudioSurround} to provide binaural rendering of surround
|
||||
* sound and ambisonic soundfields.
|
||||
*/
|
||||
public final class GvrBufferProcessor implements BufferProcessor {
|
||||
|
||||
private static final int FRAMES_PER_OUTPUT_BUFFER = 1024;
|
||||
private static final int OUTPUT_CHANNEL_COUNT = 2;
|
||||
private static final int OUTPUT_FRAME_SIZE = OUTPUT_CHANNEL_COUNT * 2; // 16-bit stereo output.
|
||||
|
||||
private int sampleRateHz;
|
||||
private int channelCount;
|
||||
private GvrAudioSurround gvrAudioSurround;
|
||||
private ByteBuffer buffer;
|
||||
private boolean inputEnded;
|
||||
|
||||
private float w;
|
||||
private float x;
|
||||
private float y;
|
||||
private float z;
|
||||
|
||||
public GvrBufferProcessor() {
|
||||
// Use the identity for the initial orientation.
|
||||
w = 1f;
|
||||
sampleRateHz = Format.NO_VALUE;
|
||||
channelCount = Format.NO_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the listener head orientation. May be called on any thread. See
|
||||
* {@code GvrAudioSurround.updateNativeOrientation}.
|
||||
*/
|
||||
public synchronized void updateOrientation(float w, float x, float y, float z) {
|
||||
this.w = w;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
if (gvrAudioSurround != null) {
|
||||
gvrAudioSurround.updateNativeOrientation(w, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean configure(int sampleRateHz, int channelCount,
|
||||
@C.Encoding int encoding) throws UnhandledFormatException {
|
||||
if (encoding != C.ENCODING_PCM_16BIT) {
|
||||
maybeReleaseGvrAudioSurround();
|
||||
throw new UnhandledFormatException(sampleRateHz, channelCount, encoding);
|
||||
}
|
||||
if (this.sampleRateHz == sampleRateHz && this.channelCount == channelCount) {
|
||||
return false;
|
||||
}
|
||||
this.sampleRateHz = sampleRateHz;
|
||||
this.channelCount = channelCount;
|
||||
maybeReleaseGvrAudioSurround();
|
||||
int surroundFormat;
|
||||
switch (channelCount) {
|
||||
case 2:
|
||||
surroundFormat = GvrAudioSurround.SurroundFormat.SURROUND_STEREO;
|
||||
break;
|
||||
case 4:
|
||||
surroundFormat = GvrAudioSurround.SurroundFormat.FIRST_ORDER_AMBISONICS;
|
||||
break;
|
||||
case 6:
|
||||
surroundFormat = GvrAudioSurround.SurroundFormat.SURROUND_FIVE_DOT_ONE;
|
||||
break;
|
||||
case 9:
|
||||
surroundFormat = GvrAudioSurround.SurroundFormat.SECOND_ORDER_AMBISONICS;
|
||||
break;
|
||||
case 16:
|
||||
surroundFormat = GvrAudioSurround.SurroundFormat.THIRD_ORDER_AMBISONICS;
|
||||
break;
|
||||
default:
|
||||
throw new UnhandledFormatException(sampleRateHz, channelCount, encoding);
|
||||
}
|
||||
gvrAudioSurround = new GvrAudioSurround(surroundFormat, sampleRateHz, channelCount,
|
||||
FRAMES_PER_OUTPUT_BUFFER);
|
||||
gvrAudioSurround.updateNativeOrientation(w, x, y, z);
|
||||
if (buffer == null) {
|
||||
buffer = ByteBuffer.allocateDirect(FRAMES_PER_OUTPUT_BUFFER * OUTPUT_FRAME_SIZE)
|
||||
.order(ByteOrder.nativeOrder());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return gvrAudioSurround != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOutputChannelCount() {
|
||||
return OUTPUT_CHANNEL_COUNT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOutputEncoding() {
|
||||
return C.ENCODING_PCM_16BIT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueInput(ByteBuffer input) {
|
||||
int position = input.position();
|
||||
int readBytes = gvrAudioSurround.addInput(input, position, input.limit() - position);
|
||||
input.position(position + readBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueEndOfStream() {
|
||||
inputEnded = true;
|
||||
gvrAudioSurround.triggerProcessing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer getOutput() {
|
||||
int writtenBytes = gvrAudioSurround.getOutput(buffer, 0, buffer.capacity());
|
||||
buffer.position(0).limit(writtenBytes);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnded() {
|
||||
return inputEnded && gvrAudioSurround.getAvailableOutputSize() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
gvrAudioSurround.flush();
|
||||
inputEnded = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void release() {
|
||||
buffer = null;
|
||||
maybeReleaseGvrAudioSurround();
|
||||
}
|
||||
|
||||
private void maybeReleaseGvrAudioSurround() {
|
||||
if (this.gvrAudioSurround != null) {
|
||||
GvrAudioSurround gvrAudioSurround = this.gvrAudioSurround;
|
||||
this.gvrAudioSurround = null;
|
||||
gvrAudioSurround.release();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -17,6 +17,7 @@ include ':demo'
|
||||
include ':playbacktests'
|
||||
include ':extension-ffmpeg'
|
||||
include ':extension-flac'
|
||||
include ':extension-gvr'
|
||||
include ':extension-okhttp'
|
||||
include ':extension-opus'
|
||||
include ':extension-vp9'
|
||||
@ -25,6 +26,7 @@ include ':extension-vp9'
|
||||
|
||||
project(':extension-ffmpeg').projectDir = new File(settingsDir, 'extensions/ffmpeg')
|
||||
project(':extension-flac').projectDir = new File(settingsDir, 'extensions/flac')
|
||||
project(':extension-gvr').projectDir = new File(settingsDir, 'extensions/gvr')
|
||||
project(':extension-okhttp').projectDir = new File(settingsDir, 'extensions/okhttp')
|
||||
project(':extension-opus').projectDir = new File(settingsDir, 'extensions/opus')
|
||||
project(':extension-vp9').projectDir = new File(settingsDir, 'extensions/vp9')
|
||||
|
Loading…
x
Reference in New Issue
Block a user