diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 56abb10cb9..a795841ee8 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -142,6 +142,8 @@
* Deprecate `setControlDispatcher` in `LeanbackPlayerAdapter`.
* Media2 extension:
* Deprecate `setControlDispatcher` in `SessionPlayerConnector`.
+* GVR extension:
+ * Remove `GvrAudioProcessor`, which has been deprecated since 2.11.0.
* RTSP:
* Use standard RTSP header names
([#9182](https://github.com/google/ExoPlayer/issues/9182)).
diff --git a/core_settings.gradle b/core_settings.gradle
index ffee74bccf..7fc3a4c3e2 100644
--- a/core_settings.gradle
+++ b/core_settings.gradle
@@ -48,8 +48,6 @@ include modulePrefix + 'extension-ffmpeg'
project(modulePrefix + 'extension-ffmpeg').projectDir = new File(rootDir, 'extensions/ffmpeg')
include modulePrefix + 'extension-flac'
project(modulePrefix + 'extension-flac').projectDir = new File(rootDir, 'extensions/flac')
-include modulePrefix + 'extension-gvr'
-project(modulePrefix + 'extension-gvr').projectDir = new File(rootDir, 'extensions/gvr')
include modulePrefix + 'extension-ima'
project(modulePrefix + 'extension-ima').projectDir = new File(rootDir, 'extensions/ima')
include modulePrefix + 'extension-cast'
diff --git a/extensions/gvr/README.md b/extensions/gvr/README.md
deleted file mode 100644
index 43a9e2cb62..0000000000
--- a/extensions/gvr/README.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# ExoPlayer GVR extension #
-
-**DEPRECATED - If you still need this extension, please contact us by filing an
-issue on our [issue tracker][].**
-
-The GVR extension wraps the [Google VR SDK for Android][]. It provides a
-GvrAudioProcessor, which uses [GvrAudioSurround][] to provide binaural rendering
-of surround sound and ambisonic soundfields.
-
-[Google VR SDK for Android]: https://developers.google.com/vr/android/
-[GvrAudioSurround]: https://developers.google.com/vr/android/reference/com/google/vr/sdk/audio/GvrAudioSurround
-[issue tracker]: https://github.com/google/ExoPlayer/issues
-
-## Getting the extension ##
-
-The easiest way to use the extension is to add it as a gradle dependency:
-
-```gradle
-implementation 'com.google.android.exoplayer:extension-gvr:2.X.X'
-```
-
-where `2.X.X` is the version, which must match the version of the ExoPlayer
-library being used.
-
-Alternatively, you can clone the ExoPlayer repository and depend on the module
-locally. Instructions for doing this can be found in ExoPlayer's
-[top level README][].
-
-## Using the extension ##
-
-* If using `DefaultRenderersFactory`, override
- `DefaultRenderersFactory.buildAudioProcessors` to return a
- `GvrAudioProcessor`.
-* If constructing renderers directly, pass a `GvrAudioProcessor` to
- `MediaCodecAudioRenderer`'s constructor.
-
-[top level README]: https://github.com/google/ExoPlayer/blob/release-v2/README.md
-
-## Links ##
-
-* [Javadoc][]: Classes matching `com.google.android.exoplayer2.ext.gvr.*`
- belong to this module.
-
-[Javadoc]: https://exoplayer.dev/doc/reference/index.html
diff --git a/extensions/gvr/build.gradle b/extensions/gvr/build.gradle
deleted file mode 100644
index db508e5137..0000000000
--- a/extensions/gvr/build.gradle
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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.
-apply from: "$gradle.ext.exoplayerSettingsDir/common_library_config.gradle"
-
-android.defaultConfig.minSdkVersion 19
-
-dependencies {
- implementation project(modulePrefix + 'library-core')
- implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion
- api 'com.google.vr:sdk-base:1.190.0'
- compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion
- compileOnly 'org.jetbrains.kotlin:kotlin-annotations-jvm:' + kotlinAnnotationsVersion
-}
-
-ext {
- javadocTitle = 'GVR extension'
-}
-apply from: '../../javadoc_library.gradle'
-
-ext {
- releaseArtifact = 'extension-gvr'
- releaseDescription = 'Google VR extension for ExoPlayer.'
-}
-apply from: '../../publish.gradle'
diff --git a/extensions/gvr/src/main/AndroidManifest.xml b/extensions/gvr/src/main/AndroidManifest.xml
deleted file mode 100644
index 6706b2507e..0000000000
--- a/extensions/gvr/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
diff --git a/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java b/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java
deleted file mode 100644
index 0fc6f54285..0000000000
--- a/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * 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 androidx.annotation.Nullable;
-import com.google.android.exoplayer2.C;
-import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
-import com.google.android.exoplayer2.audio.AudioProcessor;
-import com.google.android.exoplayer2.util.Assertions;
-import com.google.vr.sdk.audio.GvrAudioSurround;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * An {@link AudioProcessor} that uses {@code GvrAudioSurround} to provide binaural rendering of
- * surround sound and ambisonic soundfields.
- *
- * @deprecated If you still need this component, please contact us by filing an issue on our issue tracker.
- */
-@Deprecated
-public class GvrAudioProcessor implements AudioProcessor {
-
- static {
- ExoPlayerLibraryInfo.registerModule("goog.exo.gvr");
- }
-
- 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 static final int NO_SURROUND_FORMAT = GvrAudioSurround.SurroundFormat.INVALID;
-
- private AudioFormat pendingInputAudioFormat;
- private int pendingGvrAudioSurroundFormat;
- @Nullable private GvrAudioSurround gvrAudioSurround;
- private ByteBuffer buffer;
- private boolean inputEnded;
-
- private float w;
- private float x;
- private float y;
- private float z;
-
- /** Creates a new GVR audio processor. */
- public GvrAudioProcessor() {
- // Use the identity for the initial orientation.
- w = 1f;
- pendingInputAudioFormat = AudioFormat.NOT_SET;
- buffer = EMPTY_BUFFER;
- pendingGvrAudioSurroundFormat = NO_SURROUND_FORMAT;
- }
-
- /**
- * Updates the listener head orientation. May be called on any thread. See {@code
- * GvrAudioSurround.updateNativeOrientation}.
- *
- * @param w The w component of the quaternion.
- * @param x The x component of the quaternion.
- * @param y The y component of the quaternion.
- * @param z The z component of the quaternion.
- */
- 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);
- }
- }
-
- @SuppressWarnings("ReferenceEquality")
- @Override
- public synchronized AudioFormat configure(AudioFormat inputAudioFormat)
- throws UnhandledAudioFormatException {
- if (inputAudioFormat.encoding != C.ENCODING_PCM_16BIT) {
- maybeReleaseGvrAudioSurround();
- throw new UnhandledAudioFormatException(inputAudioFormat);
- }
- switch (inputAudioFormat.channelCount) {
- case 1:
- pendingGvrAudioSurroundFormat = GvrAudioSurround.SurroundFormat.SURROUND_MONO;
- break;
- case 2:
- pendingGvrAudioSurroundFormat = GvrAudioSurround.SurroundFormat.SURROUND_STEREO;
- break;
- case 4:
- pendingGvrAudioSurroundFormat = GvrAudioSurround.SurroundFormat.FIRST_ORDER_AMBISONICS;
- break;
- case 6:
- pendingGvrAudioSurroundFormat = GvrAudioSurround.SurroundFormat.SURROUND_FIVE_DOT_ONE;
- break;
- case 9:
- pendingGvrAudioSurroundFormat = GvrAudioSurround.SurroundFormat.SECOND_ORDER_AMBISONICS;
- break;
- case 16:
- pendingGvrAudioSurroundFormat = GvrAudioSurround.SurroundFormat.THIRD_ORDER_AMBISONICS;
- break;
- default:
- throw new UnhandledAudioFormatException(inputAudioFormat);
- }
- if (buffer == EMPTY_BUFFER) {
- buffer =
- ByteBuffer.allocateDirect(FRAMES_PER_OUTPUT_BUFFER * OUTPUT_FRAME_SIZE)
- .order(ByteOrder.nativeOrder());
- }
- pendingInputAudioFormat = inputAudioFormat;
- return new AudioFormat(inputAudioFormat.sampleRate, OUTPUT_CHANNEL_COUNT, C.ENCODING_PCM_16BIT);
- }
-
- @Override
- public boolean isActive() {
- return pendingGvrAudioSurroundFormat != NO_SURROUND_FORMAT || gvrAudioSurround != null;
- }
-
- @Override
- public void queueInput(ByteBuffer inputBuffer) {
- int position = inputBuffer.position();
- Assertions.checkNotNull(gvrAudioSurround);
- int readBytes =
- gvrAudioSurround.addInput(inputBuffer, position, inputBuffer.limit() - position);
- inputBuffer.position(position + readBytes);
- }
-
- @Override
- public void queueEndOfStream() {
- // TODO(internal b/174554082): assert gvrAudioSurround is non-null here and in getOutput.
- if (gvrAudioSurround != null) {
- gvrAudioSurround.triggerProcessing();
- }
- inputEnded = true;
- }
-
- @Override
- public ByteBuffer getOutput() {
- if (gvrAudioSurround == null) {
- return EMPTY_BUFFER;
- }
- int writtenBytes = gvrAudioSurround.getOutput(buffer, 0, buffer.capacity());
- buffer.position(0).limit(writtenBytes);
- return buffer;
- }
-
- @Override
- public boolean isEnded() {
- return inputEnded
- && (gvrAudioSurround == null || gvrAudioSurround.getAvailableOutputSize() == 0);
- }
-
- @Override
- public void flush() {
- if (pendingGvrAudioSurroundFormat != NO_SURROUND_FORMAT) {
- maybeReleaseGvrAudioSurround();
- gvrAudioSurround =
- new GvrAudioSurround(
- pendingGvrAudioSurroundFormat,
- pendingInputAudioFormat.sampleRate,
- pendingInputAudioFormat.channelCount,
- FRAMES_PER_OUTPUT_BUFFER);
- gvrAudioSurround.updateNativeOrientation(w, x, y, z);
- pendingGvrAudioSurroundFormat = NO_SURROUND_FORMAT;
- } else if (gvrAudioSurround != null) {
- gvrAudioSurround.flush();
- }
- inputEnded = false;
- }
-
- @Override
- public synchronized void reset() {
- maybeReleaseGvrAudioSurround();
- updateOrientation(/* w= */ 1f, /* x= */ 0f, /* y= */ 0f, /* z= */ 0f);
- inputEnded = false;
- pendingInputAudioFormat = AudioFormat.NOT_SET;
- buffer = EMPTY_BUFFER;
- pendingGvrAudioSurroundFormat = NO_SURROUND_FORMAT;
- }
-
- private void maybeReleaseGvrAudioSurround() {
- if (gvrAudioSurround != null) {
- gvrAudioSurround.release();
- gvrAudioSurround = null;
- }
- }
-}
diff --git a/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/package-info.java b/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/package-info.java
deleted file mode 100644
index 155317fc29..0000000000
--- a/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/package-info.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-@NonNullApi
-package com.google.android.exoplayer2.ext.gvr;
-
-import com.google.android.exoplayer2.util.NonNullApi;