Aperture: Move to AndroidX Media3 for video capture preview

Change-Id: I4aa4e6c880766d6b8faf04b4961358f5d79cc1a6
diff --git a/app/Android.bp b/app/Android.bp
index 58bedde..a3f3a70 100644
--- a/app/Android.bp
+++ b/app/Android.bp
@@ -28,6 +28,8 @@
         "Aperture_androidx.camera_camera-video",
         "Aperture_androidx.camera_camera-view",
         "Aperture_androidx.camera_camera-extensions",
+        "Aperture_androidx.media3_media3-exoplayer",
+        "Aperture_androidx.media3_media3-ui",
         "Aperture_com.google.zxing_core",
         "Aperture_io.coil-kt_coil",
         "Aperture_io.coil-kt_coil-video",
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 73ad61b..d1455ca 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -72,6 +72,13 @@
     // If you want to additionally use the CameraX Extensions library
     implementation("androidx.camera:camera-extensions:${cameraxVersion}")
 
+    // Media3
+    val media3Version = "1.0.0-beta02"
+    // For media playback using ExoPlayer
+    implementation("androidx.media3:media3-exoplayer:$media3Version")
+    // For building media playback UIs
+    implementation("androidx.media3:media3-ui:$media3Version")
+
     // ZXing
     implementation("com.google.zxing:core:3.5.0")
 
