diff --git a/RELEASENOTES.md b/RELEASENOTES.md index f50a5b657e..c414a5684d 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -2,6 +2,9 @@ ### dev-v2 (not yet released) ### +* AV1 extension: Uses libgav1 to decode AV1 videos. Android 10 includes an AV1 + decoder, but the older versions of Android require this extension for playback + of AV1 streams ([#3353](https://github.com/google/ExoPlayer/issues/3353)). * UI * Setting `app:played_color` on `PlayerView` and `PlayerControlView` no longer adjusts the colors of the scrubber handle , buffered and unplayed parts of diff --git a/core_settings.gradle b/core_settings.gradle index 3f6d58f777..0f9746af96 100644 --- a/core_settings.gradle +++ b/core_settings.gradle @@ -24,6 +24,7 @@ include modulePrefix + 'library-hls' include modulePrefix + 'library-smoothstreaming' include modulePrefix + 'library-ui' include modulePrefix + 'testutils' +include modulePrefix + 'extension-av1' include modulePrefix + 'extension-ffmpeg' include modulePrefix + 'extension-flac' include modulePrefix + 'extension-gvr' @@ -46,6 +47,7 @@ project(modulePrefix + 'library-hls').projectDir = new File(rootDir, 'library/hl project(modulePrefix + 'library-smoothstreaming').projectDir = new File(rootDir, 'library/smoothstreaming') project(modulePrefix + 'library-ui').projectDir = new File(rootDir, 'library/ui') project(modulePrefix + 'testutils').projectDir = new File(rootDir, 'testutils') +project(modulePrefix + 'extension-av1').projectDir = new File(rootDir, 'extensions/av1') project(modulePrefix + 'extension-ffmpeg').projectDir = new File(rootDir, 'extensions/ffmpeg') project(modulePrefix + 'extension-flac').projectDir = new File(rootDir, 'extensions/flac') project(modulePrefix + 'extension-gvr').projectDir = new File(rootDir, 'extensions/gvr') diff --git a/demos/main/build.gradle b/demos/main/build.gradle index 06c734986c..a4b4a46663 100644 --- a/demos/main/build.gradle +++ b/demos/main/build.gradle @@ -69,6 +69,7 @@ dependencies { implementation project(modulePrefix + 'library-hls') implementation project(modulePrefix + 'library-smoothstreaming') implementation project(modulePrefix + 'library-ui') + withExtensionsImplementation project(path: modulePrefix + 'extension-av1') withExtensionsImplementation project(path: modulePrefix + 'extension-ffmpeg') withExtensionsImplementation project(path: modulePrefix + 'extension-flac') withExtensionsImplementation project(path: modulePrefix + 'extension-ima') diff --git a/extensions/av1/proguard-rules.txt b/extensions/av1/proguard-rules.txt index 52feb2c5f4..9d73f7e2b5 100644 --- a/extensions/av1/proguard-rules.txt +++ b/extensions/av1/proguard-rules.txt @@ -5,7 +5,3 @@ native ; } -# Some members of this class are being accessed from native methods. Keep them unobfuscated. --keep class com.google.android.exoplayer2.ext.av1.Gav1OutputBuffer { - *; -} diff --git a/library/core/src/main/java/com/google/android/exoplayer2/C.java b/library/core/src/main/java/com/google/android/exoplayer2/C.java index b235715f46..a86d927acb 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/C.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/C.java @@ -521,6 +521,7 @@ public final class C { /** Indicates that a buffer should be decoded but not rendered. */ public static final int BUFFER_FLAG_DECODE_ONLY = 1 << 31; // 0x80000000 + // LINT.IfChange /** * Video decoder output modes. Possible modes are {@link #VIDEO_OUTPUT_MODE_NONE}, {@link * #VIDEO_OUTPUT_MODE_YUV} and {@link #VIDEO_OUTPUT_MODE_SURFACE_YUV}. @@ -535,6 +536,10 @@ public final class C { public static final int VIDEO_OUTPUT_MODE_YUV = 0; /** Video decoder output mode that renders 4:2:0 YUV planes directly to a surface. */ public static final int VIDEO_OUTPUT_MODE_SURFACE_YUV = 1; + // LINT.ThenChange( + // ../../../../../../../../../extensions/av1/src/main/jni/gav1_jni.cc, + // ../../../../../../../../../extensions/vp9/src/main/jni/vpx_jni.cc + // ) /** * Video scaling modes for {@link MediaCodec}-based {@link Renderer}s. One of {@link diff --git a/library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java index a97b1e0d5a..f53d72f598 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java @@ -365,6 +365,33 @@ public class DefaultRenderersFactory implements RenderersFactory { // The extension is present, but instantiation failed. throw new RuntimeException("Error instantiating VP9 extension", e); } + + try { + // Full class names used for constructor args so the LINT rule triggers if any of them move. + // LINT.IfChange + Class clazz = Class.forName("com.google.android.exoplayer2.ext.av1.Libgav1VideoRenderer"); + Constructor constructor = + clazz.getConstructor( + long.class, + android.os.Handler.class, + com.google.android.exoplayer2.video.VideoRendererEventListener.class, + int.class); + // LINT.ThenChange(../../../../../../../proguard-rules.txt) + Renderer renderer = + (Renderer) + constructor.newInstance( + allowedVideoJoiningTimeMs, + eventHandler, + eventListener, + MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY); + out.add(extensionRendererIndex++, renderer); + Log.i(TAG, "Loaded Libgav1VideoRenderer."); + } catch (ClassNotFoundException e) { + // Expected if the app was built without the extension. + } catch (Exception e) { + // The extension is present, but instantiation failed. + throw new RuntimeException("Error instantiating AV1 extension", e); + } } /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderOutputBuffer.java b/library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderOutputBuffer.java index 1289818c02..b179745c36 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderOutputBuffer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/VideoDecoderOutputBuffer.java @@ -34,10 +34,15 @@ public class VideoDecoderOutputBuffer extends OutputBuffer { void releaseOutputBuffer(VideoDecoderOutputBuffer outputBuffer); } + // LINT.IfChange public static final int COLORSPACE_UNKNOWN = 0; public static final int COLORSPACE_BT601 = 1; public static final int COLORSPACE_BT709 = 2; public static final int COLORSPACE_BT2020 = 3; + // LINT.ThenChange( + // ../../../../../../../../../../extensions/av1/src/main/jni/gav1_jni.cc, + // ../../../../../../../../../../extensions/vp9/src/main/jni/vpx_jni.cc + // ) /** Decoder private data. */ public int decoderPrivate;