@@ -122,6 +129,7 @@
         when (it) {
             "androidx.constraintlayout:constraintlayout" -> "androidx-constraintlayout_constraintlayout"
             "com.google.auto.value:auto-value-annotations" -> "auto_value_annotations"
+            "com.google.guava:guava" -> "guava"
             "com.google.guava:listenablefuture" -> "guava"
             "org.jetbrains.kotlin:kotlin-stdlib" -> "kotlin-stdlib"
             "org.jetbrains.kotlin:kotlin-stdlib-jdk8" -> "kotlin-stdlib-jdk8"
@@ -133,8 +141,10 @@
     val isAvailableInAosp = { group: String, artifactId: String ->
         when {
             group.startsWith("androidx") -> {
-                // We provide our own androidx.camera & lifecycle-common
-                !group.startsWith("androidx.camera") && artifactId != "lifecycle-common"
+                // We provide our own androidx.{camera,media3} & lifecycle-common
+                !group.startsWith("androidx.camera") &&
+                        !group.startsWith("androidx.media3") &&
+                        artifactId != "lifecycle-common"
             }
             group.startsWith("org.jetbrains") -> true
             group == "com.google.auto.value" -> true
diff --git a/app/libs/Android.bp b/app/libs/Android.bp
index 1caab90..18f77cd 100644
--- a/app/libs/Android.bp
+++ b/app/libs/Android.bp
@@ -282,6 +282,250 @@
 }
 
 android_library_import {
+    name: "Aperture_androidx.media3_media3-common-nodeps",
+    aars: ["androidx/media3/media3-common/1.0.0-beta02/media3-common-1.0.0-beta02.aar"],
+    sdk_version: "33",
+    min_sdk_version: "14",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    static_libs: [
+        "guava",
+        "androidx.annotation_annotation-experimental",
+        "androidx.annotation_annotation",
+    ],
+}
+
+android_library {
+    name: "Aperture_androidx.media3_media3-common",
+    sdk_version: "33",
+    min_sdk_version: "14",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    manifest: "androidx/media3/media3-common/1.0.0-beta02/AndroidManifest.xml",
+    static_libs: [
+        "Aperture_androidx.media3_media3-common-nodeps",
+        "guava",
+        "androidx.annotation_annotation-experimental",
+        "androidx.annotation_annotation",
+    ],
+    java_version: "1.7",
+}
+
+android_library_import {
+    name: "Aperture_androidx.media3_media3-database-nodeps",
+    aars: ["androidx/media3/media3-database/1.0.0-beta02/media3-database-1.0.0-beta02.aar"],
+    sdk_version: "33",
+    min_sdk_version: "14",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    static_libs: [
+        "Aperture_androidx.media3_media3-common",
+        "androidx.annotation_annotation",
+    ],
+}
+
+android_library {
+    name: "Aperture_androidx.media3_media3-database",
+    sdk_version: "33",
+    min_sdk_version: "14",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    manifest: "androidx/media3/media3-database/1.0.0-beta02/AndroidManifest.xml",
+    static_libs: [
+        "Aperture_androidx.media3_media3-database-nodeps",
+        "Aperture_androidx.media3_media3-common",
+        "androidx.annotation_annotation",
+    ],
+    java_version: "1.7",
+}
+
+android_library_import {
+    name: "Aperture_androidx.media3_media3-datasource-nodeps",
+    aars: ["androidx/media3/media3-datasource/1.0.0-beta02/media3-datasource-1.0.0-beta02.aar"],
+    sdk_version: "33",
+    min_sdk_version: "14",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    static_libs: [
+        "Aperture_androidx.media3_media3-common",
+        "Aperture_androidx.media3_media3-database",
+        "androidx.annotation_annotation",
+    ],
+}
+
+android_library {
+    name: "Aperture_androidx.media3_media3-datasource",
+    sdk_version: "33",
+    min_sdk_version: "14",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    manifest: "androidx/media3/media3-datasource/1.0.0-beta02/AndroidManifest.xml",
+    static_libs: [
+        "Aperture_androidx.media3_media3-datasource-nodeps",
+        "Aperture_androidx.media3_media3-common",
+        "Aperture_androidx.media3_media3-database",
+        "androidx.annotation_annotation",
+    ],
+    java_version: "1.7",
+}
+
+android_library_import {
+    name: "Aperture_androidx.media3_media3-decoder-nodeps",
+    aars: ["androidx/media3/media3-decoder/1.0.0-beta02/media3-decoder-1.0.0-beta02.aar"],
+    sdk_version: "33",
+    min_sdk_version: "14",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    static_libs: [
+        "Aperture_androidx.media3_media3-common",
+        "androidx.annotation_annotation",
+    ],
+}
+
+android_library {
+    name: "Aperture_androidx.media3_media3-decoder",
+    sdk_version: "33",
+    min_sdk_version: "14",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    manifest: "androidx/media3/media3-decoder/1.0.0-beta02/AndroidManifest.xml",
+    static_libs: [
+        "Aperture_androidx.media3_media3-decoder-nodeps",
+        "Aperture_androidx.media3_media3-common",
+        "androidx.annotation_annotation",
+    ],
+    java_version: "1.7",
+}
+
+android_library_import {
+    name: "Aperture_androidx.media3_media3-exoplayer-nodeps",
+    aars: ["androidx/media3/media3-exoplayer/1.0.0-beta02/media3-exoplayer-1.0.0-beta02.aar"],
+    sdk_version: "33",
+    min_sdk_version: "14",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    static_libs: [
+        "Aperture_androidx.media3_media3-common",
+        "Aperture_androidx.media3_media3-datasource",
+        "Aperture_androidx.media3_media3-decoder",
+        "Aperture_androidx.media3_media3-extractor",
+        "Aperture_androidx.media3_media3-database",
+        "androidx.annotation_annotation",
+        "androidx.core_core",
+    ],
+}
+
+android_library {
+    name: "Aperture_androidx.media3_media3-exoplayer",
+    sdk_version: "33",
+    min_sdk_version: "14",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    manifest: "androidx/media3/media3-exoplayer/1.0.0-beta02/AndroidManifest.xml",
+    static_libs: [
+        "Aperture_androidx.media3_media3-exoplayer-nodeps",
+        "Aperture_androidx.media3_media3-common",
+        "Aperture_androidx.media3_media3-datasource",
+        "Aperture_androidx.media3_media3-decoder",
+        "Aperture_androidx.media3_media3-extractor",
+        "Aperture_androidx.media3_media3-database",
+        "androidx.annotation_annotation",
+        "androidx.core_core",
+    ],
+    java_version: "1.7",
+}
+
+android_library_import {
+    name: "Aperture_androidx.media3_media3-extractor-nodeps",
+    aars: ["androidx/media3/media3-extractor/1.0.0-beta02/media3-extractor-1.0.0-beta02.aar"],
+    sdk_version: "33",
+    min_sdk_version: "14",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    static_libs: [
+        "androidx.annotation_annotation",
+        "Aperture_androidx.media3_media3-common",
+        "Aperture_androidx.media3_media3-decoder",
+    ],
+}
+
+android_library {
+    name: "Aperture_androidx.media3_media3-extractor",
+    sdk_version: "33",
+    min_sdk_version: "14",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    manifest: "androidx/media3/media3-extractor/1.0.0-beta02/AndroidManifest.xml",
+    static_libs: [
+        "Aperture_androidx.media3_media3-extractor-nodeps",
+        "androidx.annotation_annotation",
+        "Aperture_androidx.media3_media3-common",
+        "Aperture_androidx.media3_media3-decoder",
+    ],
+    java_version: "1.7",
+}
+
+android_library_import {
+    name: "Aperture_androidx.media3_media3-ui-nodeps",
+    aars: ["androidx/media3/media3-ui/1.0.0-beta02/media3-ui-1.0.0-beta02.aar"],
+    sdk_version: "33",
+    min_sdk_version: "14",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    static_libs: [
+        "Aperture_androidx.media3_media3-common",
+        "androidx.media_media",
+        "androidx.annotation_annotation",
+        "androidx.recyclerview_recyclerview",
+    ],
+}
+
+android_library {
+    name: "Aperture_androidx.media3_media3-ui",
+    sdk_version: "33",
+    min_sdk_version: "14",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    manifest: "androidx/media3/media3-ui/1.0.0-beta02/AndroidManifest.xml",
+    static_libs: [
+        "Aperture_androidx.media3_media3-ui-nodeps",
+        "Aperture_androidx.media3_media3-common",
+        "androidx.media_media",
+        "androidx.annotation_annotation",
+        "androidx.recyclerview_recyclerview",
+    ],
+    java_version: "1.7",
+}
+
+android_library_import {
     name: "Aperture_com.google.android.material_material-nodeps",
     aars: ["com/google/android/material/material/1.8.0-alpha03/material-1.8.0-alpha03.aar"],
     sdk_version: "33",
diff --git a/app/libs/androidx/media3/media3-common/1.0.0-beta02/AndroidManifest.xml b/app/libs/androidx/media3/media3-common/1.0.0-beta02/AndroidManifest.xml
new file mode 100644
index 0000000..2431e06
--- /dev/null
+++ b/app/libs/androidx/media3/media3-common/1.0.0-beta02/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.media3.common" >
+
+    <uses-sdk
+        android:minSdkVersion="16"
+        android:targetSdkVersion="30" />
+
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+
+</manifest>
\ No newline at end of file
diff --git a/app/libs/androidx/media3/media3-common/1.0.0-beta02/media3-common-1.0.0-beta02.aar b/app/libs/androidx/media3/media3-common/1.0.0-beta02/media3-common-1.0.0-beta02.aar
new file mode 100644
index 0000000..2d512e8
--- /dev/null
+++ b/app/libs/androidx/media3/media3-common/1.0.0-beta02/media3-common-1.0.0-beta02.aar
Binary files differ
diff --git a/app/libs/androidx/media3/media3-database/1.0.0-beta02/AndroidManifest.xml b/app/libs/androidx/media3/media3-database/1.0.0-beta02/AndroidManifest.xml
new file mode 100644
index 0000000..173cd75
--- /dev/null
+++ b/app/libs/androidx/media3/media3-database/1.0.0-beta02/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.media3.database" >
+
+    <uses-sdk
+        android:minSdkVersion="16"
+        android:targetSdkVersion="30" />
+
+</manifest>
\ No newline at end of file
diff --git a/app/libs/androidx/media3/media3-database/1.0.0-beta02/media3-database-1.0.0-beta02.aar b/app/libs/androidx/media3/media3-database/1.0.0-beta02/media3-database-1.0.0-beta02.aar
new file mode 100644
index 0000000..d12726d
--- /dev/null
+++ b/app/libs/androidx/media3/media3-database/1.0.0-beta02/media3-database-1.0.0-beta02.aar
Binary files differ
diff --git a/app/libs/androidx/media3/media3-datasource/1.0.0-beta02/AndroidManifest.xml b/app/libs/androidx/media3/media3-datasource/1.0.0-beta02/AndroidManifest.xml
new file mode 100644
index 0000000..50987ba
--- /dev/null
+++ b/app/libs/androidx/media3/media3-datasource/1.0.0-beta02/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.media3.datasource" >
+
+    <uses-sdk
+        android:minSdkVersion="16"
+        android:targetSdkVersion="30" />
+
+</manifest>
\ No newline at end of file
diff --git a/app/libs/androidx/media3/media3-datasource/1.0.0-beta02/media3-datasource-1.0.0-beta02.aar b/app/libs/androidx/media3/media3-datasource/1.0.0-beta02/media3-datasource-1.0.0-beta02.aar
new file mode 100644
index 0000000..dfb59e9
--- /dev/null
+++ b/app/libs/androidx/media3/media3-datasource/1.0.0-beta02/media3-datasource-1.0.0-beta02.aar
Binary files differ
diff --git a/app/libs/androidx/media3/media3-decoder/1.0.0-beta02/AndroidManifest.xml b/app/libs/androidx/media3/media3-decoder/1.0.0-beta02/AndroidManifest.xml
new file mode 100644
index 0000000..fbc2b51
--- /dev/null
+++ b/app/libs/androidx/media3/media3-decoder/1.0.0-beta02/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.media3.decoder" >
+
+    <uses-sdk
+        android:minSdkVersion="16"
+        android:targetSdkVersion="30" />
+
+</manifest>
\ No newline at end of file
diff --git a/app/libs/androidx/media3/media3-decoder/1.0.0-beta02/media3-decoder-1.0.0-beta02.aar b/app/libs/androidx/media3/media3-decoder/1.0.0-beta02/media3-decoder-1.0.0-beta02.aar
new file mode 100644
index 0000000..d857bac
--- /dev/null
+++ b/app/libs/androidx/media3/media3-decoder/1.0.0-beta02/media3-decoder-1.0.0-beta02.aar
Binary files differ
diff --git a/app/libs/androidx/media3/media3-exoplayer/1.0.0-beta02/AndroidManifest.xml b/app/libs/androidx/media3/media3-exoplayer/1.0.0-beta02/AndroidManifest.xml
new file mode 100644
index 0000000..386d6d0
--- /dev/null
+++ b/app/libs/androidx/media3/media3-exoplayer/1.0.0-beta02/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.media3.exoplayer" >
+
+    <uses-sdk
+        android:minSdkVersion="16"
+        android:targetSdkVersion="30" />
+
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+
+</manifest>
\ No newline at end of file
diff --git a/app/libs/androidx/media3/media3-exoplayer/1.0.0-beta02/media3-exoplayer-1.0.0-beta02.aar b/app/libs/androidx/media3/media3-exoplayer/1.0.0-beta02/media3-exoplayer-1.0.0-beta02.aar
new file mode 100644
index 0000000..1516100
--- /dev/null
+++ b/app/libs/androidx/media3/media3-exoplayer/1.0.0-beta02/media3-exoplayer-1.0.0-beta02.aar
Binary files differ
diff --git a/app/libs/androidx/media3/media3-extractor/1.0.0-beta02/AndroidManifest.xml b/app/libs/androidx/media3/media3-extractor/1.0.0-beta02/AndroidManifest.xml
new file mode 100644
index 0000000..89b5eb7
--- /dev/null
+++ b/app/libs/androidx/media3/media3-extractor/1.0.0-beta02/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.media3.extractor" >
+
+    <uses-sdk
+        android:minSdkVersion="16"
+        android:targetSdkVersion="30" />
+
+</manifest>
\ No newline at end of file
diff --git a/app/libs/androidx/media3/media3-extractor/1.0.0-beta02/media3-extractor-1.0.0-beta02.aar b/app/libs/androidx/media3/media3-extractor/1.0.0-beta02/media3-extractor-1.0.0-beta02.aar
new file mode 100644
index 0000000..5a314b7
--- /dev/null
+++ b/app/libs/androidx/media3/media3-extractor/1.0.0-beta02/media3-extractor-1.0.0-beta02.aar
Binary files differ
diff --git a/app/libs/androidx/media3/media3-ui/1.0.0-beta02/AndroidManifest.xml b/app/libs/androidx/media3/media3-ui/1.0.0-beta02/AndroidManifest.xml
new file mode 100644
index 0000000..3c9d28a
--- /dev/null
+++ b/app/libs/androidx/media3/media3-ui/1.0.0-beta02/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.media3.ui" >
+
+    <uses-sdk
+        android:minSdkVersion="16"
+        android:targetSdkVersion="30" />
+
+</manifest>
\ No newline at end of file
diff --git a/app/libs/androidx/media3/media3-ui/1.0.0-beta02/media3-ui-1.0.0-beta02.aar b/app/libs/androidx/media3/media3-ui/1.0.0-beta02/media3-ui-1.0.0-beta02.aar
new file mode 100644
index 0000000..1719e9b
--- /dev/null
+++ b/app/libs/androidx/media3/media3-ui/1.0.0-beta02/media3-ui-1.0.0-beta02.aar
Binary files differ
diff --git a/app/src/main/java/org/lineageos/aperture/CameraActivity.kt b/app/src/main/java/org/lineageos/aperture/CameraActivity.kt
index 0217602..64bfe74 100644
--- a/app/src/main/java/org/lineageos/aperture/CameraActivity.kt
+++ b/app/src/main/java/org/lineageos/aperture/CameraActivity.kt
@@ -93,6 +93,7 @@
 @androidx.camera.camera2.interop.ExperimentalCamera2Interop
 @androidx.camera.core.ExperimentalZeroShutterLag
 @androidx.camera.view.video.ExperimentalVideo
+@androidx.media3.common.util.UnstableApi
 open class CameraActivity : AppCompatActivity() {
     // Views
     private val aspectRatioButton by lazy { findViewById<Button>(R.id.aspectRatioButton) }
diff --git a/app/src/main/java/org/lineageos/aperture/QrScannerActivity.kt b/app/src/main/java/org/lineageos/aperture/QrScannerActivity.kt
index fd03691..b86081d 100644
--- a/app/src/main/java/org/lineageos/aperture/QrScannerActivity.kt
+++ b/app/src/main/java/org/lineageos/aperture/QrScannerActivity.kt
@@ -10,6 +10,7 @@
 @androidx.camera.camera2.interop.ExperimentalCamera2Interop
 @androidx.camera.core.ExperimentalZeroShutterLag
 @androidx.camera.view.video.ExperimentalVideo
+@androidx.media3.common.util.UnstableApi
 class QrScannerActivity : CameraActivity() {
     override fun overrideInitialCameraMode() = CameraMode.QR
 }
diff --git a/app/src/main/java/org/lineageos/aperture/ui/CapturePreviewLayout.kt b/app/src/main/java/org/lineageos/aperture/ui/CapturePreviewLayout.kt
index 7951bbb..d65a57e 100644
--- a/app/src/main/java/org/lineageos/aperture/ui/CapturePreviewLayout.kt
+++ b/app/src/main/java/org/lineageos/aperture/ui/CapturePreviewLayout.kt
@@ -10,25 +10,30 @@
 import android.util.AttributeSet
 import android.widget.ImageButton
 import android.widget.ImageView
-import android.widget.VideoView
 import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.core.view.isVisible
+import androidx.media3.common.MediaItem
+import androidx.media3.exoplayer.ExoPlayer
+import androidx.media3.ui.PlayerView
 import org.lineageos.aperture.R
 import org.lineageos.aperture.utils.MediaType
 
 /**
  * Image/video preview fragment
  */
+@androidx.media3.common.util.UnstableApi
 class CapturePreviewLayout(context: Context, attrs: AttributeSet?) : ConstraintLayout(
     context, attrs
 ) {
     private lateinit var uri: Uri
     private lateinit var mediaType: MediaType
 
+    private var exoPlayer: ExoPlayer? = null
+
     private val cancelButton by lazy { findViewById<ImageButton>(R.id.cancelButton) }
     private val confirmButton by lazy { findViewById<ImageButton>(R.id.confirmButton) }
     private val imageView by lazy { findViewById<ImageView>(R.id.imageView) }
-    private val videoView by lazy { findViewById<VideoView>(R.id.videoView) }
+    private val videoView by lazy { findViewById<PlayerView>(R.id.videoView) }
 
     /**
      * URI is null == canceled
@@ -40,9 +45,11 @@
         super.onLayout(changed, left, top, right, bottom)
 
         cancelButton.setOnClickListener {
+            stopPreview()
             onChoiceCallback(null)
         }
         confirmButton.setOnClickListener {
+            stopPreview()
             onChoiceCallback(uri)
         }
     }
@@ -51,18 +58,39 @@
         this.uri = uri
         this.mediaType = mediaType
 
-        videoView.stopPlayback()
-
         imageView.isVisible = mediaType == MediaType.PHOTO
         videoView.isVisible = mediaType == MediaType.VIDEO
 
+        startPreview()
+    }
+
+    private fun startPreview() {
         when (mediaType) {
             MediaType.PHOTO -> {
                 imageView.setImageURI(uri)
             }
             MediaType.VIDEO -> {
-                videoView.setVideoURI(uri)
-                videoView.start()
+                exoPlayer = ExoPlayer.Builder(context)
+                    .build()
+                    .also {
+                        videoView.player = it
+
+                        it.setMediaItem(MediaItem.fromUri(uri))
+
+                        it.playWhenReady = true
+                        it.seekTo(0)
+                        it.prepare()
+                    }
+            }
+        }
+    }
+
+    private fun stopPreview() {
+        when (mediaType) {
+            MediaType.PHOTO -> {}
+            MediaType.VIDEO -> {
+                exoPlayer?.release()
+                exoPlayer = null
             }
         }
     }
diff --git a/app/src/main/res/layout/capture_preview_layout.xml b/app/src/main/res/layout/capture_preview_layout.xml
index 2dd8481..4fec212 100644
--- a/app/src/main/res/layout/capture_preview_layout.xml
+++ b/app/src/main/res/layout/capture_preview_layout.xml
@@ -62,7 +62,7 @@
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toTopOf="parent" />
 
-        <VideoView
+        <androidx.media3.ui.PlayerView
             android:id="@+id/videoView"
             android:layout_width="0dp"
             android:layout_height="0dp"