From 222faa96d063ba4a7f7e9fe8089228394bf1f97b Mon Sep 17 00:00:00 2001 From: ibaker Date: Fri, 10 Jun 2022 09:20:32 +0000 Subject: [PATCH 01/73] Ensure `DRAIN_ACTION_FLUSH_AND_UPDATE_DRM_SESSION` is always executed `codecDrainAction` is set to `DRAIN_ACTION_NONE` in 3 places in `MediaCodecRenderer`: * The constructor (so there's no prior state to worry about) * `updateDrmSessionV23()`: Where `mediaCrypto` is reconfigured based on `sourceDrmSession` and `codecDrmSession` is also updated to `sourceDrmSession`. * `resetCodecStateForFlush()`: Where (before this change) the action is unconditionally set back to `DRAIN_ACTION_NONE` and so any required updated implied by `DRAIN_ACTION_FLUSH_AND_UPDATE_DRM_SESSION` is not done. This change ensures that `flushOrReleaseCodec()` handles `DRAIN_ACTION_FLUSH_AND_UPDATE_DRM_SESSION` before calling . This probably also resolves Issue: google/ExoPlayer#10274 #minor-release PiperOrigin-RevId: 454114428 --- RELEASENOTES.md | 4 ++++ .../exoplayer/mediacodec/MediaCodecRenderer.java | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 7d9ab1c365..1868b4acf3 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -69,6 +69,10 @@ for audio passthrough when the format audio channel count is unset, which occurs with HLS chunkless preparation ([10204](https://github.com/google/ExoPlayer/issues/10204)). +* DRM + * Ensure the DRM session is always correctly updated when seeking + immediately after a format change + ([10274](https://github.com/google/ExoPlayer/issues/10274)). * Ad playback / IMA: * Decrease ad polling rate from every 100ms to every 200ms, to line up with Media Rating Council (MRC) recommendations. diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecRenderer.java index de0568de56..aac827d3a0 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecRenderer.java @@ -856,6 +856,19 @@ protected boolean flushOrReleaseCodec() { releaseCodec(); return true; } + if (codecDrainAction == DRAIN_ACTION_FLUSH_AND_UPDATE_DRM_SESSION) { + checkState(Util.SDK_INT >= 23); // Implied by DRAIN_ACTION_FLUSH_AND_UPDATE_DRM_SESSION + // Needed to keep lint happy (it doesn't understand the checkState call alone) + if (Util.SDK_INT >= 23) { + try { + updateDrmSessionV23(); + } catch (ExoPlaybackException e) { + Log.w(TAG, "Failed to update the DRM session, releasing the codec instead.", e); + releaseCodec(); + return true; + } + } + } flushCodec(); return false; } From d6a6b44715c15be8348b4a30664254e57d79036a Mon Sep 17 00:00:00 2001 From: hschlueter Date: Fri, 10 Jun 2022 11:03:38 +0000 Subject: [PATCH 02/73] Combine all native GL errors in a GlException instead of logging. The native GL errors are in an arbitrary order according to https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetError.xml This means any of them could contain the most useful message so it's better to use all for the GlException's message rather than picking the last message and logging all others. PiperOrigin-RevId: 454130460 --- .../androidx/media3/common/util/GlUtil.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/libraries/common/src/main/java/androidx/media3/common/util/GlUtil.java b/libraries/common/src/main/java/androidx/media3/common/util/GlUtil.java index 44f4e648fa..adbb780e7a 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/GlUtil.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/GlUtil.java @@ -302,18 +302,22 @@ public static void focusPlaceholderEglSurfaceBt2020Pq( } /** - * Logs all OpenGL errors that occurred since this method was last called and throws a {@link - * GlException} for the last error. + * Collects all OpenGL errors that occurred since this method was last called and throws a {@link + * GlException} with the combined error message. */ public static void checkGlError() throws GlException { - int lastError = GLES20.GL_NO_ERROR; + StringBuilder errorMessageBuilder = new StringBuilder(); + boolean foundError = false; int error; while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { - Log.e(TAG, "glError: " + gluErrorString(error)); - lastError = error; + if (foundError) { + errorMessageBuilder.append('\n'); + } + errorMessageBuilder.append("glError: ").append(gluErrorString(error)); + foundError = true; } - if (lastError != GLES20.GL_NO_ERROR) { - throw new GlException("glError: " + gluErrorString(lastError)); + if (foundError) { + throw new GlException(errorMessageBuilder.toString()); } } From b5f53e771095f2c3c521008cb2c6555f5905b163 Mon Sep 17 00:00:00 2001 From: olly Date: Fri, 10 Jun 2022 14:29:55 +0000 Subject: [PATCH 03/73] Fix permissions request for media provider content URIs We need to request the external storage permission to access these PiperOrigin-RevId: 454160546 --- .../androidx/media3/common/util/Util.java | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/libraries/common/src/main/java/androidx/media3/common/util/Util.java b/libraries/common/src/main/java/androidx/media3/common/util/Util.java index f80525bdf6..0ba8dcf428 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/Util.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/Util.java @@ -55,6 +55,7 @@ import android.os.Looper; import android.os.Parcel; import android.os.SystemClock; +import android.provider.MediaStore; import android.security.NetworkSecurityPolicy; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -219,8 +220,8 @@ public static boolean maybeRequestReadExternalStoragePermission(Activity activit return false; } for (Uri uri : uris) { - if (isLocalFileUri(uri)) { - return requestExternalStoragePermission(activity); + if (maybeRequestReadExternalStoragePermission(activity, uri)) { + return true; } } return false; @@ -245,18 +246,39 @@ public static boolean maybeRequestReadExternalStoragePermission( if (mediaItem.localConfiguration == null) { continue; } - if (isLocalFileUri(mediaItem.localConfiguration.uri)) { - return requestExternalStoragePermission(activity); + if (maybeRequestReadExternalStoragePermission(activity, mediaItem.localConfiguration.uri)) { + return true; } - for (int i = 0; i < mediaItem.localConfiguration.subtitleConfigurations.size(); i++) { - if (isLocalFileUri(mediaItem.localConfiguration.subtitleConfigurations.get(i).uri)) { - return requestExternalStoragePermission(activity); + List subtitleConfigs = + mediaItem.localConfiguration.subtitleConfigurations; + for (int i = 0; i < subtitleConfigs.size(); i++) { + if (maybeRequestReadExternalStoragePermission(activity, subtitleConfigs.get(i).uri)) { + return true; } } } return false; } + private static boolean maybeRequestReadExternalStoragePermission(Activity activity, Uri uri) { + return Util.SDK_INT >= 23 && (isLocalFileUri(uri) || isMediaStoreExternalContentUri(uri)) + ? requestExternalStoragePermission(activity) + : false; + } + + private static boolean isMediaStoreExternalContentUri(Uri uri) { + if (!"content".equals(uri.getScheme()) || !MediaStore.AUTHORITY.equals(uri.getAuthority())) { + return false; + } + List pathSegments = uri.getPathSegments(); + if (pathSegments.isEmpty()) { + return false; + } + String firstPathSegment = pathSegments.get(0); + return MediaStore.VOLUME_EXTERNAL.equals(firstPathSegment) + || MediaStore.VOLUME_EXTERNAL_PRIMARY.equals(firstPathSegment); + } + /** * Returns whether it may be possible to load the URIs of the given media items based on the * network security policy's cleartext traffic permissions. From 8c63ba6fdbfcf632538acbfb6737f227923e54bf Mon Sep 17 00:00:00 2001 From: ibaker Date: Fri, 10 Jun 2022 14:32:54 +0000 Subject: [PATCH 04/73] Remove ExoPlayerTest.PlayerStateGrabber It's no longer needed PiperOrigin-RevId: 454161070 --- .../media3/exoplayer/ExoPlayerTest.java | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java index 784f6c23df..c41f46941a 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java @@ -3900,13 +3900,19 @@ public void audioFocusDenied() throws Exception { ShadowAudioManager shadowAudioManager = shadowOf(context.getSystemService(AudioManager.class)); shadowAudioManager.setNextFocusRequestResponse(AudioManager.AUDIOFOCUS_REQUEST_FAILED); - PlayerStateGrabber playerStateGrabber = new PlayerStateGrabber(); + AtomicBoolean playWhenReady = new AtomicBoolean(); ActionSchedule actionSchedule = new ActionSchedule.Builder(TAG) .setAudioAttributes(AudioAttributes.DEFAULT, /* handleAudioFocus= */ true) .play() .waitForPlaybackState(Player.STATE_READY) - .executeRunnable(playerStateGrabber) + .executeRunnable( + new PlayerRunnable() { + @Override + public void run(ExoPlayer player) { + playWhenReady.set(player.getPlayWhenReady()); + } + }) .build(); AtomicBoolean seenPlaybackSuppression = new AtomicBoolean(); Player.Listener listener = @@ -3924,7 +3930,7 @@ public void onPlaybackSuppressionReasonChanged( .start() .blockUntilActionScheduleFinished(TIMEOUT_MS); - assertThat(playerStateGrabber.playWhenReady).isFalse(); + assertThat(playWhenReady.get()).isFalse(); assertThat(seenPlaybackSuppression.get()).isFalse(); } @@ -12224,19 +12230,6 @@ public void handleMessage(ExoPlayer player, int messageType, @Nullable Object me } } - private static final class PlayerStateGrabber extends PlayerRunnable { - - public boolean playWhenReady; - public @Player.State int playbackState; - @Nullable public Timeline timeline; - - @Override - public void run(ExoPlayer player) { - playWhenReady = player.getPlayWhenReady(); - playbackState = player.getPlaybackState(); - timeline = player.getCurrentTimeline(); - } - } /** * Provides a wrapper for a {@link Runnable} which does collect playback states and window counts. * Can be used with {@link ActionSchedule.Builder#executeRunnable(Runnable)} to verify that a From e8bcdf437ee3f8df9622615960f6b754536220bc Mon Sep 17 00:00:00 2001 From: tonihei Date: Mon, 13 Jun 2022 11:00:12 +0000 Subject: [PATCH 05/73] Use correct placeholder PlayerID value in test The default constructor is only allowed to be called on API < 32 and the test should use the defined UNSET constant to be API independent. #minor-release PiperOrigin-RevId: 454568893 --- .../java/androidx/media3/exoplayer/MediaPeriodQueueTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/MediaPeriodQueueTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/MediaPeriodQueueTest.java index 17ff2cfc19..155450ec7e 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/MediaPeriodQueueTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/MediaPeriodQueueTest.java @@ -1286,7 +1286,7 @@ private static Timeline createMultiPeriodServerSideInsertedTimeline( countDownLatch.countDown(); }, /* mediaTransferListener= */ null, - new PlayerId()); + PlayerId.UNSET); if (!countDownLatch.await(/* timeout= */ 2, SECONDS)) { fail(); } From 33caabbc4422a81efbc8e04bc9994ee870ea2d13 Mon Sep 17 00:00:00 2001 From: olly Date: Mon, 13 Jun 2022 11:37:38 +0000 Subject: [PATCH 06/73] Update compileSdkVersion to 33 PiperOrigin-RevId: 454573995 --- constants.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constants.gradle b/constants.gradle index 0d49ac63ab..3c379912f6 100644 --- a/constants.gradle +++ b/constants.gradle @@ -19,7 +19,7 @@ project.ext { // Upgrading this requires [Internal ref: b/193254928] to be fixed, or some // additional robolectric config. targetSdkVersion = 30 - compileSdkVersion = 32 + compileSdkVersion = 33 dexmakerVersion = '2.28.1' junitVersion = '4.13.2' // Use the same Guava version as the Android repo: From ab56f865ea076ac3cc9eb1ad5aff6000136caf80 Mon Sep 17 00:00:00 2001 From: olly Date: Mon, 13 Jun 2022 12:34:43 +0000 Subject: [PATCH 07/73] Suppress an ExtendsObjects violation to support enabling this as a compile-time error. More information: go/lsc-extends-object PiperOrigin-RevId: 454582570 --- .../common/src/main/java/androidx/media3/common/util/Util.java | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/common/src/main/java/androidx/media3/common/util/Util.java b/libraries/common/src/main/java/androidx/media3/common/util/Util.java index 0ba8dcf428..e79ba706e6 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/Util.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/Util.java @@ -2600,6 +2600,7 @@ public static long getNowUnixTimeMs(long elapsedRealtimeEpochOffsetMs) { * @param newFromIndex The new from index. */ @UnstableApi + @SuppressWarnings("ExtendsObject") // See go/lsc-extends-object public static void moveItems( List items, int fromIndex, int toIndex, int newFromIndex) { ArrayDeque removedItems = new ArrayDeque<>(); From 118d689a08b1097a346f543111ea65deead56459 Mon Sep 17 00:00:00 2001 From: christosts Date: Tue, 14 Jun 2022 16:45:16 +0000 Subject: [PATCH 08/73] Spatializer: Assume linear channel count for E-AC3 JOC streams #minor-release PiperOrigin-RevId: 454884692 --- .../exoplayer/trackselection/DefaultTrackSelector.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelector.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelector.java index fbd9f6e57d..e0020888e6 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelector.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelector.java @@ -3685,10 +3685,17 @@ public boolean isEnabled() { } public boolean canBeSpatialized(AudioAttributes audioAttributes, Format format) { + // For E-AC3 JOC, the format is object based. When the channel count is 16, this maps to 12 + // linear channels and the rest are used for objects. See + // https://github.com/google/ExoPlayer/pull/10322#discussion_r895265881 + int linearChannelCount = + MimeTypes.AUDIO_E_AC3_JOC.equals(format.sampleMimeType) && format.channelCount == 16 + ? 12 + : format.channelCount; AudioFormat.Builder builder = new AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) - .setChannelMask(Util.getAudioTrackChannelConfig(format.channelCount)); + .setChannelMask(Util.getAudioTrackChannelConfig(linearChannelCount)); if (format.sampleRate != Format.NO_VALUE) { builder.setSampleRate(format.sampleRate); } From 252ae4c7a34889b8622cc2750c238dc40be0277b Mon Sep 17 00:00:00 2001 From: bachinger Date: Tue, 14 Jun 2022 20:33:41 +0000 Subject: [PATCH 09/73] Suppress lint errors `RestrictedApis` in lib-session PiperOrigin-RevId: 454943102 --- .../androidx/media3/session/MediaLibraryServiceLegacyStub.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaLibraryServiceLegacyStub.java b/libraries/session/src/main/java/androidx/media3/session/MediaLibraryServiceLegacyStub.java index f3d415d4a4..ad5912b796 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaLibraryServiceLegacyStub.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaLibraryServiceLegacyStub.java @@ -24,6 +24,7 @@ import static androidx.media3.session.LibraryResult.RESULT_SUCCESS; import static androidx.media3.session.MediaUtils.TRANSACTION_SIZE_LIMIT_IN_BYTES; +import android.annotation.SuppressLint; import android.os.BadParcelableException; import android.os.Bundle; import android.os.RemoteException; @@ -116,6 +117,7 @@ public BrowserRoot onGetRoot( // TODO(b/192455639): Optimize potential multiple calls of // MediaBrowserCompat.SubscriptionCallback#onChildrenLoaded() with the same // content. + @SuppressLint("RestrictedApi") @Override public void onSubscribe(String id, Bundle option) { @Nullable ControllerInfo controller = getCurrentController(); @@ -141,6 +143,7 @@ public void onSubscribe(String id, Bundle option) { }); } + @SuppressLint("RestrictedApi") @Override public void onUnsubscribe(String id) { @Nullable ControllerInfo controller = getCurrentController(); From 7f89531c5b0c894946c2ca4bf54cfc66e3d4507b Mon Sep 17 00:00:00 2001 From: bachinger Date: Tue, 14 Jun 2022 20:43:26 +0000 Subject: [PATCH 10/73] Make HttpDataSourceTestEnv require API 19 PiperOrigin-RevId: 454945333 --- .../java/androidx/media3/test/utils/HttpDataSourceTestEnv.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/test_utils/src/main/java/androidx/media3/test/utils/HttpDataSourceTestEnv.java b/libraries/test_utils/src/main/java/androidx/media3/test/utils/HttpDataSourceTestEnv.java index dad7531277..48ae08e1f3 100644 --- a/libraries/test_utils/src/main/java/androidx/media3/test/utils/HttpDataSourceTestEnv.java +++ b/libraries/test_utils/src/main/java/androidx/media3/test/utils/HttpDataSourceTestEnv.java @@ -19,6 +19,7 @@ import static androidx.media3.test.utils.WebServerDispatcher.getRequestPath; import android.net.Uri; +import androidx.annotation.RequiresApi; import androidx.media3.common.util.UnstableApi; import androidx.media3.datasource.HttpDataSource; import com.google.common.collect.ImmutableList; @@ -31,6 +32,7 @@ import org.junit.rules.ExternalResource; /** A JUnit {@link Rule} that creates test resources for {@link HttpDataSource} contract tests. */ +@RequiresApi(19) @UnstableApi public class HttpDataSourceTestEnv extends ExternalResource { private static int seed = 0; From 1f380c1dd36b4554286d0f4e93bc0479579eb991 Mon Sep 17 00:00:00 2001 From: bachinger Date: Tue, 14 Jun 2022 20:59:55 +0000 Subject: [PATCH 11/73] Add `many` quantity for fr an fr-CA See https://issuetracker.google.com/208178382 PiperOrigin-RevId: 454949204 --- libraries/ui/src/main/res/values-fr-rCA/strings.xml | 2 ++ libraries/ui/src/main/res/values-fr/strings.xml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libraries/ui/src/main/res/values-fr-rCA/strings.xml b/libraries/ui/src/main/res/values-fr-rCA/strings.xml index f30d732a13..fbcc917ee7 100644 --- a/libraries/ui/src/main/res/values-fr-rCA/strings.xml +++ b/libraries/ui/src/main/res/values-fr-rCA/strings.xml @@ -31,11 +31,13 @@ Reculer de %d seconde Reculer de %d secondes + Reculer de %d secondes Avance rapide Avancer rapidement de %d seconde Avancer rapidement de %d secondes + Avancer rapidement de %d secondes Ne rien lire en boucle Lire une chanson en boucle diff --git a/libraries/ui/src/main/res/values-fr/strings.xml b/libraries/ui/src/main/res/values-fr/strings.xml index 6aaf078c29..5c50bbd517 100644 --- a/libraries/ui/src/main/res/values-fr/strings.xml +++ b/libraries/ui/src/main/res/values-fr/strings.xml @@ -31,11 +31,13 @@ Revenir en arrière de %d seconde Revenir en arrière de %d secondes + Revenir en arrière de %d secondes Avance rapide Avancer de %d seconde Avancer de %d secondes + Avancer de %d secondes Ne rien lire en boucle Lire un titre en boucle From 29bf4c8aabd9003e907d31563b9eead4658c1fce Mon Sep 17 00:00:00 2001 From: bachinger Date: Tue, 14 Jun 2022 21:10:10 +0000 Subject: [PATCH 12/73] Add lint base to make gradle lint run without errors PiperOrigin-RevId: 454951844 --- libraries/common/build.gradle | 3 +++ libraries/common/lint-baseline.xml | 29 ++++++++++++++++++++++++++++ libraries/session/build.gradle | 3 +++ libraries/session/lint-baseline.xml | 30 +++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 libraries/common/lint-baseline.xml create mode 100644 libraries/session/lint-baseline.xml diff --git a/libraries/common/build.gradle b/libraries/common/build.gradle index d0123731b0..048fe60f41 100644 --- a/libraries/common/build.gradle +++ b/libraries/common/build.gradle @@ -30,6 +30,9 @@ android { testCoverageEnabled = true } } + lint { + baseline = file("lint-baseline.xml") + } } dependencies { diff --git a/libraries/common/lint-baseline.xml b/libraries/common/lint-baseline.xml new file mode 100644 index 0000000000..efedf9f2ec --- /dev/null +++ b/libraries/common/lint-baseline.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/libraries/session/build.gradle b/libraries/session/build.gradle index 7627d7d6a2..114a98bed6 100644 --- a/libraries/session/build.gradle +++ b/libraries/session/build.gradle @@ -26,6 +26,9 @@ android { } } sourceSets.androidTest.assets.srcDir '../test_data/src/test/assets/' + lint { + baseline = file("lint-baseline.xml") + } } dependencies { api project(modulePrefix + 'lib-common') diff --git a/libraries/session/lint-baseline.xml b/libraries/session/lint-baseline.xml new file mode 100644 index 0000000000..6dec23241b --- /dev/null +++ b/libraries/session/lint-baseline.xml @@ -0,0 +1,30 @@ + + + + + + + + + + From 84c43f855fd60f96b5f415dc316c1333cfdec704 Mon Sep 17 00:00:00 2001 From: hmzh Date: Wed, 15 Jun 2022 12:42:05 +0000 Subject: [PATCH 13/73] Implement seeking to the start of a MIDI file - Fixed MidiExtractor state issues which caused seeking to behave unexpectedly. Ensures the extractor is now always in the file loading state after returning RESULT_END_OF_INPUT. - Fixed an infinite loop in MidiExtractor caused by the file data array having an initial size of 0. The extractor attempted to increase the capacity of the array by using this size of 0 in it's calculations. PiperOrigin-RevId: 455107511 --- .../extractordumps/midi/Twinkle.mid.0.dump | 355 ++++++++++++++++++ .../midi/Twinkle.mid.unknown_length.dump | 355 ++++++++++++++++++ .../src/test/assets/media/midi/Twinkle.mid | Bin 0 -> 162 bytes 3 files changed, 710 insertions(+) create mode 100644 libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.0.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.unknown_length.dump create mode 100644 libraries/test_data/src/test/assets/media/midi/Twinkle.mid diff --git a/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.0.dump b/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.0.dump new file mode 100644 index 0000000000..9bbb94438c --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.0.dump @@ -0,0 +1,355 @@ +seekMap: + isSeekable = false + duration = UNSET TIME + getPosition(0) = [[timeUs=0, position=0]] +numberOfTracks = 1 +track 0: + total output bytes = 264 + sample count = 86 + format 0: + sampleMimeType = audio/midi + sample 0: + time = 0 + flags = 1 + data = length 7, hash C95FA520 + sample 1: + time = 0 + flags = 1 + data = length 5, hash 1CF3DA7 + sample 2: + time = 0 + flags = 1 + data = length 3, hash FFFED75B + sample 3: + time = 2108 + flags = 1 + data = length 3, hash FFFED448 + sample 4: + time = 2148 + flags = 1 + data = length 3, hash FFFE9730 + sample 5: + time = 2276 + flags = 1 + data = length 3, hash FFFED733 + sample 6: + time = 4384 + flags = 1 + data = length 3, hash FFFECFEF + sample 7: + time = 4384 + flags = 1 + data = length 3, hash FFFECF7F + sample 8: + time = 4384 + flags = 1 + data = length 3, hash FFFED751 + sample 9: + time = 6492 + flags = 1 + data = length 3, hash FFFED312 + sample 10: + time = 6522 + flags = 1 + data = length 3, hash FFFE9730 + sample 11: + time = 6650 + flags = 1 + data = length 3, hash FFFED733 + sample 12: + time = 8758 + flags = 1 + data = length 3, hash FFFECFEF + sample 13: + time = 8758 + flags = 1 + data = length 3, hash FFFECF7F + sample 14: + time = 8758 + flags = 1 + data = length 3, hash FFFED839 + sample 15: + time = 10873 + flags = 1 + data = length 3, hash FFFED4E3 + sample 16: + time = 10918 + flags = 1 + data = length 3, hash FFFE9730 + sample 17: + time = 11046 + flags = 1 + data = length 3, hash FFFED80C + sample 18: + time = 13161 + flags = 1 + data = length 3, hash FFFECFEF + sample 19: + time = 13161 + flags = 1 + data = length 3, hash FFFECF7F + sample 20: + time = 13161 + flags = 1 + data = length 3, hash FFFED83E + sample 21: + time = 15276 + flags = 1 + data = length 3, hash FFFED57E + sample 22: + time = 15326 + flags = 1 + data = length 3, hash FFFE9730 + sample 23: + time = 15454 + flags = 1 + data = length 3, hash FFFED80C + sample 24: + time = 17569 + flags = 1 + data = length 3, hash FFFECFEF + sample 25: + time = 17569 + flags = 1 + data = length 3, hash FFFECF7F + sample 26: + time = 17569 + flags = 1 + data = length 3, hash FFFED877 + sample 27: + time = 19686 + flags = 1 + data = length 3, hash FFFED4E3 + sample 28: + time = 19731 + flags = 1 + data = length 3, hash FFFE9730 + sample 29: + time = 19859 + flags = 1 + data = length 3, hash FFFED84A + sample 30: + time = 21976 + flags = 1 + data = length 3, hash FFFECFEF + sample 31: + time = 21976 + flags = 1 + data = length 3, hash FFFECF7F + sample 32: + time = 21976 + flags = 1 + data = length 3, hash FFFED87C + sample 33: + time = 24093 + flags = 1 + data = length 3, hash FFFED57E + sample 34: + time = 24143 + flags = 1 + data = length 3, hash FFFE9730 + sample 35: + time = 24271 + flags = 1 + data = length 3, hash FFFED84A + sample 36: + time = 26388 + flags = 1 + data = length 3, hash FFFECFEF + sample 37: + time = 26388 + flags = 1 + data = length 3, hash FFFECF7F + sample 38: + time = 26388 + flags = 1 + data = length 3, hash FFFED82F + sample 39: + time = 28503 + flags = 1 + data = length 3, hash FFFED3AE + sample 40: + time = 28538 + flags = 1 + data = length 3, hash FFFE9AF1 + sample 41: + time = 28794 + flags = 1 + data = length 3, hash FFFED80C + sample 42: + time = 30909 + flags = 1 + data = length 3, hash FFFECFEF + sample 43: + time = 30909 + flags = 1 + data = length 3, hash FFFECF7F + sample 44: + time = 30909 + flags = 1 + data = length 3, hash FFFED800 + sample 45: + time = 33022 + flags = 1 + data = length 3, hash FFFED57E + sample 46: + time = 33072 + flags = 1 + data = length 3, hash FFFE9730 + sample 47: + time = 33200 + flags = 1 + data = length 3, hash FFFED7CE + sample 48: + time = 35313 + flags = 1 + data = length 3, hash FFFECFEF + sample 49: + time = 35313 + flags = 1 + data = length 3, hash FFFECF7F + sample 50: + time = 35313 + flags = 1 + data = length 3, hash FFFED7FB + sample 51: + time = 37426 + flags = 1 + data = length 3, hash FFFED4E3 + sample 52: + time = 37471 + flags = 1 + data = length 3, hash FFFE9730 + sample 53: + time = 37599 + flags = 1 + data = length 3, hash FFFED7CE + sample 54: + time = 39712 + flags = 1 + data = length 3, hash FFFECFEF + sample 55: + time = 39712 + flags = 1 + data = length 3, hash FFFECF7F + sample 56: + time = 39712 + flags = 1 + data = length 3, hash FFFED7E1 + sample 57: + time = 41824 + flags = 1 + data = length 3, hash FFFED63D + sample 58: + time = 41874 + flags = 1 + data = length 3, hash FFFED73F + sample 59: + time = 41938 + flags = 1 + data = length 3, hash FFFED7AF + sample 60: + time = 44050 + flags = 1 + data = length 3, hash FFFED02F + sample 61: + time = 44050 + flags = 1 + data = length 3, hash FFFED73F + sample 62: + time = 44114 + flags = 1 + data = length 3, hash FFFED7D7 + sample 63: + time = 46226 + flags = 1 + data = length 3, hash FFFED507 + sample 64: + time = 46266 + flags = 1 + data = length 3, hash FFFED73F + sample 65: + time = 46330 + flags = 1 + data = length 3, hash FFFED7AF + sample 66: + time = 48442 + flags = 1 + data = length 3, hash FFFED02F + sample 67: + time = 48442 + flags = 1 + data = length 3, hash FFFED73F + sample 68: + time = 48506 + flags = 1 + data = length 3, hash FFFED79E + sample 69: + time = 50616 + flags = 1 + data = length 3, hash FFFED5A2 + sample 70: + time = 50661 + flags = 1 + data = length 3, hash FFFED73F + sample 71: + time = 50725 + flags = 1 + data = length 3, hash FFFED771 + sample 72: + time = 52835 + flags = 1 + data = length 3, hash FFFED02F + sample 73: + time = 52835 + flags = 1 + data = length 3, hash FFFED73F + sample 74: + time = 52899 + flags = 1 + data = length 3, hash FFFED7A3 + sample 75: + time = 55009 + flags = 1 + data = length 3, hash FFFED63D + sample 76: + time = 55059 + flags = 1 + data = length 3, hash FFFED73F + sample 77: + time = 55123 + flags = 1 + data = length 3, hash FFFED771 + sample 78: + time = 57233 + flags = 1 + data = length 3, hash FFFED02F + sample 79: + time = 57233 + flags = 1 + data = length 3, hash FFFED73F + sample 80: + time = 57297 + flags = 1 + data = length 3, hash FFFED751 + sample 81: + time = 59405 + flags = 1 + data = length 3, hash FFFED313 + sample 82: + time = 59435 + flags = 1 + data = length 3, hash FFFE9AF1 + sample 83: + time = 59691 + flags = 1 + data = length 3, hash FFFED733 + sample 84: + time = 61799 + flags = 1 + data = length 3, hash FFFECFEF + sample 85: + time = 61799 + flags = 1 + data = length 3, hash FFFECFEE +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.unknown_length.dump new file mode 100644 index 0000000000..9bbb94438c --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.unknown_length.dump @@ -0,0 +1,355 @@ +seekMap: + isSeekable = false + duration = UNSET TIME + getPosition(0) = [[timeUs=0, position=0]] +numberOfTracks = 1 +track 0: + total output bytes = 264 + sample count = 86 + format 0: + sampleMimeType = audio/midi + sample 0: + time = 0 + flags = 1 + data = length 7, hash C95FA520 + sample 1: + time = 0 + flags = 1 + data = length 5, hash 1CF3DA7 + sample 2: + time = 0 + flags = 1 + data = length 3, hash FFFED75B + sample 3: + time = 2108 + flags = 1 + data = length 3, hash FFFED448 + sample 4: + time = 2148 + flags = 1 + data = length 3, hash FFFE9730 + sample 5: + time = 2276 + flags = 1 + data = length 3, hash FFFED733 + sample 6: + time = 4384 + flags = 1 + data = length 3, hash FFFECFEF + sample 7: + time = 4384 + flags = 1 + data = length 3, hash FFFECF7F + sample 8: + time = 4384 + flags = 1 + data = length 3, hash FFFED751 + sample 9: + time = 6492 + flags = 1 + data = length 3, hash FFFED312 + sample 10: + time = 6522 + flags = 1 + data = length 3, hash FFFE9730 + sample 11: + time = 6650 + flags = 1 + data = length 3, hash FFFED733 + sample 12: + time = 8758 + flags = 1 + data = length 3, hash FFFECFEF + sample 13: + time = 8758 + flags = 1 + data = length 3, hash FFFECF7F + sample 14: + time = 8758 + flags = 1 + data = length 3, hash FFFED839 + sample 15: + time = 10873 + flags = 1 + data = length 3, hash FFFED4E3 + sample 16: + time = 10918 + flags = 1 + data = length 3, hash FFFE9730 + sample 17: + time = 11046 + flags = 1 + data = length 3, hash FFFED80C + sample 18: + time = 13161 + flags = 1 + data = length 3, hash FFFECFEF + sample 19: + time = 13161 + flags = 1 + data = length 3, hash FFFECF7F + sample 20: + time = 13161 + flags = 1 + data = length 3, hash FFFED83E + sample 21: + time = 15276 + flags = 1 + data = length 3, hash FFFED57E + sample 22: + time = 15326 + flags = 1 + data = length 3, hash FFFE9730 + sample 23: + time = 15454 + flags = 1 + data = length 3, hash FFFED80C + sample 24: + time = 17569 + flags = 1 + data = length 3, hash FFFECFEF + sample 25: + time = 17569 + flags = 1 + data = length 3, hash FFFECF7F + sample 26: + time = 17569 + flags = 1 + data = length 3, hash FFFED877 + sample 27: + time = 19686 + flags = 1 + data = length 3, hash FFFED4E3 + sample 28: + time = 19731 + flags = 1 + data = length 3, hash FFFE9730 + sample 29: + time = 19859 + flags = 1 + data = length 3, hash FFFED84A + sample 30: + time = 21976 + flags = 1 + data = length 3, hash FFFECFEF + sample 31: + time = 21976 + flags = 1 + data = length 3, hash FFFECF7F + sample 32: + time = 21976 + flags = 1 + data = length 3, hash FFFED87C + sample 33: + time = 24093 + flags = 1 + data = length 3, hash FFFED57E + sample 34: + time = 24143 + flags = 1 + data = length 3, hash FFFE9730 + sample 35: + time = 24271 + flags = 1 + data = length 3, hash FFFED84A + sample 36: + time = 26388 + flags = 1 + data = length 3, hash FFFECFEF + sample 37: + time = 26388 + flags = 1 + data = length 3, hash FFFECF7F + sample 38: + time = 26388 + flags = 1 + data = length 3, hash FFFED82F + sample 39: + time = 28503 + flags = 1 + data = length 3, hash FFFED3AE + sample 40: + time = 28538 + flags = 1 + data = length 3, hash FFFE9AF1 + sample 41: + time = 28794 + flags = 1 + data = length 3, hash FFFED80C + sample 42: + time = 30909 + flags = 1 + data = length 3, hash FFFECFEF + sample 43: + time = 30909 + flags = 1 + data = length 3, hash FFFECF7F + sample 44: + time = 30909 + flags = 1 + data = length 3, hash FFFED800 + sample 45: + time = 33022 + flags = 1 + data = length 3, hash FFFED57E + sample 46: + time = 33072 + flags = 1 + data = length 3, hash FFFE9730 + sample 47: + time = 33200 + flags = 1 + data = length 3, hash FFFED7CE + sample 48: + time = 35313 + flags = 1 + data = length 3, hash FFFECFEF + sample 49: + time = 35313 + flags = 1 + data = length 3, hash FFFECF7F + sample 50: + time = 35313 + flags = 1 + data = length 3, hash FFFED7FB + sample 51: + time = 37426 + flags = 1 + data = length 3, hash FFFED4E3 + sample 52: + time = 37471 + flags = 1 + data = length 3, hash FFFE9730 + sample 53: + time = 37599 + flags = 1 + data = length 3, hash FFFED7CE + sample 54: + time = 39712 + flags = 1 + data = length 3, hash FFFECFEF + sample 55: + time = 39712 + flags = 1 + data = length 3, hash FFFECF7F + sample 56: + time = 39712 + flags = 1 + data = length 3, hash FFFED7E1 + sample 57: + time = 41824 + flags = 1 + data = length 3, hash FFFED63D + sample 58: + time = 41874 + flags = 1 + data = length 3, hash FFFED73F + sample 59: + time = 41938 + flags = 1 + data = length 3, hash FFFED7AF + sample 60: + time = 44050 + flags = 1 + data = length 3, hash FFFED02F + sample 61: + time = 44050 + flags = 1 + data = length 3, hash FFFED73F + sample 62: + time = 44114 + flags = 1 + data = length 3, hash FFFED7D7 + sample 63: + time = 46226 + flags = 1 + data = length 3, hash FFFED507 + sample 64: + time = 46266 + flags = 1 + data = length 3, hash FFFED73F + sample 65: + time = 46330 + flags = 1 + data = length 3, hash FFFED7AF + sample 66: + time = 48442 + flags = 1 + data = length 3, hash FFFED02F + sample 67: + time = 48442 + flags = 1 + data = length 3, hash FFFED73F + sample 68: + time = 48506 + flags = 1 + data = length 3, hash FFFED79E + sample 69: + time = 50616 + flags = 1 + data = length 3, hash FFFED5A2 + sample 70: + time = 50661 + flags = 1 + data = length 3, hash FFFED73F + sample 71: + time = 50725 + flags = 1 + data = length 3, hash FFFED771 + sample 72: + time = 52835 + flags = 1 + data = length 3, hash FFFED02F + sample 73: + time = 52835 + flags = 1 + data = length 3, hash FFFED73F + sample 74: + time = 52899 + flags = 1 + data = length 3, hash FFFED7A3 + sample 75: + time = 55009 + flags = 1 + data = length 3, hash FFFED63D + sample 76: + time = 55059 + flags = 1 + data = length 3, hash FFFED73F + sample 77: + time = 55123 + flags = 1 + data = length 3, hash FFFED771 + sample 78: + time = 57233 + flags = 1 + data = length 3, hash FFFED02F + sample 79: + time = 57233 + flags = 1 + data = length 3, hash FFFED73F + sample 80: + time = 57297 + flags = 1 + data = length 3, hash FFFED751 + sample 81: + time = 59405 + flags = 1 + data = length 3, hash FFFED313 + sample 82: + time = 59435 + flags = 1 + data = length 3, hash FFFE9AF1 + sample 83: + time = 59691 + flags = 1 + data = length 3, hash FFFED733 + sample 84: + time = 61799 + flags = 1 + data = length 3, hash FFFECFEF + sample 85: + time = 61799 + flags = 1 + data = length 3, hash FFFECFEE +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/media/midi/Twinkle.mid b/libraries/test_data/src/test/assets/media/midi/Twinkle.mid new file mode 100644 index 0000000000000000000000000000000000000000..8c25f4fbaecf0357b2ceac07e82178d35a11684f GIT binary patch literal 162 zcmeYb$w*;fU|<7cMurC8kfLlLtB2u#1Pcq30SCkXNG2eEf{jKakN`2{pbTeSAj26b z;%o$ExPnAnfg-LT5fH;!xe21i5hUUW6mbNp0Wlnm940t00I>#yw$pW(U Date: Wed, 15 Jun 2022 13:01:33 +0000 Subject: [PATCH 14/73] Support setMediaItem(s) in MediaControllerImplLegacy These calls were not implemented so far as they require a mix of initial prepareFrom/playFrom calls and addQueueItem. We can also support clients without queue handling to set single MediaItems. To make the calls consistent and predictable in the session, we need to ensure that none of the play/pause/addQueueItem/ removeQueueItem/prepare/playFromXYZ/prepareFromXYZ are called before the controller is prepared and has media. #minor-release PiperOrigin-RevId: 455110246 --- RELEASENOTES.md | 2 + .../media3/session/MediaController.java | 92 ++--- .../session/MediaControllerImplLegacy.java | 323 ++++++++++-------- .../androidx/media3/session/MediaSession.java | 10 +- .../androidx/media3/session/MediaUtils.java | 4 +- .../media3/session/QueueTimeline.java | 6 +- ...aControllerWithMediaSessionCompatTest.java | 76 ----- ...CompatCallbackWithMediaControllerTest.java | 296 ++-------------- 8 files changed, 252 insertions(+), 557 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ddf2d0fc4e..4f154ce7f1 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -179,6 +179,8 @@ of requests. * Forward legacy `MediaController` calls to play media to `MediaSession.Callback.onAddMediaItems` instead of `onSetMediaUri`. + * Support `setMediaItems(s)` methods when `MediaController` connects to a + legacy media session. * Data sources: * Rename `DummyDataSource` to `PlaceholderDataSource`. * Workaround OkHttp interrupt handling. diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaController.java b/libraries/session/src/main/java/androidx/media3/session/MediaController.java index 348750b813..624a0faa7a 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaController.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaController.java @@ -81,13 +81,14 @@ *
  • Controller Lifecycle *
  • Threading Model *
  • Package Visibility Filter + *
  • Backward Compatibility with legacy media sessions * * *

    Controller Lifecycle

    * *

    When a controller is created with the {@link SessionToken} for a {@link MediaSession} (i.e. * session token type is {@link SessionToken#TYPE_SESSION}), the controller will connect to the - * specific session. + * specific session.F * *

    When a controller is created with the {@link SessionToken} for a {@link MediaSessionService} * (i.e. session token type is {@link SessionToken#TYPE_SESSION_SERVICE} or {@link @@ -127,6 +128,34 @@ * * * } + * + *

    Backward Compatibility with legacy media sessions

    + * + *

    In addition to {@link MediaSession}, the controller also supports connecting to a legacy media + * session - {@linkplain android.media.session.MediaSession framework session} and {@linkplain + * MediaSessionCompat AndroidX session compat}. + * + *

    To request legacy sessions to play media, use one of the {@link #setMediaItem} methods and set + * either {@link MediaItem#mediaId}, {@link MediaItem.RequestMetadata#mediaUri} or {@link + * MediaItem.RequestMetadata#searchQuery}. Once the controller is {@linkplain #prepare() prepared}, + * the controller triggers one of the following callbacks depending on the provided information and + * the value of {@link #getPlayWhenReady()}: + * + *

      + *
    • {@link MediaSessionCompat.Callback#onPrepareFromUri onPrepareFromUri} + *
    • {@link MediaSessionCompat.Callback#onPlayFromUri onPlayFromUri} + *
    • {@link MediaSessionCompat.Callback#onPrepareFromMediaId onPrepareFromMediaId} + *
    • {@link MediaSessionCompat.Callback#onPlayFromMediaId onPlayFromMediaId} + *
    • {@link MediaSessionCompat.Callback#onPrepareFromSearch onPrepareFromSearch} + *
    • {@link MediaSessionCompat.Callback#onPlayFromSearch onPlayFromSearch} + *
    + * + * Other playlist change methods, like {@link #addMediaItem} or {@link #removeMediaItem}, trigger + * the {@link MediaSessionCompat.Callback#onAddQueueItem onAddQueueItem} and {@link + * MediaSessionCompat.Callback#onRemoveQueueItem} onRemoveQueueItem} callbacks. Check {@link + * #getAvailableCommands()} to see if playlist modifications are {@linkplain + * androidx.media3.common.Player.Command#COMMAND_CHANGE_MEDIA_ITEMS supported} by the legacy + * session. */ public class MediaController implements Player { @@ -478,13 +507,6 @@ public boolean isConnected() { return impl.isConnected(); } - /** - * {@inheritDoc} - * - *

    Interoperability: When connected to {@link - * android.support.v4.media.session.MediaSessionCompat}, then this will be grouped together with - * previously called {@link #setMediaUri}. See {@link #setMediaUri} for details. - */ @Override public void play() { verifyApplicationThread(); @@ -505,13 +527,6 @@ public void pause() { impl.pause(); } - /** - * {@inheritDoc} - * - *

    Interoperability: When connected to {@link - * android.support.v4.media.session.MediaSessionCompat}, then this will be grouped together with - * previously called {@link #setMediaUri}. See {@link #setMediaUri} for details. - */ @Override public void prepare() { verifyApplicationThread(); @@ -980,44 +995,6 @@ public void setMediaItems(List mediaItems, int startIndex, long start *

    The {@link Player.Listener#onTimelineChanged} and/or {@link * Player.Listener#onMediaItemTransition} would be called when it's completed. * - *

    Interoperability: When connected to {@link - * android.support.v4.media.session.MediaSessionCompat}, this call will be grouped together with - * later {@link #prepare} or {@link #play}, depending on the uri pattern as follows: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Uri patterns and following API calls for MediaControllerCompat methods
    Uri patternsFollowing API callsMethod
    {@code androidx://media3-session/setMediaUri?uri=[uri]}{@link #prepare}{@link MediaControllerCompat.TransportControls#prepareFromUri prepareFromUri} - *
    {@link #play}{@link MediaControllerCompat.TransportControls#playFromUri playFromUri} - *
    {@code androidx://media3-session/setMediaUri?id=[mediaId]}{@link #prepare}{@link MediaControllerCompat.TransportControls#prepareFromMediaId prepareFromMediaId} - *
    {@link #play}{@link MediaControllerCompat.TransportControls#playFromMediaId playFromMediaId} - *
    {@code androidx://media3-session/setMediaUri?query=[query]}{@link #prepare}{@link MediaControllerCompat.TransportControls#prepareFromSearch prepareFromSearch} - *
    {@link #play}{@link MediaControllerCompat.TransportControls#playFromSearch playFromSearch} - *
    Does not match with any pattern above{@link #prepare}{@link MediaControllerCompat.TransportControls#prepareFromUri prepareFromUri} - *
    {@link #play}{@link MediaControllerCompat.TransportControls#playFromUri playFromUri} - *
    - * *

    Returned {@link ListenableFuture} will return {@link SessionResult#RESULT_SUCCESS} when it's * handled together with {@link #prepare} or {@link #play}. If this API is called multiple times * without prepare or play, then {@link SessionResult#RESULT_INFO_SKIPPED} will be returned for @@ -1027,15 +1004,6 @@ public void setMediaItems(List mediaItems, int startIndex, long start * @param extras A {@link Bundle} to send extra information. May be empty. * @return A {@link ListenableFuture} of {@link SessionResult} representing the pending * completion. - * @see MediaConstants#MEDIA_URI_AUTHORITY - * @see MediaConstants#MEDIA_URI_PATH_PREPARE_FROM_MEDIA_ID - * @see MediaConstants#MEDIA_URI_PATH_PLAY_FROM_MEDIA_ID - * @see MediaConstants#MEDIA_URI_PATH_PREPARE_FROM_SEARCH - * @see MediaConstants#MEDIA_URI_PATH_PLAY_FROM_SEARCH - * @see MediaConstants#MEDIA_URI_PATH_SET_MEDIA_URI - * @see MediaConstants#MEDIA_URI_QUERY_ID - * @see MediaConstants#MEDIA_URI_QUERY_QUERY - * @see MediaConstants#MEDIA_URI_QUERY_URI */ public ListenableFuture setMediaUri(Uri uri, Bundle extras) { verifyApplicationThread(); diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java index 3855969830..05fb4335cf 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java @@ -31,16 +31,12 @@ import static androidx.media3.common.Player.STATE_IDLE; import static androidx.media3.common.Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED; import static androidx.media3.common.util.Assertions.checkNotNull; +import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkStateNotNull; import static androidx.media3.session.MediaConstants.ARGUMENT_CAPTIONING_ENABLED; -import static androidx.media3.session.MediaConstants.MEDIA_URI_QUERY_ID; -import static androidx.media3.session.MediaConstants.MEDIA_URI_QUERY_QUERY; -import static androidx.media3.session.MediaConstants.MEDIA_URI_QUERY_URI; -import static androidx.media3.session.MediaConstants.MEDIA_URI_SET_MEDIA_URI_PREFIX; import static androidx.media3.session.MediaConstants.SESSION_COMMAND_ON_CAPTIONING_ENABLED_CHANGED; import static androidx.media3.session.MediaUtils.POSITION_DIFF_TOLERANCE_MS; import static androidx.media3.session.MediaUtils.calculateBufferedPercentage; -import static androidx.media3.session.SessionResult.RESULT_INFO_SKIPPED; import static androidx.media3.session.SessionResult.RESULT_SUCCESS; import static java.lang.Math.max; import static java.lang.Math.min; @@ -60,7 +56,6 @@ import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.MediaSessionCompat.QueueItem; import android.support.v4.media.session.PlaybackStateCompat; -import android.text.TextUtils; import android.util.Pair; import android.view.Surface; import android.view.SurfaceHolder; @@ -112,30 +107,19 @@ private static final long AGGREGATES_CALLBACKS_WITHIN_TIMEOUT_MS = 500L; private static final int VOLUME_FLAGS = AudioManager.FLAG_SHOW_UI; - final Context context; + /* package */ final Context context; + /* package */ final MediaController instance; private final SessionToken token; - - final MediaController instance; - private final ListenerSet listeners; - private final ControllerCompatCallback controllerCompatCallback; @Nullable private MediaControllerCompat controllerCompat; - @Nullable private MediaBrowserCompat browserCompat; - private boolean released; - private boolean connected; - - @Nullable private SetMediaUriRequest pendingSetMediaUriRequest; - private LegacyPlayerInfo legacyPlayerInfo; - private LegacyPlayerInfo pendingLegacyPlayerInfo; - private ControllerInfo controllerInfo; public MediaControllerImplLegacy(Context context, MediaController instance, SessionToken token) { @@ -177,6 +161,9 @@ public void removeListener(Listener listener) { @Override public void stop() { + if (controllerInfo.playerInfo.playbackState == STATE_IDLE) { + return; + } PlayerInfo maskedPlayerInfo = controllerInfo.playerInfo.copyWithSessionPositionInfo( createSessionPositionInfo( @@ -244,6 +231,9 @@ public boolean isConnected() { @Override public void play() { + if (controllerInfo.playerInfo.playWhenReady) { + return; + } ControllerInfo maskedControllerInfo = new ControllerInfo( controllerInfo.playerInfo.copyWithPlayWhenReady( @@ -258,36 +248,16 @@ public void play() { /* discontinuityReason= */ null, /* mediaItemTransitionReason= */ null); - if (pendingSetMediaUriRequest == null) { + if (isPrepared() && hasMedia()) { controllerCompat.getTransportControls().play(); - } else { - switch (pendingSetMediaUriRequest.type) { - case MEDIA_URI_QUERY_ID: - controllerCompat - .getTransportControls() - .playFromMediaId(pendingSetMediaUriRequest.value, pendingSetMediaUriRequest.extras); - break; - case MEDIA_URI_QUERY_QUERY: - controllerCompat - .getTransportControls() - .playFromSearch(pendingSetMediaUriRequest.value, pendingSetMediaUriRequest.extras); - break; - case MEDIA_URI_QUERY_URI: - controllerCompat - .getTransportControls() - .playFromUri( - Uri.parse(pendingSetMediaUriRequest.value), pendingSetMediaUriRequest.extras); - break; - default: - throw new IllegalStateException("Unexpected type " + pendingSetMediaUriRequest.type); - } - pendingSetMediaUriRequest.result.set(new SessionResult(RESULT_SUCCESS)); - pendingSetMediaUriRequest = null; } } @Override public void pause() { + if (!controllerInfo.playerInfo.playWhenReady) { + return; + } ControllerInfo maskedControllerInfo = new ControllerInfo( controllerInfo.playerInfo.copyWithPlayWhenReady( @@ -302,11 +272,16 @@ public void pause() { /* discontinuityReason= */ null, /* mediaItemTransitionReason= */ null); - controllerCompat.getTransportControls().pause(); + if (isPrepared() && hasMedia()) { + controllerCompat.getTransportControls().pause(); + } } @Override public void prepare() { + if (controllerInfo.playerInfo.playbackState != STATE_IDLE) { + return; + } ControllerInfo maskedControllerInfo = new ControllerInfo( controllerInfo.playerInfo.copyWithPlaybackState( @@ -322,32 +297,8 @@ public void prepare() { /* discontinuityReason= */ null, /* mediaItemTransitionReason= */ null); - if (pendingSetMediaUriRequest == null) { - controllerCompat.getTransportControls().prepare(); - } else { - switch (pendingSetMediaUriRequest.type) { - case MEDIA_URI_QUERY_ID: - controllerCompat - .getTransportControls() - .prepareFromMediaId( - pendingSetMediaUriRequest.value, pendingSetMediaUriRequest.extras); - break; - case MEDIA_URI_QUERY_QUERY: - controllerCompat - .getTransportControls() - .prepareFromSearch(pendingSetMediaUriRequest.value, pendingSetMediaUriRequest.extras); - break; - case MEDIA_URI_QUERY_URI: - controllerCompat - .getTransportControls() - .prepareFromUri( - Uri.parse(pendingSetMediaUriRequest.value), pendingSetMediaUriRequest.extras); - break; - default: - throw new IllegalStateException("Unexpected type " + pendingSetMediaUriRequest.type); - } - pendingSetMediaUriRequest.result.set(new SessionResult(RESULT_SUCCESS)); - pendingSetMediaUriRequest = null; + if (hasMedia()) { + initializeLegacyPlaylist(); } } @@ -655,63 +606,71 @@ public Timeline getCurrentTimeline() { } @Override - public void setMediaItem(MediaItem unusedMediaItem) { - Log.w(TAG, "Session doesn't support setting media items"); + public void setMediaItem(MediaItem mediaItem) { + setMediaItem(mediaItem, /* startPositionMs= */ C.TIME_UNSET); } @Override - public void setMediaItem(MediaItem unusedMediaItem, long unusedStartPositionMs) { - Log.w(TAG, "Session doesn't support setting media items"); + public void setMediaItem(MediaItem mediaItem, long startPositionMs) { + setMediaItems(ImmutableList.of(mediaItem), /* startIndex= */ 0, startPositionMs); } @Override - public void setMediaItem(MediaItem unusedMediaItem, boolean unusedResetPosition) { - Log.w(TAG, "Session doesn't support setting media items"); + public void setMediaItem(MediaItem mediaItem, boolean resetPosition) { + setMediaItem(mediaItem); } @Override - public void setMediaItems(List unusedMediaItems) { - Log.w(TAG, "Session doesn't support setting media items"); + public void setMediaItems(List mediaItems) { + setMediaItems(mediaItems, /* startIndex= */ 0, /* startPositionMs= */ C.TIME_UNSET); } @Override - public void setMediaItems(List unusedMediaItems, boolean unusedResetPosition) { - Log.w(TAG, "Session doesn't support setting media items"); + public void setMediaItems(List mediaItems, boolean resetPosition) { + setMediaItems(mediaItems); } @Override - public void setMediaItems( - List unusedMediaItems, int unusedStartIndex, long unusedStartPositionMs) { - Log.w(TAG, "Session doesn't support setting media items"); + public void setMediaItems(List mediaItems, int startIndex, long startPositionMs) { + if (mediaItems.isEmpty()) { + clearMediaItems(); + return; + } + QueueTimeline newQueueTimeline = + QueueTimeline.DEFAULT.copyWithNewMediaItems(/* index= */ 0, mediaItems); + if (startPositionMs == C.TIME_UNSET) { + // Assume a default start position of 0 until we know more. + startPositionMs = 0; + } + PlayerInfo maskedPlayerInfo = + controllerInfo.playerInfo.copyWithTimelineAndSessionPositionInfo( + newQueueTimeline, + createSessionPositionInfo( + createPositionInfo(startIndex, mediaItems.get(startIndex), startPositionMs), + /* isPlayingAd= */ false, + /* durationMs= */ C.TIME_UNSET, + /* bufferedPositionMs= */ 0, + /* bufferedPercentage= */ 0, + /* totalBufferedDurationMs= */ 0)); + ControllerInfo maskedControllerInfo = + new ControllerInfo( + maskedPlayerInfo, + controllerInfo.availableSessionCommands, + controllerInfo.availablePlayerCommands, + controllerInfo.customLayout); + updateStateMaskedControllerInfo( + maskedControllerInfo, + /* discontinuityReason= */ null, + /* mediaItemTransitionReason= */ null); + if (isPrepared()) { + initializeLegacyPlaylist(); + } } @Override public ListenableFuture setMediaUri(Uri uri, Bundle extras) { - if (pendingSetMediaUriRequest != null) { - Log.w( - TAG, - "SetMediaUri() is called multiple times without prepare() nor play()." - + " Previous call will be skipped."); - pendingSetMediaUriRequest.result.set(new SessionResult(RESULT_INFO_SKIPPED)); - pendingSetMediaUriRequest = null; - } - SettableFuture result = SettableFuture.create(); - if (uri.toString().startsWith(MEDIA_URI_SET_MEDIA_URI_PREFIX) - && uri.getQueryParameterNames().size() == 1) { - String queryParameterName = uri.getQueryParameterNames().iterator().next(); - if (TextUtils.equals(queryParameterName, MEDIA_URI_QUERY_ID) - || TextUtils.equals(queryParameterName, MEDIA_URI_QUERY_QUERY) - || TextUtils.equals(queryParameterName, MEDIA_URI_QUERY_URI)) { - pendingSetMediaUriRequest = - new SetMediaUriRequest( - queryParameterName, uri.getQueryParameter(queryParameterName), extras, result); - } - } - if (pendingSetMediaUriRequest == null) { - pendingSetMediaUriRequest = - new SetMediaUriRequest(MEDIA_URI_QUERY_URI, uri.toString(), extras, result); - } - return result; + Log.w(TAG, "Session doesn't support setMediaUri"); + return Futures.immediateCancelledFuture(); } @Override @@ -744,9 +703,14 @@ public void addMediaItems(int index, List mediaItems) { if (mediaItems.isEmpty()) { return; } - index = min(index, getCurrentTimeline().getWindowCount()); - QueueTimeline queueTimeline = (QueueTimeline) controllerInfo.playerInfo.timeline; + if (queueTimeline.isEmpty()) { + // Handle initial items in setMediaItems to ensure initial legacy session commands are called. + setMediaItems(mediaItems); + return; + } + + index = min(index, getCurrentTimeline().getWindowCount()); QueueTimeline newQueueTimeline = queueTimeline.copyWithNewMediaItems(index, mediaItems); int currentMediaItemIndex = getCurrentMediaItemIndex(); int newCurrentMediaItemIndex = @@ -765,10 +729,12 @@ public void addMediaItems(int index, List mediaItems) { /* discontinuityReason= */ null, /* mediaItemTransitionReason= */ null); - for (int i = 0; i < mediaItems.size(); i++) { - MediaItem mediaItem = mediaItems.get(i); - controllerCompat.addQueueItem( - MediaUtils.convertToMediaDescriptionCompat(mediaItem), index + i); + if (isPrepared()) { + for (int i = 0; i < mediaItems.size(); i++) { + MediaItem mediaItem = mediaItems.get(i); + controllerCompat.addQueueItem( + MediaUtils.convertToMediaDescriptionCompat(mediaItem), index + i); + } } } @@ -815,8 +781,10 @@ public void removeMediaItems(int fromIndex, int toIndex) { /* discontinuityReason= */ null, /* mediaItemTransitionReason= */ null); - for (int i = fromIndex; i < toIndex && i < legacyPlayerInfo.queue.size(); i++) { - controllerCompat.removeQueueItem(legacyPlayerInfo.queue.get(i).getDescription()); + if (isPrepared()) { + for (int i = fromIndex; i < toIndex && i < legacyPlayerInfo.queue.size(); i++) { + controllerCompat.removeQueueItem(legacyPlayerInfo.queue.get(i).getDescription()); + } } } @@ -876,14 +844,16 @@ public void moveMediaItems(int fromIndex, int toIndex, int newIndex) { /* discontinuityReason= */ null, /* mediaItemTransitionReason= */ null); - ArrayList moveItems = new ArrayList<>(); - for (int i = 0; i < (toIndex - fromIndex); i++) { - moveItems.add(legacyPlayerInfo.queue.get(fromIndex)); - controllerCompat.removeQueueItem(legacyPlayerInfo.queue.get(fromIndex).getDescription()); - } - for (int i = 0; i < moveItems.size(); i++) { - QueueItem item = moveItems.get(i); - controllerCompat.addQueueItem(item.getDescription(), i + newIndex); + if (isPrepared()) { + ArrayList moveItems = new ArrayList<>(); + for (int i = 0; i < (toIndex - fromIndex); i++) { + moveItems.add(legacyPlayerInfo.queue.get(fromIndex)); + controllerCompat.removeQueueItem(legacyPlayerInfo.queue.get(fromIndex).getDescription()); + } + for (int i = 0; i < moveItems.size(); i++) { + QueueItem item = moveItems.get(i); + controllerCompat.addQueueItem(item.getDescription(), i + newIndex); + } } } @@ -1294,6 +1264,91 @@ private void connectToService() { }); } + private boolean isPrepared() { + return controllerInfo.playerInfo.playbackState != STATE_IDLE; + } + + private boolean hasMedia() { + return !controllerInfo.playerInfo.timeline.isEmpty(); + } + + private void initializeLegacyPlaylist() { + Window window = new Window(); + checkState(isPrepared() && hasMedia()); + QueueTimeline queueTimeline = (QueueTimeline) controllerInfo.playerInfo.timeline; + // Set the current item first as these calls are expected to replace the current playlist. + int currentIndex = controllerInfo.playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex; + MediaItem currentMediaItem = queueTimeline.getWindow(currentIndex, window).mediaItem; + if (queueTimeline.getQueueId(currentIndex) != QueueItem.UNKNOWN_ID) { + // Current item is already known to the session. Just prepare or play. + if (controllerInfo.playerInfo.playWhenReady) { + controllerCompat.getTransportControls().play(); + } else { + controllerCompat.getTransportControls().prepare(); + } + } else if (currentMediaItem.requestMetadata.mediaUri != null) { + if (controllerInfo.playerInfo.playWhenReady) { + controllerCompat + .getTransportControls() + .playFromUri( + currentMediaItem.requestMetadata.mediaUri, + getOrEmptyBundle(currentMediaItem.requestMetadata.extras)); + } else { + controllerCompat + .getTransportControls() + .prepareFromUri( + currentMediaItem.requestMetadata.mediaUri, + getOrEmptyBundle(currentMediaItem.requestMetadata.extras)); + } + } else if (currentMediaItem.requestMetadata.searchQuery != null) { + if (controllerInfo.playerInfo.playWhenReady) { + controllerCompat + .getTransportControls() + .playFromSearch( + currentMediaItem.requestMetadata.searchQuery, + getOrEmptyBundle(currentMediaItem.requestMetadata.extras)); + } else { + controllerCompat + .getTransportControls() + .prepareFromSearch( + currentMediaItem.requestMetadata.searchQuery, + getOrEmptyBundle(currentMediaItem.requestMetadata.extras)); + } + } else { + if (controllerInfo.playerInfo.playWhenReady) { + controllerCompat + .getTransportControls() + .playFromMediaId( + currentMediaItem.mediaId, + getOrEmptyBundle(currentMediaItem.requestMetadata.extras)); + } else { + controllerCompat + .getTransportControls() + .prepareFromMediaId( + currentMediaItem.mediaId, + getOrEmptyBundle(currentMediaItem.requestMetadata.extras)); + } + } + // Seek to non-zero start positon if needed. + if (controllerInfo.playerInfo.sessionPositionInfo.positionInfo.positionMs != 0) { + controllerCompat + .getTransportControls() + .seekTo(controllerInfo.playerInfo.sessionPositionInfo.positionInfo.positionMs); + } + // Add all other items to the playlist if supported. + if (getAvailableCommands().contains(Player.COMMAND_CHANGE_MEDIA_ITEMS)) { + for (int i = 0; i < queueTimeline.getWindowCount(); i++) { + if (i == currentIndex || queueTimeline.getQueueId(i) != QueueItem.UNKNOWN_ID) { + // Skip the current item (added above) and all items already known to the session. + continue; + } + MediaItem mediaItem = queueTimeline.getWindow(/* windowIndex= */ i, window).mediaItem; + controllerCompat.addQueueItem( + MediaUtils.convertToMediaDescriptionCompat(mediaItem), /* index= */ i); + } + } + } + private void handleNewLegacyParameters( boolean notifyConnected, LegacyPlayerInfo newLegacyPlayerInfo) { if (released || !connected) { @@ -1938,6 +1993,10 @@ private static PlaybackStateCompat convertToSafePlaybackStateCompat( return state; } + private static Bundle getOrEmptyBundle(@Nullable Bundle bundle) { + return bundle == null ? Bundle.EMPTY : bundle; + } + private static long getActiveQueueId(@Nullable PlaybackStateCompat playbackStateCompat) { return playbackStateCompat == null ? QueueItem.UNKNOWN_ID @@ -2088,22 +2147,6 @@ private static SessionPositionInfo createSessionPositionInfo( /* contentBufferedPositionMs= */ bufferedPositionMs); } - private static final class SetMediaUriRequest { - - public final String type; - public final String value; - public final Bundle extras; - public final SettableFuture result; - - public SetMediaUriRequest( - String type, String value, Bundle extras, SettableFuture result) { - this.type = type; - this.value = value; - this.extras = extras; - this.result = result; - } - } - // Media 1.0 variables private static final class LegacyPlayerInfo { diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSession.java b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java index 194f074264..71edff1179 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSession.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java @@ -88,7 +88,7 @@ *

  • Threading Model *
  • Media Key Events Mapping *
  • Supporting Multiple Sessions - *
  • Backward Compatibility with Legacy Session APIs + *
  • Backward Compatibility with Legacy Session APIs *
  • Backward Compatibility with Legacy Controller APIs * * @@ -201,10 +201,10 @@ * *

    Backward Compatibility with Legacy Controller APIs

    * - *

    In addition to {@link MediaController}, session also supports connection from the legacy - * controller APIs - {@link android.media.session.MediaController framework controller} and {@link - * MediaControllerCompat AndroidX controller compat}. However, {@link ControllerInfo} may not be - * precise for legacy controllers. See {@link ControllerInfo} for the details. + *

    In addition to {@link MediaController}, the session also supports connections from the legacy + * controller APIs - {@linkplain android.media.session.MediaController framework controller} and + * {@linkplain MediaControllerCompat AndroidX controller compat}. However, {@link ControllerInfo} + * may not be precise for legacy controllers. See {@link ControllerInfo} for the details. * *

    Unknown package name nor UID doesn't mean that you should disallow connection nor commands. * For SDK levels where such issues happen, session tokens could only be obtained by trusted diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaUtils.java b/libraries/session/src/main/java/androidx/media3/session/MediaUtils.java index f3459fccca..d85bc1194b 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaUtils.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaUtils.java @@ -30,6 +30,7 @@ import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS; import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM; import static androidx.media3.common.Player.COMMAND_SET_DEVICE_VOLUME; +import static androidx.media3.common.Player.COMMAND_SET_MEDIA_ITEM; import static androidx.media3.common.Player.COMMAND_SET_REPEAT_MODE; import static androidx.media3.common.Player.COMMAND_SET_SHUFFLE_MODE; import static androidx.media3.common.Player.COMMAND_SET_SPEED_AND_PITCH; @@ -1058,7 +1059,8 @@ public static Player.Commands convertToPlayerCommands(long sessionFlags, boolean COMMAND_SEEK_TO_NEXT, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_GET_MEDIA_ITEMS_METADATA, - COMMAND_GET_CURRENT_MEDIA_ITEM); + COMMAND_GET_CURRENT_MEDIA_ITEM, + COMMAND_SET_MEDIA_ITEM); boolean includePlaylistCommands = (sessionFlags & FLAG_HANDLES_QUEUE_COMMANDS) != 0; if (includePlaylistCommands) { playerCommandsBuilder.add(COMMAND_CHANGE_MEDIA_ITEMS); diff --git a/libraries/session/src/main/java/androidx/media3/session/QueueTimeline.java b/libraries/session/src/main/java/androidx/media3/session/QueueTimeline.java index be92deea32..adaf65d707 100644 --- a/libraries/session/src/main/java/androidx/media3/session/QueueTimeline.java +++ b/libraries/session/src/main/java/androidx/media3/session/QueueTimeline.java @@ -79,11 +79,11 @@ public QueueTimeline copyWithNewMediaItem(int replaceIndex, MediaItem newMediaIt newMediaItemsBuilder.build(), unmodifiableMediaItemToQueueIdMap, fakeMediaItem); } - public QueueTimeline copyWithNewMediaItems(int addToIndex, List newMediaItems) { + public QueueTimeline copyWithNewMediaItems(int index, List newMediaItems) { ImmutableList.Builder newMediaItemsBuilder = new ImmutableList.Builder<>(); - newMediaItemsBuilder.addAll(mediaItems.subList(0, addToIndex)); + newMediaItemsBuilder.addAll(mediaItems.subList(0, index)); newMediaItemsBuilder.addAll(newMediaItems); - newMediaItemsBuilder.addAll(mediaItems.subList(addToIndex, mediaItems.size())); + newMediaItemsBuilder.addAll(mediaItems.subList(index, mediaItems.size())); return new QueueTimeline( newMediaItemsBuilder.build(), unmodifiableMediaItemToQueueIdMap, fakeMediaItem); } diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerWithMediaSessionCompatTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerWithMediaSessionCompatTest.java index 882dc54dff..1ea60474e6 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerWithMediaSessionCompatTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerWithMediaSessionCompatTest.java @@ -29,7 +29,6 @@ import static androidx.media3.common.Player.STATE_READY; import static androidx.media3.session.MediaConstants.ARGUMENT_CAPTIONING_ENABLED; import static androidx.media3.session.MediaConstants.SESSION_COMMAND_ON_CAPTIONING_ENABLED_CHANGED; -import static androidx.media3.session.SessionResult.RESULT_INFO_SKIPPED; import static androidx.media3.session.SessionResult.RESULT_SUCCESS; import static androidx.media3.test.session.common.CommonConstants.DEFAULT_TEST_NAME; import static androidx.media3.test.session.common.CommonConstants.METADATA_ALBUM_TITLE; @@ -37,10 +36,8 @@ import static androidx.media3.test.session.common.CommonConstants.METADATA_DESCRIPTION; import static androidx.media3.test.session.common.CommonConstants.METADATA_TITLE; import static androidx.media3.test.session.common.CommonConstants.SUPPORT_APP_PACKAGE_NAME; -import static androidx.media3.test.session.common.TestUtils.NO_RESPONSE_TIMEOUT_MS; import static androidx.media3.test.session.common.TestUtils.TIMEOUT_MS; import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; import static java.util.concurrent.TimeUnit.MILLISECONDS; import android.app.PendingIntent; @@ -85,8 +82,6 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -567,77 +562,6 @@ public void onPositionDiscontinuity( assertThat(isPlayingAdRef.get()).isTrue(); } - @Test - public void setMediaUri_resultSetAfterPrepare() throws Exception { - MediaController controller = controllerTestRule.createController(session.getSessionToken()); - - Uri testUri = Uri.parse("androidx://test"); - ListenableFuture future = - threadTestRule - .getHandler() - .postAndSync(() -> controller.setMediaUri(testUri, /* extras= */ Bundle.EMPTY)); - - SessionResult result; - try { - result = future.get(NO_RESPONSE_TIMEOUT_MS, TimeUnit.MILLISECONDS); - assertWithMessage("TimeoutException is expected").fail(); - } catch (TimeoutException e) { - // expected. - } - - threadTestRule.getHandler().postAndSync(controller::prepare); - - result = future.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); - assertThat(result.resultCode).isEqualTo(RESULT_SUCCESS); - } - - @Test - public void setMediaUri_resultSetAfterPlay() throws Exception { - MediaController controller = controllerTestRule.createController(session.getSessionToken()); - - Uri testUri = Uri.parse("androidx://test"); - ListenableFuture future = - threadTestRule - .getHandler() - .postAndSync(() -> controller.setMediaUri(testUri, /* extras= */ Bundle.EMPTY)); - - SessionResult result; - try { - result = future.get(NO_RESPONSE_TIMEOUT_MS, TimeUnit.MILLISECONDS); - assertWithMessage("TimeoutException is expected").fail(); - } catch (TimeoutException e) { - // expected. - } - - threadTestRule.getHandler().postAndSync(controller::play); - - result = future.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); - assertThat(result.resultCode).isEqualTo(RESULT_SUCCESS); - } - - @Test - public void setMediaUris_multipleCalls_previousCallReturnsResultInfoSkipped() throws Exception { - MediaController controller = controllerTestRule.createController(session.getSessionToken()); - - Uri testUri1 = Uri.parse("androidx://test1"); - Uri testUri2 = Uri.parse("androidx://test2"); - ListenableFuture future1 = - threadTestRule - .getHandler() - .postAndSync(() -> controller.setMediaUri(testUri1, /* extras= */ Bundle.EMPTY)); - ListenableFuture future2 = - threadTestRule - .getHandler() - .postAndSync(() -> controller.setMediaUri(testUri2, /* extras= */ Bundle.EMPTY)); - - threadTestRule.getHandler().postAndSync(controller::prepare); - - SessionResult result1 = future1.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); - SessionResult result2 = future2.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); - assertThat(result1.resultCode).isEqualTo(RESULT_INFO_SKIPPED); - assertThat(result2.resultCode).isEqualTo(RESULT_SUCCESS); - } - @Test public void seekToDefaultPosition_withMediaItemIndex_updatesExpectedMediaItemIndex() throws Exception { diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionCompatCallbackWithMediaControllerTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionCompatCallbackWithMediaControllerTest.java index 57996844a2..ca25291cf4 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionCompatCallbackWithMediaControllerTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionCompatCallbackWithMediaControllerTest.java @@ -16,13 +16,6 @@ package androidx.media3.session; import static android.support.v4.media.session.MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS; -import static androidx.media3.session.MediaConstants.MEDIA_URI_AUTHORITY; -import static androidx.media3.session.MediaConstants.MEDIA_URI_PATH_SET_MEDIA_URI; -import static androidx.media3.session.MediaConstants.MEDIA_URI_QUERY_ID; -import static androidx.media3.session.MediaConstants.MEDIA_URI_QUERY_QUERY; -import static androidx.media3.session.MediaConstants.MEDIA_URI_QUERY_URI; -import static androidx.media3.session.MediaConstants.MEDIA_URI_SCHEME; -import static androidx.media3.test.session.common.TestUtils.NO_RESPONSE_TIMEOUT_MS; import static androidx.media3.test.session.common.TestUtils.VOLUME_CHANGE_TIMEOUT_MS; import static com.google.common.truth.Truth.assertThat; import static java.util.concurrent.TimeUnit.MILLISECONDS; @@ -78,6 +71,9 @@ public class MediaSessionCompatCallbackWithMediaControllerTest { // The maximum time to wait for an operation. private static final long TIMEOUT_MS = 3000L; + // Timeout used where the test expects no operation. + private static final long NOOP_TIMEOUT_MS = 500L; + @ClassRule public static MainLooperTestRule mainLooperTestRule = new MainLooperTestRule(); @Rule public final HandlerThreadTestRule threadTestRule = new HandlerThreadTestRule(TAG); @@ -122,6 +118,11 @@ private RemoteMediaController createControllerAndWaitConnection() throws Excepti @Test public void play() throws Exception { + List testList = MediaTestUtils.createMediaItems(/* size= */ 2); + List testQueue = MediaUtils.convertToQueueItemList(testList); + session.setQueue(testQueue); + session.setFlags(FLAG_HANDLES_QUEUE_COMMANDS); + setPlaybackState(PlaybackStateCompat.STATE_PAUSED); RemoteMediaController controller = createControllerAndWaitConnection(); sessionCallback.reset(1); @@ -132,6 +133,11 @@ public void play() throws Exception { @Test public void pause() throws Exception { + List testList = MediaTestUtils.createMediaItems(/* size= */ 2); + List testQueue = MediaUtils.convertToQueueItemList(testList); + session.setQueue(testQueue); + session.setFlags(FLAG_HANDLES_QUEUE_COMMANDS); + setPlaybackState(PlaybackStateCompat.STATE_PLAYING); RemoteMediaController controller = createControllerAndWaitConnection(); sessionCallback.reset(1); @@ -142,20 +148,31 @@ public void pause() throws Exception { @Test public void prepare() throws Exception { + List testList = MediaTestUtils.createMediaItems(/* size= */ 2); + List testQueue = MediaUtils.convertToQueueItemList(testList); + session.setQueue(testQueue); + session.setFlags(FLAG_HANDLES_QUEUE_COMMANDS); RemoteMediaController controller = createControllerAndWaitConnection(); sessionCallback.reset(1); controller.prepare(); + assertThat(sessionCallback.await(TIMEOUT_MS)).isTrue(); assertThat(sessionCallback.onPrepareCalled).isEqualTo(true); } @Test public void stop() throws Exception { + List testList = MediaTestUtils.createMediaItems(/* size= */ 2); + List testQueue = MediaUtils.convertToQueueItemList(testList); + session.setQueue(testQueue); + session.setFlags(FLAG_HANDLES_QUEUE_COMMANDS); RemoteMediaController controller = createControllerAndWaitConnection(); + controller.prepare(); sessionCallback.reset(1); controller.stop(); + assertThat(sessionCallback.await(TIMEOUT_MS)).isTrue(); assertThat(sessionCallback.onStopCalled).isEqualTo(true); } @@ -314,6 +331,7 @@ public void addMediaItems() throws Exception { session.setQueue(testQueue); session.setFlags(FLAG_HANDLES_QUEUE_COMMANDS); + setPlaybackState(PlaybackStateCompat.STATE_PLAYING); RemoteMediaController controller = createControllerAndWaitConnection(); sessionCallback.reset(size); @@ -338,6 +356,7 @@ public void removeMediaItems() throws Exception { session.setQueue(MediaUtils.convertToQueueItemList(testList)); session.setFlags(FLAG_HANDLES_QUEUE_COMMANDS); + setPlaybackState(PlaybackStateCompat.STATE_BUFFERING); RemoteMediaController controller = createControllerAndWaitConnection(); sessionCallback.reset(count); @@ -634,269 +653,6 @@ public void setRatingWithoutMediaId() throws Exception { assertThat(MediaUtils.convertToRating(sessionCallback.rating)).isEqualTo(rating); } - @Test - public void setMediaUri_ignored() throws Exception { - RemoteMediaController controller = createControllerAndWaitConnection(); - sessionCallback.reset(1); - - controller.setMediaUri(Uri.parse("androidx://test?test=xx"), /* extras= */ Bundle.EMPTY); - - assertThat(sessionCallback.await(NO_RESPONSE_TIMEOUT_MS)).isFalse(); - } - - @Test - public void setMediaUri_followedByPrepare_callsPrepareFromMediaId() throws Exception { - String testMediaId = "anyMediaId"; - Bundle testExtras = new Bundle(); - testExtras.putString("testKey", "testValue"); - - RemoteMediaController controller = createControllerAndWaitConnection(); - sessionCallback.reset(1); - - controller.setMediaUri( - new Uri.Builder() - .scheme(MEDIA_URI_SCHEME) - .authority(MEDIA_URI_AUTHORITY) - .path(MEDIA_URI_PATH_SET_MEDIA_URI) - .appendQueryParameter(MEDIA_URI_QUERY_ID, testMediaId) - .build(), - testExtras); - controller.prepare(); - - assertThat(sessionCallback.await(TIMEOUT_MS)).isTrue(); - assertThat(sessionCallback.onPrepareFromMediaIdCalled).isTrue(); - assertThat(sessionCallback.mediaId).isEqualTo(testMediaId); - assertThat(TestUtils.equals(testExtras, sessionCallback.extras)).isTrue(); - assertThat(sessionCallback.query).isNull(); - assertThat(sessionCallback.uri).isNull(); - assertThat(sessionCallback.onPrepareCalled).isFalse(); - } - - @Test - public void setMediaUri_followedByPrepare_callsPrepareFromSearch() throws Exception { - String testSearchQuery = "anyQuery"; - Bundle testExtras = new Bundle(); - testExtras.putString("testKey", "testValue"); - - RemoteMediaController controller = createControllerAndWaitConnection(); - sessionCallback.reset(1); - - controller.setMediaUri( - new Uri.Builder() - .scheme(MEDIA_URI_SCHEME) - .authority(MEDIA_URI_AUTHORITY) - .path(MEDIA_URI_PATH_SET_MEDIA_URI) - .appendQueryParameter(MEDIA_URI_QUERY_QUERY, testSearchQuery) - .build(), - testExtras); - controller.prepare(); - - assertThat(sessionCallback.await(TIMEOUT_MS)).isTrue(); - assertThat(sessionCallback.onPrepareFromSearchCalled).isTrue(); - assertThat(sessionCallback.query).isEqualTo(testSearchQuery); - assertThat(TestUtils.equals(testExtras, sessionCallback.extras)).isTrue(); - assertThat(sessionCallback.mediaId).isNull(); - assertThat(sessionCallback.uri).isNull(); - assertThat(sessionCallback.onPrepareCalled).isFalse(); - } - - @Test - public void setMediaUri_followedByPrepare_callsPrepareFromUri() throws Exception { - Uri testMediaUri = Uri.parse("androidx://jetpack/test?query=android%20media"); - Bundle testExtras = new Bundle(); - testExtras.putString("testKey", "testValue"); - - RemoteMediaController controller = createControllerAndWaitConnection(); - sessionCallback.reset(1); - - controller.setMediaUri( - new Uri.Builder() - .scheme(MEDIA_URI_SCHEME) - .authority(MEDIA_URI_AUTHORITY) - .path(MEDIA_URI_PATH_SET_MEDIA_URI) - .appendQueryParameter(MEDIA_URI_QUERY_URI, testMediaUri.toString()) - .build(), - testExtras); - controller.prepare(); - - assertThat(sessionCallback.await(TIMEOUT_MS)).isTrue(); - assertThat(sessionCallback.onPrepareFromUriCalled).isTrue(); - assertThat(sessionCallback.uri).isEqualTo(testMediaUri); - assertThat(sessionCallback.mediaId).isNull(); - assertThat(sessionCallback.query).isNull(); - assertThat(sessionCallback.onPrepareCalled).isFalse(); - } - - @Test - public void setMediaUri_withoutFormattingFollowedByPrepare_callsPrepareFromUri() - throws Exception { - Uri testMediaUri = Uri.parse("androidx://jetpack/test?query=android%20media"); - Bundle testExtras = new Bundle(); - testExtras.putString("testKey", "testValue"); - - RemoteMediaController controller = createControllerAndWaitConnection(); - sessionCallback.reset(1); - - controller.setMediaUri(testMediaUri, testExtras); - controller.prepare(); - - assertThat(sessionCallback.await(TIMEOUT_MS)).isTrue(); - assertThat(sessionCallback.onPrepareFromUriCalled).isTrue(); - assertThat(sessionCallback.uri).isEqualTo(testMediaUri); - assertThat(sessionCallback.mediaId).isNull(); - assertThat(sessionCallback.query).isNull(); - assertThat(sessionCallback.onPrepareCalled).isFalse(); - } - - @Test - public void setMediaUri_followedByPlay_callsPlayFromMediaId() throws Exception { - String testMediaId = "anyMediaId"; - Bundle testExtras = new Bundle(); - testExtras.putString("testKey", "testValue"); - - RemoteMediaController controller = createControllerAndWaitConnection(); - sessionCallback.reset(1); - - controller.setMediaUri( - new Uri.Builder() - .scheme(MEDIA_URI_SCHEME) - .authority(MEDIA_URI_AUTHORITY) - .path(MEDIA_URI_PATH_SET_MEDIA_URI) - .appendQueryParameter(MEDIA_URI_QUERY_ID, testMediaId) - .build(), - testExtras); - controller.play(); - - assertThat(sessionCallback.await(TIMEOUT_MS)).isTrue(); - assertThat(sessionCallback.onPlayFromMediaIdCalled).isTrue(); - assertThat(sessionCallback.mediaId).isEqualTo(testMediaId); - assertThat(TestUtils.equals(testExtras, sessionCallback.extras)).isTrue(); - assertThat(sessionCallback.query).isNull(); - assertThat(sessionCallback.uri).isNull(); - assertThat(sessionCallback.onPlayCalledCount).isEqualTo(0); - } - - @Test - public void setMediaUri_followedByPlay_callsPlayFromSearch() throws Exception { - String testSearchQuery = "anyQuery"; - Bundle testExtras = new Bundle(); - testExtras.putString("testKey", "testValue"); - - RemoteMediaController controller = createControllerAndWaitConnection(); - sessionCallback.reset(1); - - controller.setMediaUri( - new Uri.Builder() - .scheme(MEDIA_URI_SCHEME) - .authority(MEDIA_URI_AUTHORITY) - .path(MEDIA_URI_PATH_SET_MEDIA_URI) - .appendQueryParameter(MEDIA_URI_QUERY_QUERY, testSearchQuery) - .build(), - testExtras); - controller.play(); - - assertThat(sessionCallback.await(TIMEOUT_MS)).isTrue(); - assertThat(sessionCallback.onPlayFromSearchCalled).isTrue(); - assertThat(sessionCallback.query).isEqualTo(testSearchQuery); - assertThat(TestUtils.equals(testExtras, sessionCallback.extras)).isTrue(); - assertThat(sessionCallback.mediaId).isNull(); - assertThat(sessionCallback.uri).isNull(); - assertThat(sessionCallback.onPlayCalledCount).isEqualTo(0); - } - - @Test - public void setMediaUri_followedByPlay_callsPlayFromUri() throws Exception { - Uri testMediaUri = Uri.parse("androidx://jetpack/test?query=android%20media"); - Bundle testExtras = new Bundle(); - testExtras.putString("testKey", "testValue"); - - RemoteMediaController controller = createControllerAndWaitConnection(); - sessionCallback.reset(1); - - controller.setMediaUri( - new Uri.Builder() - .scheme(MEDIA_URI_SCHEME) - .authority(MEDIA_URI_AUTHORITY) - .path(MEDIA_URI_PATH_SET_MEDIA_URI) - .appendQueryParameter(MEDIA_URI_QUERY_URI, testMediaUri.toString()) - .build(), - testExtras); - controller.play(); - - assertThat(sessionCallback.await(TIMEOUT_MS)).isTrue(); - assertThat(sessionCallback.onPlayFromUriCalled).isTrue(); - assertThat(sessionCallback.uri).isEqualTo(testMediaUri); - assertThat(sessionCallback.mediaId).isNull(); - assertThat(sessionCallback.query).isNull(); - assertThat(sessionCallback.onPlayCalledCount).isEqualTo(0); - } - - @Test - public void setMediaUri_withoutFormattingFollowedByPlay_callsPlayFromUri() throws Exception { - Uri testMediaUri = Uri.parse("androidx://jetpack/test?query=android%20media"); - Bundle testExtras = new Bundle(); - testExtras.putString("testKey", "testValue"); - - RemoteMediaController controller = createControllerAndWaitConnection(); - sessionCallback.reset(1); - - controller.setMediaUri(testMediaUri, testExtras); - controller.play(); - - assertThat(sessionCallback.await(TIMEOUT_MS)).isTrue(); - assertThat(sessionCallback.onPlayFromUriCalled).isTrue(); - assertThat(sessionCallback.uri).isEqualTo(testMediaUri); - assertThat(sessionCallback.mediaId).isNull(); - assertThat(sessionCallback.query).isNull(); - assertThat(sessionCallback.onPlayCalledCount).isEqualTo(0); - } - - @Test - public void setMediaUri_followedByPrepareTwice_callsPrepareFromUriAndPrepare() throws Exception { - RemoteMediaController controller = createControllerAndWaitConnection(); - sessionCallback.reset(2); - - controller.setMediaUri(Uri.parse("androidx://test"), /* extras= */ Bundle.EMPTY); - - controller.prepare(); - controller.prepare(); - - assertThat(sessionCallback.await(TIMEOUT_MS)).isTrue(); - assertThat(sessionCallback.onPrepareFromUriCalled).isTrue(); - assertThat(sessionCallback.onPrepareCalled).isTrue(); - } - - @Test - public void setMediaUri_followedByPlayTwice_callsPlayFromUriAndPlay() throws Exception { - RemoteMediaController controller = createControllerAndWaitConnection(); - sessionCallback.reset(2); - - controller.setMediaUri(Uri.parse("androidx://test"), /* extras= */ Bundle.EMPTY); - - controller.play(); - controller.play(); - - assertThat(sessionCallback.await(TIMEOUT_MS)).isTrue(); - assertThat(sessionCallback.onPlayFromUriCalled).isTrue(); - assertThat(sessionCallback.onPlayCalledCount).isEqualTo(1); - } - - @Test - public void setMediaUri_multipleCalls_skipped() throws Exception { - RemoteMediaController controller = createControllerAndWaitConnection(); - sessionCallback.reset(2); - - Uri testUri1 = Uri.parse("androidx://test1"); - Uri testUri2 = Uri.parse("androidx://test2"); - controller.setMediaUri(testUri1, /* extras= */ Bundle.EMPTY); - controller.setMediaUri(testUri2, /* extras= */ Bundle.EMPTY); - controller.prepare(); - - assertThat(sessionCallback.await(TIMEOUT_MS)).isFalse(); - assertThat(sessionCallback.onPrepareFromUriCalled).isTrue(); - assertThat(sessionCallback.uri).isEqualTo(testUri2); - } - @Test public void seekToNext_callsOnSkipToNext() throws Exception { RemoteMediaController controller = createControllerAndWaitConnection(); From ea7f1ca1e32f19131cec690c6934d82c81a2d6d0 Mon Sep 17 00:00:00 2001 From: hschlueter Date: Wed, 15 Jun 2022 13:14:56 +0000 Subject: [PATCH 15/73] Use FrameProcessorChain#SurfaceProvider for encoder compat transform. This change adds a SurfaceProvider interface which is necessary to allow for texture processors whose output size becomes available asynchronously in follow-ups. VTSP's implementation of this interface wraps the encoder and provides its input surface together with the output frame width, height, and orientation as used for encoder configuration. The FrameProcessorChain converts the output frames to the provided orientation and resolution using a ScaleToFitTransformation and Presentation replacing EncoderCompatibilityTransformation. PiperOrigin-RevId: 455112598 --- .../rotate45_then_scale2w.png | Bin 0 -> 1139704 bytes .../FrameProcessorChainPixelTest.java | 93 +++++-- .../transformer/FrameProcessorChainTest.java | 154 ----------- .../transformer/TransformerEndToEndTest.java | 69 ++++- .../EncoderCompatibilityTransformation.java | 82 ------ .../transformer/FrameProcessorChain.java | 261 ++++++++++-------- .../MatrixTransformationProcessor.java | 12 +- .../media3/transformer/MatrixUtils.java | 21 ++ .../media3/transformer/SurfaceInfo.java | 70 +++++ .../transformer/TransformerVideoRenderer.java | 5 +- .../VideoTranscodingSamplePipeline.java | 233 ++++++++++++---- ...ncoderCompatibilityTransformationTest.java | 80 ------ .../transformer/VideoEncoderWrapperTest.java | 146 ++++++++++ 13 files changed, 702 insertions(+), 524 deletions(-) create mode 100644 libraries/test_data/src/test/assets/media/bitmap/sample_mp4_first_frame/rotate45_then_scale2w.png delete mode 100644 libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainTest.java delete mode 100644 libraries/transformer/src/main/java/androidx/media3/transformer/EncoderCompatibilityTransformation.java create mode 100644 libraries/transformer/src/main/java/androidx/media3/transformer/SurfaceInfo.java delete mode 100644 libraries/transformer/src/test/java/androidx/media3/transformer/EncoderCompatibilityTransformationTest.java create mode 100644 libraries/transformer/src/test/java/androidx/media3/transformer/VideoEncoderWrapperTest.java diff --git a/libraries/test_data/src/test/assets/media/bitmap/sample_mp4_first_frame/rotate45_then_scale2w.png b/libraries/test_data/src/test/assets/media/bitmap/sample_mp4_first_frame/rotate45_then_scale2w.png new file mode 100644 index 0000000000000000000000000000000000000000..b68ddf2035ee3dd0ac8a2d73a372c5c8161fe991 GIT binary patch literal 1139704 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

    r9Ki{FJ-dIV_hXYN@D@2e8&-z}+$(ztTv!(Q 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 i-9z~;6>{I0gn6}gai9k|5 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

    <5D)zLE9r)Co`-TEj&A$+){IB5dV;k(F74#6> z{qGePqM)JGrQ5r|$XZ2xBE@?j0{@`VKmNQ}4Rw^7mBQ>jj9ho}EX1BY!#EPMCjJPH zAGhaYDbLrGGR21RFq3-j@iut$XU_avEn-{V{9De#R4nz<>@L7S-K~znBv6>E#&|`r zs(65*=sFkHkso(j+n?>P4B1uN3R03YO_l4nIPYE?YU*5Ok~Cc+IhXttB#HsO{&

    Vlzl5(lEbK4sg`cjTKMs`}6;y-Wrp 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%0A{p+2#Ui%^2vr(Ym~x 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 z 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%0D4dglGUj!6VDg`$yVk?g(W-6pU$N0I4>b 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

    F); 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%0AWQeH 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�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

    Nqu!K`!uHv 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 x{muvbsJ|&D=s``Er2IESkcNN$8ZRb$`(1(); private @MonotonicNonNull FrameProcessorChain frameProcessorChain; - private @MonotonicNonNull ImageReader outputImageReader; + private volatile @MonotonicNonNull ImageReader outputImageReader; private @MonotonicNonNull MediaFormat mediaFormat; @After @@ -260,6 +262,30 @@ public void processData_withScaleToFitTransformation_rotate45_producesExpectedOu assertThat(averagePixelAbsoluteDifference).isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE); } + @Test + public void processData_withTwoWrappedScaleToFitTransformations_producesExpectedOutput() + throws Exception { + String testId = "processData_withTwoWrappedScaleToFitTransformations"; + setUpAndPrepareFirstFrame( + DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO, + new GlEffectWrapper(new ScaleToFitTransformation.Builder().setRotationDegrees(45).build()), + new GlEffectWrapper( + new ScaleToFitTransformation.Builder() + .setScale(/* scaleX= */ 2, /* scaleY= */ 1) + .build())); + Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ROTATE_THEN_SCALE_PNG_ASSET_PATH); + + Bitmap actualBitmap = processFirstFrameAndEnd(); + + BitmapTestUtil.maybeSaveTestBitmapToCacheDirectory( + testId, /* bitmapLabel= */ "actual", actualBitmap); + // TODO(b/207848601): switch to using proper tooling for testing against golden data. + float averagePixelAbsoluteDifference = + BitmapTestUtil.getAveragePixelAbsoluteDifferenceArgb8888( + expectedBitmap, actualBitmap, testId); + assertThat(averagePixelAbsoluteDifference).isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE); + } + @Test public void processData_withManyComposedMatrixTransformations_producesSameOutputAsCombinedTransformation() @@ -325,27 +351,27 @@ private void setUpAndPrepareFirstFrame(float pixelWidthHeightRatio, List { + outputImageReader = + ImageReader.newInstance( + requestedWidth, + requestedHeight, + PixelFormat.RGBA_8888, + /* maxImages= */ 1); + return new SurfaceInfo( + outputImageReader.getSurface(), requestedWidth, requestedHeight); + }, + Transformer.DebugViewProvider.NONE, + /* enableExperimentalHdrEditing= */ false)); frameProcessorChain.registerInputFrame(); // Queue the first video frame from the extractor. @@ -437,4 +463,27 @@ public Matrix getMatrix(long presentationTimeUs) { return checkStateNotNull(adjustedTransformationMatrix); } } + + /** + * Wraps a {@link GlEffect} to prevent the {@link FrameProcessorChain} from detecting its class + * and optimizing it. + * + *

    This ensures that {@link FrameProcessorChain} uses a separate {@link GlTextureProcessor} for + * the wrapped {@link GlEffect} rather than merging it with preceding or subsequent {@link + * GlEffect} instances and applying them in one combined {@link GlTextureProcessor}. + */ + private static final class GlEffectWrapper implements GlEffect { + + private final GlEffect effect; + + public GlEffectWrapper(GlEffect effect) { + this.effect = effect; + } + + @Override + public SingleFrameGlTextureProcessor toGlTextureProcessor(Context context) + throws FrameProcessingException { + return effect.toGlTextureProcessor(context); + } + } } diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainTest.java deleted file mode 100644 index 5dfe72e5b1..0000000000 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainTest.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 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. - */ -package androidx.media3.transformer; - -import static androidx.test.core.app.ApplicationProvider.getApplicationContext; -import static com.google.common.truth.Truth.assertThat; - -import android.content.Context; -import android.util.Size; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.google.common.collect.ImmutableList; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Tests for creating and configuring a {@link FrameProcessorChain}. - * - *

    See {@link FrameProcessorChainPixelTest} for data processing tests. - */ -@RunWith(AndroidJUnit4.class) -public final class FrameProcessorChainTest { - private final AtomicReference frameProcessingException = - new AtomicReference<>(); - - @Test - public void getOutputSize_noOperation_returnsInputSize() throws Exception { - Size inputSize = new Size(200, 100); - FrameProcessorChain frameProcessorChain = - createFrameProcessorChainWithFakeTextureProcessors( - /* pixelWidthHeightRatio= */ 1f, - inputSize, - /* textureProcessorOutputSizes= */ ImmutableList.of()); - - Size outputSize = frameProcessorChain.getOutputSize(); - - assertThat(outputSize).isEqualTo(inputSize); - assertThat(frameProcessingException.get()).isNull(); - } - - @Test - public void getOutputSize_withWidePixels_returnsWiderOutputSize() throws Exception { - Size inputSize = new Size(200, 100); - FrameProcessorChain frameProcessorChain = - createFrameProcessorChainWithFakeTextureProcessors( - /* pixelWidthHeightRatio= */ 2f, - inputSize, - /* textureProcessorOutputSizes= */ ImmutableList.of()); - - Size outputSize = frameProcessorChain.getOutputSize(); - - assertThat(outputSize).isEqualTo(new Size(400, 100)); - assertThat(frameProcessingException.get()).isNull(); - } - - @Test - public void getOutputSize_withTallPixels_returnsTallerOutputSize() throws Exception { - Size inputSize = new Size(200, 100); - FrameProcessorChain frameProcessorChain = - createFrameProcessorChainWithFakeTextureProcessors( - /* pixelWidthHeightRatio= */ .5f, - inputSize, - /* textureProcessorOutputSizes= */ ImmutableList.of()); - - Size outputSize = frameProcessorChain.getOutputSize(); - - assertThat(outputSize).isEqualTo(new Size(200, 200)); - assertThat(frameProcessingException.get()).isNull(); - } - - @Test - public void getOutputSize_withOneTextureProcessor_returnsItsOutputSize() throws Exception { - Size inputSize = new Size(200, 100); - Size textureProcessorOutputSize = new Size(300, 250); - FrameProcessorChain frameProcessorChain = - createFrameProcessorChainWithFakeTextureProcessors( - /* pixelWidthHeightRatio= */ 1f, - inputSize, - /* textureProcessorOutputSizes= */ ImmutableList.of(textureProcessorOutputSize)); - - Size frameProcessorChainOutputSize = frameProcessorChain.getOutputSize(); - - assertThat(frameProcessorChainOutputSize).isEqualTo(textureProcessorOutputSize); - assertThat(frameProcessingException.get()).isNull(); - } - - @Test - public void getOutputSize_withThreeTextureProcessors_returnsLastOutputSize() throws Exception { - Size inputSize = new Size(200, 100); - Size outputSize1 = new Size(300, 250); - Size outputSize2 = new Size(400, 244); - Size outputSize3 = new Size(150, 160); - FrameProcessorChain frameProcessorChain = - createFrameProcessorChainWithFakeTextureProcessors( - /* pixelWidthHeightRatio= */ 1f, - inputSize, - /* textureProcessorOutputSizes= */ ImmutableList.of( - outputSize1, outputSize2, outputSize3)); - - Size frameProcessorChainOutputSize = frameProcessorChain.getOutputSize(); - - assertThat(frameProcessorChainOutputSize).isEqualTo(outputSize3); - assertThat(frameProcessingException.get()).isNull(); - } - - private FrameProcessorChain createFrameProcessorChainWithFakeTextureProcessors( - float pixelWidthHeightRatio, Size inputSize, List textureProcessorOutputSizes) - throws FrameProcessingException { - ImmutableList.Builder effects = new ImmutableList.Builder<>(); - for (Size element : textureProcessorOutputSizes) { - effects.add((Context context) -> new FakeTextureProcessor(element)); - } - return FrameProcessorChain.create( - getApplicationContext(), - /* listener= */ this.frameProcessingException::set, - pixelWidthHeightRatio, - inputSize.getWidth(), - inputSize.getHeight(), - /* streamOffsetUs= */ 0L, - effects.build(), - /* enableExperimentalHdrEditing= */ false); - } - - private static class FakeTextureProcessor extends SingleFrameGlTextureProcessor { - - private final Size outputSize; - - private FakeTextureProcessor(Size outputSize) { - this.outputSize = outputSize; - } - - @Override - public Size configure(int inputWidth, int inputHeight) { - return outputSize; - } - - @Override - public void drawFrame(int inputTexId, long presentationTimeNs) {} - } -} diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java index 1b6af6de70..f7aeb0ca91 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java @@ -18,12 +18,15 @@ import static androidx.media3.transformer.AndroidTestUtil.MP4_ASSET_URI_STRING; import static androidx.media3.transformer.AndroidTestUtil.MP4_ASSET_WITH_INCREASING_TIMESTAMPS_320W_240H_15S_URI_STRING; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; import android.content.Context; import android.net.Uri; +import androidx.media3.common.Format; import androidx.media3.common.MediaItem; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; @@ -34,9 +37,10 @@ @RunWith(AndroidJUnit4.class) public class TransformerEndToEndTest { + private final Context context = ApplicationProvider.getApplicationContext(); + @Test public void videoEditing_completesWithConsistentFrameCount() throws Exception { - Context context = ApplicationProvider.getApplicationContext(); Transformer transformer = new Transformer.Builder(context) .setTransformationRequest( @@ -61,7 +65,6 @@ public void videoEditing_completesWithConsistentFrameCount() throws Exception { @Test public void videoOnly_completesWithConsistentDuration() throws Exception { - Context context = ApplicationProvider.getApplicationContext(); Transformer transformer = new Transformer.Builder(context) .setRemoveAudio(true) @@ -85,7 +88,6 @@ public void videoOnly_completesWithConsistentDuration() throws Exception { @Test public void clippedMedia_completesWithClippedDuration() throws Exception { - Context context = ApplicationProvider.getApplicationContext(); Transformer transformer = new Transformer.Builder(context).build(); long clippingStartMs = 10_000; long clippingEndMs = 11_000; @@ -106,4 +108,65 @@ public void clippedMedia_completesWithClippedDuration() throws Exception { assertThat(result.transformationResult.durationMs).isAtMost(clippingEndMs - clippingStartMs); } + + @Test + public void videoEncoderFormatUnsupported_completesWithError() { + Transformer transformer = + new Transformer.Builder(context) + .setEncoderFactory(new VideoUnsupportedEncoderFactory(context)) + .setRemoveAudio(true) + .build(); + + TransformationException exception = + assertThrows( + TransformationException.class, + () -> + new TransformerAndroidTestRunner.Builder(context, transformer) + .build() + .run( + /* testId= */ "videoEncoderFormatUnsupported_completesWithError", + MediaItem.fromUri(Uri.parse(MP4_ASSET_URI_STRING)))); + + assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class); + assertThat(exception.errorCode) + .isEqualTo(TransformationException.ERROR_CODE_ENCODER_INIT_FAILED); + assertThat(exception).hasMessageThat().contains("video"); + } + + private static final class VideoUnsupportedEncoderFactory implements Codec.EncoderFactory { + + private final Codec.EncoderFactory encoderFactory; + + public VideoUnsupportedEncoderFactory(Context context) { + encoderFactory = new DefaultEncoderFactory(context); + } + + @Override + public Codec createForAudioEncoding(Format format, List allowedMimeTypes) + throws TransformationException { + return encoderFactory.createForAudioEncoding(format, allowedMimeTypes); + } + + @Override + public Codec createForVideoEncoding(Format format, List allowedMimeTypes) + throws TransformationException { + throw TransformationException.createForCodec( + new IllegalArgumentException(), + /* isVideo= */ true, + /* isDecoder= */ false, + format, + /* mediaCodecName= */ null, + TransformationException.ERROR_CODE_ENCODER_INIT_FAILED); + } + + @Override + public boolean audioNeedsEncoding() { + return false; + } + + @Override + public boolean videoNeedsEncoding() { + return true; + } + } } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderCompatibilityTransformation.java b/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderCompatibilityTransformation.java deleted file mode 100644 index 05ff98fe0a..0000000000 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderCompatibilityTransformation.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2022 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 androidx.media3.transformer; - -import static androidx.media3.common.util.Assertions.checkArgument; -import static androidx.media3.common.util.Assertions.checkState; -import static androidx.media3.common.util.Assertions.checkStateNotNull; - -import android.graphics.Matrix; -import android.util.Size; -import androidx.media3.common.C; -import androidx.media3.common.Format; -import org.checkerframework.checker.nullness.qual.MonotonicNonNull; - -/** - * Specifies a {@link Format#rotationDegrees} to apply to each frame for encoder compatibility, if - * needed. - * - *

    Encoders commonly support higher maximum widths than maximum heights. This may rotate the - * decoded frame before encoding, so the encoded frame's width >= height, and set {@link - * Format#rotationDegrees} to ensure the frame is displayed in the correct orientation. - */ -/* package */ class EncoderCompatibilityTransformation implements MatrixTransformation { - // TODO(b/218488308): Allow reconfiguration of the output size, as encoders may not support the - // requested output resolution. - - private int outputRotationDegrees; - private @MonotonicNonNull Matrix transformationMatrix; - - /** Creates a new instance. */ - public EncoderCompatibilityTransformation() { - outputRotationDegrees = C.LENGTH_UNSET; - } - - @Override - public Size configure(int inputWidth, int inputHeight) { - checkArgument(inputWidth > 0, "inputWidth must be positive"); - checkArgument(inputHeight > 0, "inputHeight must be positive"); - - transformationMatrix = new Matrix(); - if (inputHeight > inputWidth) { - outputRotationDegrees = 90; - transformationMatrix.postRotate(outputRotationDegrees); - return new Size(inputHeight, inputWidth); - } else { - outputRotationDegrees = 0; - return new Size(inputWidth, inputHeight); - } - } - - @Override - public Matrix getMatrix(long presentationTimeUs) { - return checkStateNotNull(transformationMatrix, "configure must be called first"); - } - - /** - * Returns {@link Format#rotationDegrees} for the output frame. - * - *

    Return values may be {@code 0} or {@code 90} degrees. - * - *

    Should only be called after {@linkplain #configure(int, int) configuration}. - */ - public int getOutputRotationDegrees() { - checkState( - outputRotationDegrees != C.LENGTH_UNSET, - "configure must be called before getOutputRotationDegrees"); - return outputRotationDegrees; - } -} diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java index 0b2bea5a34..63421d6d65 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java @@ -18,7 +18,6 @@ import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkState; -import static androidx.media3.common.util.Assertions.checkStateNotNull; import static com.google.common.collect.Iterables.getLast; import static java.util.concurrent.TimeUnit.MILLISECONDS; @@ -40,6 +39,7 @@ import androidx.media3.common.util.GlUtil; import androidx.media3.common.util.Log; import androidx.media3.common.util.Util; +import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; @@ -58,8 +58,9 @@ * and is processed on a background thread as it becomes available. All input frames should be * {@linkplain #registerInputFrame() registered} before they are rendered to the input surface. * {@link #getPendingFrameCount()} can be used to check whether there are frames that have not been - * fully processed yet. Output is written to its {@linkplain #setOutputSurface(Surface, int, int, - * SurfaceView) output surface}. + * fully processed yet. Output is written to the provided {@linkplain #create(Context, Listener, + * float, int, int, long, List, SurfaceInfo.Provider, Transformer.DebugViewProvider, boolean) output + * surface}. */ // TODO(b/227625423): Factor out FrameProcessor interface and rename this class to GlFrameProcessor. /* package */ final class FrameProcessorChain { @@ -84,11 +85,18 @@ public interface Listener { * @param inputWidth The input frame width, in pixels. * @param inputHeight The input frame height, in pixels. * @param effects The {@link GlEffect GlEffects} to apply to each frame. + * @param outputSurfaceProvider A {@link SurfaceInfo.Provider} managing the output {@link + * Surface}. + * @param debugViewProvider A {@link Transformer.DebugViewProvider}. * @param enableExperimentalHdrEditing Whether to attempt to process the input as an HDR signal. - * @return A new instance. + * @return A new instance or {@code null}, if no output surface was provided. * @throws FrameProcessingException If reading shader files fails, or an OpenGL error occurs while * creating and configuring the OpenGL components. */ + // TODO(b/227625423): Remove @Nullable here and allow the output surface to be @Nullable until + // the output surface is requested when the output size becomes available asynchronously + // via the final GlTextureProcessor. + @Nullable public static FrameProcessorChain create( Context context, Listener listener, @@ -97,6 +105,8 @@ public static FrameProcessorChain create( int inputHeight, long streamOffsetUs, List effects, + SurfaceInfo.Provider outputSurfaceProvider, + Transformer.DebugViewProvider debugViewProvider, boolean enableExperimentalHdrEditing) throws FrameProcessingException { checkArgument(inputWidth > 0, "inputWidth must be positive"); @@ -104,21 +114,25 @@ public static FrameProcessorChain create( ExecutorService singleThreadExecutorService = Util.newSingleThreadExecutor(THREAD_NAME); + Future> frameProcessorChainFuture = + singleThreadExecutorService.submit( + () -> + Optional.fromNullable( + createOpenGlObjectsAndFrameProcessorChain( + context, + listener, + pixelWidthHeightRatio, + inputWidth, + inputHeight, + streamOffsetUs, + effects, + outputSurfaceProvider, + debugViewProvider, + enableExperimentalHdrEditing, + singleThreadExecutorService))); + try { - return singleThreadExecutorService - .submit( - () -> - createOpenGlObjectsAndFrameProcessorChain( - context, - listener, - pixelWidthHeightRatio, - inputWidth, - inputHeight, - streamOffsetUs, - effects, - enableExperimentalHdrEditing, - singleThreadExecutorService)) - .get(); + return frameProcessorChainFuture.get().orNull(); } catch (ExecutionException e) { throw new FrameProcessingException(e); } catch (InterruptedException e) { @@ -135,6 +149,7 @@ public static FrameProcessorChain create( *

    This method must be executed using the {@code singleThreadExecutorService}. */ @WorkerThread + @Nullable private static FrameProcessorChain createOpenGlObjectsAndFrameProcessorChain( Context context, Listener listener, @@ -143,6 +158,8 @@ private static FrameProcessorChain createOpenGlObjectsAndFrameProcessorChain( int inputHeight, long streamOffsetUs, List effects, + SurfaceInfo.Provider outputSurfaceProvider, + Transformer.DebugViewProvider debugViewProvider, boolean enableExperimentalHdrEditing, ExecutorService singleThreadExecutorService) throws GlUtil.GlException, FrameProcessingException { @@ -164,45 +181,6 @@ private static FrameProcessorChain createOpenGlObjectsAndFrameProcessorChain( GlUtil.focusPlaceholderEglSurface(eglContext, eglDisplay); } - ExternalTextureProcessor externalTextureProcessor = - new ExternalTextureProcessor(context, enableExperimentalHdrEditing); - ImmutableList textureProcessors = - getTextureProcessors(context, externalTextureProcessor, pixelWidthHeightRatio, effects); - - // Initialize texture processors. - int inputExternalTexId = GlUtil.createExternalTexture(); - Size outputSize = externalTextureProcessor.configure(inputWidth, inputHeight); - ImmutableList.Builder intermediateTextures = new ImmutableList.Builder<>(); - for (int i = 1; i < textureProcessors.size(); i++) { - int texId = GlUtil.createTexture(outputSize.getWidth(), outputSize.getHeight()); - int fboId = GlUtil.createFboForTexture(texId); - intermediateTextures.add( - new TextureInfo(texId, fboId, outputSize.getWidth(), outputSize.getHeight())); - SingleFrameGlTextureProcessor textureProcessor = textureProcessors.get(i); - outputSize = textureProcessor.configure(outputSize.getWidth(), outputSize.getHeight()); - } - return new FrameProcessorChain( - eglDisplay, - eglContext, - singleThreadExecutorService, - inputExternalTexId, - streamOffsetUs, - intermediateTextures.build(), - textureProcessors, - outputSize, - listener, - enableExperimentalHdrEditing); - } - - private static ImmutableList getTextureProcessors( - Context context, - ExternalTextureProcessor externalTextureProcessor, - float pixelWidthHeightRatio, - List effects) - throws FrameProcessingException { - ImmutableList.Builder textureProcessors = - new ImmutableList.Builder().add(externalTextureProcessor); - ImmutableList.Builder matrixTransformationListBuilder = new ImmutableList.Builder<>(); // Scale to expand the frame to apply the pixelWidthHeightRatio. @@ -218,6 +196,14 @@ private static ImmutableList getTextureProcessors .build()); } + ExternalTextureProcessor externalTextureProcessor = + new ExternalTextureProcessor(context, enableExperimentalHdrEditing); + int inputExternalTexId = GlUtil.createExternalTexture(); + Size outputSize = externalTextureProcessor.configure(inputWidth, inputHeight); + ImmutableList.Builder intermediateTextures = new ImmutableList.Builder<>(); + ImmutableList.Builder textureProcessors = + new ImmutableList.Builder().add(externalTextureProcessor); + // Combine consecutive GlMatrixTransformations into a single SingleFrameGlTextureProcessor and // convert all other GlEffects to SingleFrameGlTextureProcessors. for (int i = 0; i < effects.size(); i++) { @@ -226,21 +212,100 @@ private static ImmutableList getTextureProcessors matrixTransformationListBuilder.add((GlMatrixTransformation) effect); continue; } + ImmutableList matrixTransformations = matrixTransformationListBuilder.build(); if (!matrixTransformations.isEmpty()) { - textureProcessors.add(new MatrixTransformationProcessor(context, matrixTransformations)); + MatrixTransformationProcessor matrixTransformationProcessor = + new MatrixTransformationProcessor(context, matrixTransformations); + intermediateTextures.add(createTexture(outputSize.getWidth(), outputSize.getHeight())); + outputSize = + matrixTransformationProcessor.configure(outputSize.getWidth(), outputSize.getHeight()); + textureProcessors.add(matrixTransformationProcessor); matrixTransformationListBuilder = new ImmutableList.Builder<>(); } - textureProcessors.add(effect.toGlTextureProcessor(context)); + intermediateTextures.add(createTexture(outputSize.getWidth(), outputSize.getHeight())); + SingleFrameGlTextureProcessor textureProcessor = effect.toGlTextureProcessor(context); + outputSize = textureProcessor.configure(outputSize.getWidth(), outputSize.getHeight()); + textureProcessors.add(textureProcessor); } + + // TODO(b/227625423): Request the output surface during processing when the output size becomes + // available asynchronously via the final GlTextureProcessor instead of requesting it here. + // This will also avoid needing to return null here when no surface is provided. + Size requestedOutputSize = + MatrixUtils.configureAndGetOutputSize( + outputSize.getWidth(), outputSize.getHeight(), matrixTransformationListBuilder.build()); + @Nullable + SurfaceInfo outputSurfaceInfo = + outputSurfaceProvider.getSurfaceInfo( + requestedOutputSize.getWidth(), requestedOutputSize.getHeight()); + if (outputSurfaceInfo == null) { + Log.d(TAG, "No output surface provided."); + return null; + } + + if (outputSurfaceInfo.orientationDegrees != 0) { + matrixTransformationListBuilder.add( + new ScaleToFitTransformation.Builder() + .setRotationDegrees(outputSurfaceInfo.orientationDegrees) + .build()); + } + if (outputSurfaceInfo.width != outputSize.getWidth() + || outputSurfaceInfo.height != outputSize.getHeight()) { + matrixTransformationListBuilder.add( + new Presentation.Builder() + .setAspectRatio( + outputSurfaceInfo.width / (float) outputSurfaceInfo.height, + Presentation.LAYOUT_SCALE_TO_FIT) + .setResolution(outputSurfaceInfo.height) + .build()); + } + + // Convert final list of matrix transformations (including additional transformations for the + // output surface) to a SingleFrameGlTextureProcessors. ImmutableList matrixTransformations = matrixTransformationListBuilder.build(); if (!matrixTransformations.isEmpty()) { - textureProcessors.add(new MatrixTransformationProcessor(context, matrixTransformations)); + intermediateTextures.add(createTexture(outputSize.getWidth(), outputSize.getHeight())); + MatrixTransformationProcessor matrixTransformationProcessor = + new MatrixTransformationProcessor(context, matrixTransformations); + outputSize = + matrixTransformationProcessor.configure(outputSize.getWidth(), outputSize.getHeight()); + checkState(outputSize.getWidth() == outputSurfaceInfo.width); + checkState(outputSize.getHeight() == outputSurfaceInfo.height); + textureProcessors.add(matrixTransformationProcessor); } - return textureProcessors.build(); + EGLSurface outputEglSurface; + if (enableExperimentalHdrEditing) { + // TODO(b/227624622): Don't assume BT.2020 PQ input/output. + outputEglSurface = GlUtil.getEglSurfaceBt2020Pq(eglDisplay, outputSurfaceInfo.surface); + } else { + outputEglSurface = GlUtil.getEglSurface(eglDisplay, outputSurfaceInfo.surface); + } + return new FrameProcessorChain( + eglDisplay, + eglContext, + singleThreadExecutorService, + inputExternalTexId, + streamOffsetUs, + intermediateTextures.build(), + textureProcessors.build(), + outputSurfaceInfo.width, + outputSurfaceInfo.height, + outputEglSurface, + listener, + debugViewProvider.getDebugPreviewSurfaceView( + outputSurfaceInfo.width, outputSurfaceInfo.height), + enableExperimentalHdrEditing); + } + + private static TextureInfo createTexture(int outputWidth, int outputHeight) + throws GlUtil.GlException { + int texId = GlUtil.createTexture(outputWidth, outputHeight); + int fboId = GlUtil.createFboForTexture(texId); + return new TextureInfo(texId, fboId, outputWidth, outputHeight); } private static final String TAG = "FrameProcessorChain"; @@ -282,8 +347,6 @@ private static ImmutableList getTextureProcessors * SingleFrameGlTextureProcessor}. */ private final ImmutableList intermediateTextures; - /** The last texture processor's output {@link Size}. */ - private final Size recommendedOutputSize; private final Listener listener; @@ -293,15 +356,13 @@ private static ImmutableList getTextureProcessors */ private final AtomicBoolean stopProcessing; - private int outputWidth; - private int outputHeight; - private @MonotonicNonNull Surface outputSurface; - + private final int outputWidth; + private final int outputHeight; /** * Wraps the output {@link Surface} that is populated with the output of the final {@link * SingleFrameGlTextureProcessor} for each frame. */ - private @MonotonicNonNull EGLSurface outputEglSurface; + private final EGLSurface outputEglSurface; /** * Wraps a debug {@link SurfaceView} that is populated with the output of the final {@link * SingleFrameGlTextureProcessor} for each frame. @@ -320,8 +381,11 @@ private FrameProcessorChain( long streamOffsetUs, ImmutableList intermediateTextures, ImmutableList textureProcessors, - Size recommendedOutputSize, + int outputWidth, + int outputHeight, + EGLSurface outputEglSurface, Listener listener, + @Nullable SurfaceView debugSurfaceView, boolean enableExperimentalHdrEditing) { checkState(!textureProcessors.isEmpty()); @@ -332,7 +396,9 @@ private FrameProcessorChain( this.streamOffsetUs = streamOffsetUs; this.intermediateTextures = intermediateTextures; this.textureProcessors = textureProcessors; - this.recommendedOutputSize = recommendedOutputSize; + this.outputWidth = outputWidth; + this.outputHeight = outputHeight; + this.outputEglSurface = outputEglSurface; this.listener = listener; this.stopProcessing = new AtomicBoolean(); this.enableExperimentalHdrEditing = enableExperimentalHdrEditing; @@ -342,47 +408,14 @@ private FrameProcessorChain( inputSurfaceTexture = new SurfaceTexture(inputExternalTexId); inputSurface = new Surface(inputSurfaceTexture); textureTransformMatrix = new float[16]; - outputWidth = C.LENGTH_UNSET; - outputHeight = C.LENGTH_UNSET; - } - - /** - * Returns the recommended output size. - * - *

    This is the recommended size to use for the {@linkplain #setOutputSurface(Surface, int, int, - * SurfaceView) output surface}. - */ - public Size getOutputSize() { - return recommendedOutputSize; - } - - /** - * Sets the output {@link Surface}. - * - *

    The recommended output size is given by {@link #getOutputSize()}. Setting a different output - * size may cause poor quality or distortion. - * - * @param outputSurface The output {@link Surface}. - * @param outputWidth The output width, in pixels. - * @param outputHeight The output height, in pixels. - * @param debugSurfaceView Optional debug {@link SurfaceView} to show output. - */ - public void setOutputSurface( - Surface outputSurface, - int outputWidth, - int outputHeight, - @Nullable SurfaceView debugSurfaceView) { - // TODO(b/218488308): Don't override output size for encoder fallback. Instead allow the final - // SingleFrameGlTextureProcessor to be re-configured or append another - // SingleFrameGlTextureProcessor. - this.outputSurface = outputSurface; - this.outputWidth = outputWidth; - this.outputHeight = outputHeight; - if (debugSurfaceView != null) { debugSurfaceViewWrapper = new SurfaceViewWrapper(debugSurfaceView); } + } + /** Returns the input {@link Surface}. */ + public Surface getInputSurface() { + // TODO(b/227625423): Allow input surface to be recreated for input size change. inputSurfaceTexture.setOnFrameAvailableListener( surfaceTexture -> { if (stopProcessing.get()) { @@ -398,10 +431,6 @@ public void setOutputSurface( } } }); - } - - /** Returns the input {@link Surface}. */ - public Surface getInputSurface() { return inputSurface; } @@ -479,16 +508,6 @@ private void processFrame() { try { checkState(Thread.currentThread().getName().equals(THREAD_NAME)); - if (outputEglSurface == null) { - checkStateNotNull(outputSurface); - if (enableExperimentalHdrEditing) { - // TODO(b/227624622): Don't assume BT.2020 PQ input/output. - outputEglSurface = GlUtil.getEglSurfaceBt2020Pq(eglDisplay, outputSurface); - } else { - outputEglSurface = GlUtil.getEglSurface(eglDisplay, outputSurface); - } - } - inputSurfaceTexture.updateTexImage(); long inputFrameTimeNs = inputSurfaceTexture.getTimestamp(); // Correct for the stream offset so processors see original media presentation timestamps. diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/MatrixTransformationProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/MatrixTransformationProcessor.java index 542f79c45e..9f551f0a3b 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/MatrixTransformationProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/MatrixTransformationProcessor.java @@ -15,7 +15,6 @@ */ package androidx.media3.transformer; -import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkState; import android.content.Context; @@ -133,16 +132,7 @@ public MatrixTransformationProcessor( @Override public Size configure(int inputWidth, int inputHeight) { - checkArgument(inputWidth > 0, "inputWidth must be positive"); - checkArgument(inputHeight > 0, "inputHeight must be positive"); - - Size outputSize = new Size(inputWidth, inputHeight); - for (int i = 0; i < matrixTransformations.size(); i++) { - outputSize = - matrixTransformations.get(i).configure(outputSize.getWidth(), outputSize.getHeight()); - } - - return outputSize; + return MatrixUtils.configureAndGetOutputSize(inputWidth, inputHeight, matrixTransformations); } @Override diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/MatrixUtils.java b/libraries/transformer/src/main/java/androidx/media3/transformer/MatrixUtils.java index 206d7cf16d..5a48570e53 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/MatrixUtils.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/MatrixUtils.java @@ -18,6 +18,7 @@ import static androidx.media3.common.util.Assertions.checkArgument; import android.opengl.Matrix; +import android.util.Size; import com.google.common.collect.ImmutableList; import java.util.Arrays; @@ -217,6 +218,26 @@ public static ImmutableList transformPoints( return transformedPoints.build(); } + /** + * Returns the output frame {@link Size} after applying the given list of {@link + * GlMatrixTransformation GlMatrixTransformations} to an input frame with the given size. + */ + public static Size configureAndGetOutputSize( + int inputWidth, + int inputHeight, + ImmutableList matrixTransformations) { + checkArgument(inputWidth > 0, "inputWidth must be positive"); + checkArgument(inputHeight > 0, "inputHeight must be positive"); + + Size outputSize = new Size(inputWidth, inputHeight); + for (int i = 0; i < matrixTransformations.size(); i++) { + outputSize = + matrixTransformations.get(i).configure(outputSize.getWidth(), outputSize.getHeight()); + } + + return outputSize; + } + /** Class only contains static methods. */ private MatrixUtils() {} } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/SurfaceInfo.java b/libraries/transformer/src/main/java/androidx/media3/transformer/SurfaceInfo.java new file mode 100644 index 0000000000..09bc801058 --- /dev/null +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/SurfaceInfo.java @@ -0,0 +1,70 @@ +/* + * Copyright 2022 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 androidx.media3.transformer; + +import static androidx.media3.common.util.Assertions.checkArgument; + +import android.view.Surface; +import androidx.annotation.Nullable; + +/** Immutable value class for a {@link Surface} and supporting information. */ +/* package */ final class SurfaceInfo { + + /** The {@link Surface}. */ + public final Surface surface; + /** The width of frames rendered to the {@link #surface}, in pixels. */ + public final int width; + /** The height of frames rendered to the {@link #surface}, in pixels. */ + public final int height; + /** + * A counter-clockwise rotation to apply to frames before rendering them to the {@link #surface}. + * + *

    Must be 0, 90, 180, or 270 degrees. Default is 0. + */ + public final int orientationDegrees; + + /** Creates a new instance. */ + public SurfaceInfo(Surface surface, int width, int height) { + this(surface, width, height, /* orientationDegrees= */ 0); + } + + /** Creates a new instance. */ + public SurfaceInfo(Surface surface, int width, int height, int orientationDegrees) { + checkArgument( + orientationDegrees == 0 + || orientationDegrees == 90 + || orientationDegrees == 180 + || orientationDegrees == 270, + "orientationDegrees must be 0, 90, 180, or 270"); + this.surface = surface; + this.width = width; + this.height = height; + this.orientationDegrees = orientationDegrees; + } + + /** A provider for a {@link SurfaceInfo} instance. */ + public interface Provider { + /** + * Provides a {@linkplain SurfaceInfo surface} for the requested dimensions. + * + *

    The dimensions given in the provided {@link SurfaceInfo} may differ from the requested + * dimensions. It is up to the caller to transform frames from the requested dimensions to the + * provided dimensions before rendering them to the {@link SurfaceInfo#surface}. + */ + @Nullable + SurfaceInfo getSurfaceInfo(int requestedWidth, int requestedHeight); + } +} diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerVideoRenderer.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerVideoRenderer.java index 6ea492fcb9..b97b14c57e 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerVideoRenderer.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerVideoRenderer.java @@ -106,10 +106,7 @@ protected boolean ensureConfigured() throws TransformationException { encoderFactory, muxerWrapper.getSupportedSampleMimeTypes(getTrackType()), fallbackListener, - /* frameProcessorChainListener= */ exception -> - asyncErrorListener.onTransformationException( - TransformationException.createForFrameProcessorChain( - exception, TransformationException.ERROR_CODE_GL_PROCESSING_FAILED)), + asyncErrorListener, debugViewProvider); } if (transformationRequest.flattenForSlowMotion) { diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java index 83ea088026..32d5c628aa 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java @@ -17,25 +17,29 @@ package androidx.media3.transformer; import static androidx.media3.common.util.Assertions.checkNotNull; +import static androidx.media3.common.util.Assertions.checkStateNotNull; import android.content.Context; import android.media.MediaCodec; -import android.util.Size; +import android.view.Surface; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import androidx.media3.common.C; import androidx.media3.common.Format; import androidx.media3.common.util.Util; import androidx.media3.decoder.DecoderInputBuffer; import com.google.common.collect.ImmutableList; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.dataflow.qual.Pure; /** * Pipeline to decode video samples, apply transformations on the raw samples, and re-encode them. */ /* package */ final class VideoTranscodingSamplePipeline implements SamplePipeline { - private final int outputRotationDegrees; private final int maxPendingFrameCount; private final DecoderInputBuffer decoderInputBuffer; @@ -44,7 +48,7 @@ private final FrameProcessorChain frameProcessorChain; - private final Codec encoder; + private final EncoderWrapper encoderWrapper; private final DecoderInputBuffer encoderOutputBuffer; private boolean signaledEndOfStreamToEncoder; @@ -59,7 +63,7 @@ public VideoTranscodingSamplePipeline( Codec.EncoderFactory encoderFactory, List allowedOutputMimeTypes, FallbackListener fallbackListener, - FrameProcessorChain.Listener frameProcessorChainListener, + Transformer.AsyncErrorListener asyncErrorListener, Transformer.DebugViewProvider debugViewProvider) throws TransformationException { decoderInputBuffer = @@ -89,54 +93,45 @@ public VideoTranscodingSamplePipeline( effectsListBuilder.add( new Presentation.Builder().setResolution(transformationRequest.outputHeight).build()); } - EncoderCompatibilityTransformation encoderCompatibilityTransformation = - new EncoderCompatibilityTransformation(); - effectsListBuilder.add(encoderCompatibilityTransformation); + + AtomicReference encoderInitializationException = + new AtomicReference<>(); + encoderWrapper = + new EncoderWrapper( + encoderFactory, + inputFormat, + allowedOutputMimeTypes, + transformationRequest, + fallbackListener, + encoderInitializationException); + + @Nullable FrameProcessorChain frameProcessorChain; try { frameProcessorChain = FrameProcessorChain.create( context, - frameProcessorChainListener, + /* listener= */ exception -> + asyncErrorListener.onTransformationException( + TransformationException.createForFrameProcessorChain( + exception, TransformationException.ERROR_CODE_GL_PROCESSING_FAILED)), inputFormat.pixelWidthHeightRatio, /* inputWidth= */ decodedWidth, /* inputHeight= */ decodedHeight, streamOffsetUs, effectsListBuilder.build(), + /* outputSurfaceProvider= */ encoderWrapper, + debugViewProvider, transformationRequest.enableHdrEditing); } catch (FrameProcessingException e) { throw TransformationException.createForFrameProcessorChain( e, TransformationException.ERROR_CODE_GL_INIT_FAILED); } - Size requestedEncoderSize = frameProcessorChain.getOutputSize(); - outputRotationDegrees = encoderCompatibilityTransformation.getOutputRotationDegrees(); - - Format requestedEncoderFormat = - new Format.Builder() - .setWidth(requestedEncoderSize.getWidth()) - .setHeight(requestedEncoderSize.getHeight()) - .setRotationDegrees(0) - .setFrameRate(inputFormat.frameRate) - .setSampleMimeType( - transformationRequest.videoMimeType != null - ? transformationRequest.videoMimeType - : inputFormat.sampleMimeType) - .build(); - - encoder = encoderFactory.createForVideoEncoding(requestedEncoderFormat, allowedOutputMimeTypes); - Format encoderSupportedFormat = encoder.getConfigurationFormat(); - fallbackListener.onTransformationRequestFinalized( - createFallbackTransformationRequest( - transformationRequest, - /* hasOutputFormatRotation= */ outputRotationDegrees == 0, - requestedEncoderFormat, - encoderSupportedFormat)); - frameProcessorChain.setOutputSurface( - /* outputSurface= */ encoder.getInputSurface(), - /* outputWidth= */ encoderSupportedFormat.width, - /* outputHeight= */ encoderSupportedFormat.height, - debugViewProvider.getDebugPreviewSurfaceView( - encoderSupportedFormat.width, encoderSupportedFormat.height)); + if (frameProcessorChain == null) { + // Failed to create FrameProcessorChain because the encoder could not provide a surface. + throw checkStateNotNull(encoderInitializationException.get()); + } + this.frameProcessorChain = frameProcessorChain; decoder = decoderFactory.createForVideoDecoding( @@ -164,7 +159,7 @@ public void queueInputBuffer() throws TransformationException { public boolean processData() throws TransformationException { if (frameProcessorChain.isEnded()) { if (!signaledEndOfStreamToEncoder) { - encoder.signalEndOfInputStream(); + encoderWrapper.signalEndOfInputStream(); signaledEndOfStreamToEncoder = true; } return false; @@ -187,20 +182,17 @@ public boolean processData() throws TransformationException { @Override @Nullable public Format getOutputFormat() throws TransformationException { - @Nullable Format format = encoder.getOutputFormat(); - return format == null - ? null - : format.buildUpon().setRotationDegrees(outputRotationDegrees).build(); + return encoderWrapper.getOutputFormat(); } @Override @Nullable public DecoderInputBuffer getOutputBuffer() throws TransformationException { - encoderOutputBuffer.data = encoder.getOutputBuffer(); + encoderOutputBuffer.data = encoderWrapper.getOutputBuffer(); if (encoderOutputBuffer.data == null) { return null; } - MediaCodec.BufferInfo bufferInfo = checkNotNull(encoder.getOutputBufferInfo()); + MediaCodec.BufferInfo bufferInfo = checkNotNull(encoderWrapper.getOutputBufferInfo()); encoderOutputBuffer.timeUs = bufferInfo.presentationTimeUs; encoderOutputBuffer.setFlags(bufferInfo.flags); return encoderOutputBuffer; @@ -208,19 +200,19 @@ public DecoderInputBuffer getOutputBuffer() throws TransformationException { @Override public void releaseOutputBuffer() throws TransformationException { - encoder.releaseOutputBuffer(/* render= */ false); + encoderWrapper.releaseOutputBuffer(/* render= */ false); } @Override public boolean isEnded() { - return encoder.isEnded(); + return encoderWrapper.isEnded(); } @Override public void release() { frameProcessorChain.release(); decoder.release(); - encoder.release(); + encoderWrapper.release(); } /** @@ -292,4 +284,151 @@ private boolean isDecodeOnlyBuffer(long presentationTimeUs) { } return false; } + + /** + * Wraps an {@linkplain Codec encoder} and provides its input {@link Surface}. + * + *

    The encoder is created once the {@link Surface} is {@linkplain #getSurfaceInfo(int, int) + * requested}. If it is {@linkplain #getSurfaceInfo(int, int) requested} again with different + * dimensions, the same encoder is used and the provided dimensions stay fixed. + */ + @VisibleForTesting + /* package */ static final class EncoderWrapper implements SurfaceInfo.Provider { + + private final Codec.EncoderFactory encoderFactory; + private final Format inputFormat; + private final List allowedOutputMimeTypes; + private final TransformationRequest transformationRequest; + private final FallbackListener fallbackListener; + private final AtomicReference encoderInitializationException; + + private @MonotonicNonNull SurfaceInfo encoderSurfaceInfo; + + private volatile @MonotonicNonNull Codec encoder; + private volatile int outputRotationDegrees; + private volatile boolean releaseEncoder; + + public EncoderWrapper( + Codec.EncoderFactory encoderFactory, + Format inputFormat, + List allowedOutputMimeTypes, + TransformationRequest transformationRequest, + FallbackListener fallbackListener, + AtomicReference encoderInitializationException) { + + this.encoderFactory = encoderFactory; + this.inputFormat = inputFormat; + this.allowedOutputMimeTypes = allowedOutputMimeTypes; + this.transformationRequest = transformationRequest; + this.fallbackListener = fallbackListener; + this.encoderInitializationException = encoderInitializationException; + } + + @Override + @Nullable + public SurfaceInfo getSurfaceInfo(int requestedWidth, int requestedHeight) { + if (releaseEncoder) { + return null; + } + if (encoderSurfaceInfo != null) { + return encoderSurfaceInfo; + } + + // Encoders commonly support higher maximum widths than maximum heights. This may rotate the + // frame before encoding, so the encoded frame's width >= height, and sets + // rotationDegrees in the output Format to ensure the frame is displayed in the correct + // orientation. + boolean flipOrientation = requestedWidth < requestedHeight; + if (flipOrientation) { + int temp = requestedWidth; + requestedWidth = requestedHeight; + requestedHeight = temp; + outputRotationDegrees = 90; + } + + Format requestedEncoderFormat = + new Format.Builder() + .setWidth(requestedWidth) + .setHeight(requestedHeight) + .setRotationDegrees(0) + .setFrameRate(inputFormat.frameRate) + .setSampleMimeType( + transformationRequest.videoMimeType != null + ? transformationRequest.videoMimeType + : inputFormat.sampleMimeType) + .build(); + + try { + encoder = + encoderFactory.createForVideoEncoding(requestedEncoderFormat, allowedOutputMimeTypes); + } catch (TransformationException e) { + encoderInitializationException.set(e); + return null; + } + Format encoderSupportedFormat = encoder.getConfigurationFormat(); + fallbackListener.onTransformationRequestFinalized( + createFallbackTransformationRequest( + transformationRequest, + /* hasOutputFormatRotation= */ flipOrientation, + requestedEncoderFormat, + encoderSupportedFormat)); + + encoderSurfaceInfo = + new SurfaceInfo( + encoder.getInputSurface(), + encoderSupportedFormat.width, + encoderSupportedFormat.height, + outputRotationDegrees); + + if (releaseEncoder) { + encoder.release(); + } + return encoderSurfaceInfo; + } + + public void signalEndOfInputStream() throws TransformationException { + if (encoder != null) { + encoder.signalEndOfInputStream(); + } + } + + @Nullable + public Format getOutputFormat() throws TransformationException { + if (encoder == null) { + return null; + } + @Nullable Format outputFormat = encoder.getOutputFormat(); + if (outputFormat != null && outputRotationDegrees != 0) { + outputFormat = outputFormat.buildUpon().setRotationDegrees(outputRotationDegrees).build(); + } + return outputFormat; + } + + @Nullable + public ByteBuffer getOutputBuffer() throws TransformationException { + return encoder != null ? encoder.getOutputBuffer() : null; + } + + @Nullable + public MediaCodec.BufferInfo getOutputBufferInfo() throws TransformationException { + return encoder != null ? encoder.getOutputBufferInfo() : null; + } + + public void releaseOutputBuffer(boolean render) throws TransformationException { + if (encoder != null) { + encoder.releaseOutputBuffer(render); + } + } + + public boolean isEnded() { + return encoder != null && encoder.isEnded(); + } + + public void release() { + if (encoder != null) { + encoder.release(); + } + releaseEncoder = true; + } + } } diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/EncoderCompatibilityTransformationTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/EncoderCompatibilityTransformationTest.java deleted file mode 100644 index 3eb95008d1..0000000000 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/EncoderCompatibilityTransformationTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2022 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 androidx.media3.transformer; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertThrows; - -import android.util.Size; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** Unit tests for {@link EncoderCompatibilityTransformation}. */ -@RunWith(AndroidJUnit4.class) -public final class EncoderCompatibilityTransformationTest { - @Test - public void configure_noEditsLandscape_leavesOrientationUnchanged() { - int inputWidth = 200; - int inputHeight = 150; - EncoderCompatibilityTransformation encoderCompatibilityTransformation = - new EncoderCompatibilityTransformation(); - - Size outputSize = encoderCompatibilityTransformation.configure(inputWidth, inputHeight); - - assertThat(encoderCompatibilityTransformation.getOutputRotationDegrees()).isEqualTo(0); - assertThat(outputSize.getWidth()).isEqualTo(inputWidth); - assertThat(outputSize.getHeight()).isEqualTo(inputHeight); - } - - @Test - public void configure_noEditsSquare_leavesOrientationUnchanged() { - int inputWidth = 150; - int inputHeight = 150; - EncoderCompatibilityTransformation encoderCompatibilityTransformation = - new EncoderCompatibilityTransformation(); - - Size outputSize = encoderCompatibilityTransformation.configure(inputWidth, inputHeight); - - assertThat(encoderCompatibilityTransformation.getOutputRotationDegrees()).isEqualTo(0); - assertThat(outputSize.getWidth()).isEqualTo(inputWidth); - assertThat(outputSize.getHeight()).isEqualTo(inputHeight); - } - - @Test - public void configure_noEditsPortrait_flipsOrientation() { - int inputWidth = 150; - int inputHeight = 200; - EncoderCompatibilityTransformation encoderCompatibilityTransformation = - new EncoderCompatibilityTransformation(); - - Size outputSize = encoderCompatibilityTransformation.configure(inputWidth, inputHeight); - - assertThat(encoderCompatibilityTransformation.getOutputRotationDegrees()).isEqualTo(90); - assertThat(outputSize.getWidth()).isEqualTo(inputHeight); - assertThat(outputSize.getHeight()).isEqualTo(inputWidth); - } - - @Test - public void getOutputRotationDegreesBeforeConfigure_throwsIllegalStateException() { - EncoderCompatibilityTransformation encoderCompatibilityTransformation = - new EncoderCompatibilityTransformation(); - - // configure not called before getOutputRotationDegrees. - assertThrows( - IllegalStateException.class, encoderCompatibilityTransformation::getOutputRotationDegrees); - } -} diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/VideoEncoderWrapperTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/VideoEncoderWrapperTest.java new file mode 100644 index 0000000000..e7e7c5e4f6 --- /dev/null +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/VideoEncoderWrapperTest.java @@ -0,0 +1,146 @@ +/* + * Copyright 2022 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 androidx.media3.transformer; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.net.Uri; +import android.os.Looper; +import androidx.media3.common.C; +import androidx.media3.common.Format; +import androidx.media3.common.MediaItem; +import androidx.media3.common.util.Clock; +import androidx.media3.common.util.ListenerSet; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.common.collect.ImmutableList; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Unit tests for {@link VideoTranscodingSamplePipeline.EncoderWrapper}. */ +@RunWith(AndroidJUnit4.class) +public final class VideoEncoderWrapperTest { + private final TransformationRequest emptyTransformationRequest = + new TransformationRequest.Builder().build(); + private final FakeVideoEncoderFactory fakeEncoderFactory = new FakeVideoEncoderFactory(); + private final FallbackListener fallbackListener = + new FallbackListener( + MediaItem.fromUri(Uri.EMPTY), + new ListenerSet<>(Looper.myLooper(), Clock.DEFAULT, (listener, flags) -> {}), + emptyTransformationRequest); + private final VideoTranscodingSamplePipeline.EncoderWrapper encoderWrapper = + new VideoTranscodingSamplePipeline.EncoderWrapper( + fakeEncoderFactory, + /* inputFormat= */ new Format.Builder().build(), + /* allowedOutputMimeTypes= */ ImmutableList.of(), + emptyTransformationRequest, + fallbackListener, + new AtomicReference<>()); + + @Before + public void registerTrack() { + fallbackListener.registerTrack(); + } + + @Test + public void getSurfaceInfo_landscape_leavesOrientationUnchanged() { + int inputWidth = 200; + int inputHeight = 150; + + SurfaceInfo surfaceInfo = encoderWrapper.getSurfaceInfo(inputWidth, inputHeight); + + assertThat(surfaceInfo.orientationDegrees).isEqualTo(0); + assertThat(surfaceInfo.width).isEqualTo(inputWidth); + assertThat(surfaceInfo.height).isEqualTo(inputHeight); + } + + @Test + public void getSurfaceInfo_square_leavesOrientationUnchanged() { + int inputWidth = 150; + int inputHeight = 150; + + SurfaceInfo surfaceInfo = encoderWrapper.getSurfaceInfo(inputWidth, inputHeight); + + assertThat(surfaceInfo.orientationDegrees).isEqualTo(0); + assertThat(surfaceInfo.width).isEqualTo(inputWidth); + assertThat(surfaceInfo.height).isEqualTo(inputHeight); + } + + @Test + public void getSurfaceInfo_portrait_flipsOrientation() { + int inputWidth = 150; + int inputHeight = 200; + + SurfaceInfo surfaceInfo = encoderWrapper.getSurfaceInfo(inputWidth, inputHeight); + + assertThat(surfaceInfo.orientationDegrees).isEqualTo(90); + assertThat(surfaceInfo.width).isEqualTo(inputHeight); + assertThat(surfaceInfo.height).isEqualTo(inputWidth); + } + + @Test + public void getSurfaceInfo_withEncoderFallback_usesFallbackResolution() { + int inputWidth = 200; + int inputHeight = 150; + int fallbackWidth = 100; + int fallbackHeight = 75; + fakeEncoderFactory.setFallbackResolution(fallbackWidth, fallbackHeight); + + SurfaceInfo surfaceInfo = encoderWrapper.getSurfaceInfo(inputWidth, inputHeight); + + assertThat(surfaceInfo.orientationDegrees).isEqualTo(0); + assertThat(surfaceInfo.width).isEqualTo(fallbackWidth); + assertThat(surfaceInfo.height).isEqualTo(fallbackHeight); + } + + private static class FakeVideoEncoderFactory implements Codec.EncoderFactory { + + private int fallbackWidth; + private int fallbackHeight; + + public FakeVideoEncoderFactory() { + fallbackWidth = C.LENGTH_UNSET; + fallbackHeight = C.LENGTH_UNSET; + } + + public void setFallbackResolution(int fallbackWidth, int fallbackHeight) { + this.fallbackWidth = fallbackWidth; + this.fallbackHeight = fallbackHeight; + } + + @Override + public Codec createForAudioEncoding(Format format, List allowedMimeTypes) { + throw new UnsupportedOperationException(); + } + + @Override + public Codec createForVideoEncoding(Format format, List allowedMimeTypes) { + Codec mockEncoder = mock(Codec.class); + if (fallbackWidth != C.LENGTH_UNSET) { + format = format.buildUpon().setWidth(fallbackWidth).build(); + } + if (fallbackHeight != C.LENGTH_UNSET) { + format = format.buildUpon().setHeight(fallbackHeight).build(); + } + when(mockEncoder.getConfigurationFormat()).thenReturn(format); + return mockEncoder; + } + } +} From fdfca880195da2ca5e5d0ef002feb8144009384c Mon Sep 17 00:00:00 2001 From: hschlueter Date: Wed, 15 Jun 2022 13:27:35 +0000 Subject: [PATCH 16/73] Replace FrameProcessorChain#isEnded with listener method. PiperOrigin-RevId: 455114693 --- .../FrameProcessorChainPixelTest.java | 17 ++++++-- .../transformer/FrameProcessorChain.java | 40 ++++++++++++++----- .../VideoTranscodingSamplePipeline.java | 26 +++++++----- 3 files changed, 59 insertions(+), 24 deletions(-) diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java index 7cec1d5a6a..0820049cb9 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java @@ -89,9 +89,10 @@ public final class FrameProcessorChainPixelTest { private final AtomicReference frameProcessingException = new AtomicReference<>(); + private @MonotonicNonNull MediaFormat mediaFormat; private @MonotonicNonNull FrameProcessorChain frameProcessorChain; private volatile @MonotonicNonNull ImageReader outputImageReader; - private @MonotonicNonNull MediaFormat mediaFormat; + private volatile boolean frameProcessingEnded; @After public void release() { @@ -354,7 +355,17 @@ private void setUpAndPrepareFirstFrame(float pixelWidthHeightRatio, ListThis listener is only called from the {@link FrameProcessorChain}'s background thread. */ public interface Listener { - /** Called when an exception occurs during asynchronous frame processing. */ + /** + * Called when an exception occurs during asynchronous frame processing. + * + *

    If an error occurred, consuming and producing further frames will not work as expected and + * the {@link FrameProcessorChain} should be released. + */ void onFrameProcessingError(FrameProcessingException exception); + + /** Called after the frame processor has produced its final output frame. */ + void onFrameProcessingEnded(); } /** @@ -454,22 +462,24 @@ public int getPendingFrameCount() { return pendingFrameCount.get(); } - /** Informs the {@code FrameProcessorChain} that no further input frames should be accepted. */ + /** + * Informs the {@code FrameProcessorChain} that no further input frames should be accepted. + * + * @throws IllegalStateException If called more than once. + */ public void signalEndOfInputStream() { + checkState(!inputStreamEnded); inputStreamEnded = true; - } - - /** Returns whether all frames have been processed. */ - public boolean isEnded() { - return inputStreamEnded && getPendingFrameCount() == 0; + futures.add(singleThreadExecutorService.submit(this::signalEndOfOutputStream)); } /** * Releases all resources. * - *

    If the frame processor chain is released before it has {@linkplain #isEnded() ended}, it - * will attempt to cancel processing any input frames that have already become available. Input - * frames that become available after release are ignored. + *

    If the frame processor chain is released before it has {@linkplain + * Listener#onFrameProcessingEnded() ended}, it will attempt to cancel processing any input frames + * that have already become available. Input frames that become available after release are + * ignored. * *

    This method blocks until all OpenGL resources are released or releasing times out. */ @@ -563,6 +573,16 @@ private void processFrame() { } } + /** Calls {@link Listener#onFrameProcessingEnded()} once no more frames are pending. */ + @WorkerThread + private void signalEndOfOutputStream() { + if (getPendingFrameCount() == 0) { + listener.onFrameProcessingEnded(); + } else { + futures.add(singleThreadExecutorService.submit(this::signalEndOfOutputStream)); + } + } + /** * Releases the {@link SingleFrameGlTextureProcessor SingleFrameGlTextureProcessors} and destroys * the OpenGL context. diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java index 32d5c628aa..6c05da6c51 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java @@ -51,8 +51,6 @@ private final EncoderWrapper encoderWrapper; private final DecoderInputBuffer encoderOutputBuffer; - private boolean signaledEndOfStreamToEncoder; - public VideoTranscodingSamplePipeline( Context context, Format inputFormat, @@ -110,10 +108,23 @@ public VideoTranscodingSamplePipeline( frameProcessorChain = FrameProcessorChain.create( context, - /* listener= */ exception -> + new FrameProcessorChain.Listener() { + @Override + public void onFrameProcessingError(FrameProcessingException exception) { asyncErrorListener.onTransformationException( TransformationException.createForFrameProcessorChain( - exception, TransformationException.ERROR_CODE_GL_PROCESSING_FAILED)), + exception, TransformationException.ERROR_CODE_GL_PROCESSING_FAILED)); + } + + @Override + public void onFrameProcessingEnded() { + try { + encoderWrapper.signalEndOfInputStream(); + } catch (TransformationException exception) { + asyncErrorListener.onTransformationException(exception); + } + } + }, inputFormat.pixelWidthHeightRatio, /* inputWidth= */ decodedWidth, /* inputHeight= */ decodedHeight, @@ -157,13 +168,6 @@ public void queueInputBuffer() throws TransformationException { @Override public boolean processData() throws TransformationException { - if (frameProcessorChain.isEnded()) { - if (!signaledEndOfStreamToEncoder) { - encoderWrapper.signalEndOfInputStream(); - signaledEndOfStreamToEncoder = true; - } - return false; - } if (decoder.isEnded()) { return false; } From 21d4e8581701e12743626f49823a667d9f05ed68 Mon Sep 17 00:00:00 2001 From: tonihei Date: Wed, 15 Jun 2022 13:32:25 +0000 Subject: [PATCH 17/73] Remove setMediaUri/onSetMediaUri This code path is now completely redundant as the same effect can be achieved by using player.setMediaItem. #minor-release PiperOrigin-RevId: 455115567 --- RELEASENOTES.md | 4 + .../media3/session/IMediaSession.aidl | 1 - .../media3/session/MediaConstants.java | 94 ------------------- .../media3/session/MediaController.java | 33 ------- .../session/MediaControllerImplBase.java | 10 -- .../session/MediaControllerImplLegacy.java | 7 -- .../androidx/media3/session/MediaSession.java | 18 ---- .../media3/session/MediaSessionImpl.java | 5 - .../media3/session/MediaSessionStub.java | 17 ---- .../media3/session/SessionCommand.java | 6 +- .../common/IRemoteMediaController.aidl | 1 - .../session/MediaControllerListenerTest.java | 4 +- .../media3/session/MediaControllerTest.java | 4 +- .../session/MediaSessionCallbackTest.java | 38 -------- .../session/MediaSessionPermissionTest.java | 50 +--------- .../MediaControllerProviderService.java | 11 --- .../media3/session/RemoteMediaController.java | 5 - 17 files changed, 12 insertions(+), 296 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 4f154ce7f1..e050b7090d 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -181,6 +181,10 @@ `MediaSession.Callback.onAddMediaItems` instead of `onSetMediaUri`. * Support `setMediaItems(s)` methods when `MediaController` connects to a legacy media session. + * Remove `MediaController.setMediaUri` and + `MediaSession.Callback.onSetMediaUri`. The same functionality can be + achieved by using `MediaController.setMediaItem` and + `MediaSession.Callback.onAddMediaItems`. * Data sources: * Rename `DummyDataSource` to `PlaceholderDataSource`. * Workaround OkHttp interrupt handling. diff --git a/libraries/session/src/main/aidl/androidx/media3/session/IMediaSession.aidl b/libraries/session/src/main/aidl/androidx/media3/session/IMediaSession.aidl index ac88efa63a..e62fa1bc7e 100644 --- a/libraries/session/src/main/aidl/androidx/media3/session/IMediaSession.aidl +++ b/libraries/session/src/main/aidl/androidx/media3/session/IMediaSession.aidl @@ -32,7 +32,6 @@ oneway interface IMediaSession { // Id < 3000 is reserved to avoid potential collision with media2 1.x. - void setMediaUri(IMediaController caller, int seq, in Uri uri, in Bundle extras) = 3000; void setVolume(IMediaController caller, int seq, float volume) = 3001; void setDeviceVolume(IMediaController caller, int seq, int volume) = 3002; void increaseDeviceVolume(IMediaController caller, int seq) = 3003; diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaConstants.java b/libraries/session/src/main/java/androidx/media3/session/MediaConstants.java index be791c9cc5..ce5e4142d0 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaConstants.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaConstants.java @@ -15,7 +15,6 @@ */ package androidx.media3.session; -import android.net.Uri; import android.os.Bundle; import android.support.v4.media.session.MediaControllerCompat; import android.support.v4.media.session.MediaSessionCompat; @@ -25,99 +24,6 @@ /** Constants that can be shared between media session and controller. */ public final class MediaConstants { - /** - * A {@link Uri} scheme used in a media uri. - * - * @see MediaController#setMediaUri - * @see MediaSession.Callback#onSetMediaUri - */ - public static final String MEDIA_URI_SCHEME = "androidx"; - - /** - * A {@link Uri} authority used in a media uri. - * - * @see MediaController#setMediaUri - * @see MediaSession.Callback#onSetMediaUri - */ - public static final String MEDIA_URI_AUTHORITY = "media3-session"; - - /** - * A {@link Uri} path used by {@code - * android.support.v4.media.session.MediaControllerCompat.TransportControls#playFromMediaId}. - * - * @see MediaController#setMediaUri - * @see MediaSession.Callback#onSetMediaUri - */ - public static final String MEDIA_URI_PATH_PLAY_FROM_MEDIA_ID = "playFromMediaId"; - - /** - * A {@link Uri} path used by {@code - * android.support.v4.media.session.MediaControllerCompat.TransportControls#playFromSearch}. - * - * @see MediaController#setMediaUri - * @see MediaSession.Callback#onSetMediaUri - */ - public static final String MEDIA_URI_PATH_PLAY_FROM_SEARCH = "playFromSearch"; - - /** - * A {@link Uri} path used by {@link - * android.support.v4.media.session.MediaControllerCompat.TransportControls#prepareFromMediaId}. - * - * @see MediaController#setMediaUri - * @see MediaSession.Callback#onSetMediaUri - */ - public static final String MEDIA_URI_PATH_PREPARE_FROM_MEDIA_ID = "prepareFromMediaId"; - - /** - * A {@link Uri} path used by {@link - * android.support.v4.media.session.MediaControllerCompat.TransportControls#prepareFromSearch}. - * - * @see MediaController#setMediaUri - * @see MediaSession.Callback#onSetMediaUri - */ - public static final String MEDIA_URI_PATH_PREPARE_FROM_SEARCH = "prepareFromSearch"; - - /** - * A {@link Uri} path for encoding how the uri will be translated when connected to {@link - * android.support.v4.media.session.MediaSessionCompat}. - * - * @see MediaController#setMediaUri - */ - public static final String MEDIA_URI_PATH_SET_MEDIA_URI = "setMediaUri"; - - // From scheme to path, plus path delimiter - /* package */ static final String MEDIA_URI_SET_MEDIA_URI_PREFIX = - new Uri.Builder() - .scheme(MEDIA_URI_SCHEME) - .authority(MEDIA_URI_AUTHORITY) - .path(MEDIA_URI_PATH_SET_MEDIA_URI) - .build() - .toString() - + "?"; - - /** - * A {@link Uri} query for media id. - * - * @see MediaSession.Callback#onSetMediaUri - * @see MediaController#setMediaUri - */ - public static final String MEDIA_URI_QUERY_ID = "id"; - - /** - * A {@link Uri} query for search query. - * - * @see MediaSession.Callback#onSetMediaUri - * @see MediaController#setMediaUri - */ - public static final String MEDIA_URI_QUERY_QUERY = "query"; - - /** - * A {@link Uri} query for media uri. - * - * @see MediaController#setMediaUri - */ - public static final String MEDIA_URI_QUERY_URI = "uri"; - /** * Bundle key to indicate a preference that a region of space for the skip to next control should * always be blocked out in the UI, even when the seek to next standard action is not supported. diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaController.java b/libraries/session/src/main/java/androidx/media3/session/MediaController.java index 624a0faa7a..e47fc02253 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaController.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaController.java @@ -24,7 +24,6 @@ import android.app.PendingIntent; import android.content.Context; -import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -985,36 +984,6 @@ public void setMediaItems(List mediaItems, int startIndex, long start impl.setMediaItems(mediaItems, startIndex, startPositionMs); } - /** - * Requests that the connected {@link MediaSession} sets a specific {@link Uri} for playback. Use - * this, or {@link #setMediaItems} to specify which item(s) to play. - * - *

    This can be called multiple times in any states. This would override previous call of this, - * or {@link #setMediaItems}. - * - *

    The {@link Player.Listener#onTimelineChanged} and/or {@link - * Player.Listener#onMediaItemTransition} would be called when it's completed. - * - *

    Returned {@link ListenableFuture} will return {@link SessionResult#RESULT_SUCCESS} when it's - * handled together with {@link #prepare} or {@link #play}. If this API is called multiple times - * without prepare or play, then {@link SessionResult#RESULT_INFO_SKIPPED} will be returned for - * previous calls. - * - * @param uri The uri of the item(s) to play. - * @param extras A {@link Bundle} to send extra information. May be empty. - * @return A {@link ListenableFuture} of {@link SessionResult} representing the pending - * completion. - */ - public ListenableFuture setMediaUri(Uri uri, Bundle extras) { - verifyApplicationThread(); - checkNotNull(uri); - checkNotNull(extras); - if (isConnected()) { - return impl.setMediaUri(uri, extras); - } - return createDisconnectedFuture(); - } - @Override public void setPlaylistMetadata(MediaMetadata playlistMetadata) { verifyApplicationThread(); @@ -1928,8 +1897,6 @@ interface MediaControllerImpl { void setMediaItems(List mediaItems, int startIndex, long startPositionMs); - ListenableFuture setMediaUri(Uri uri, Bundle extras); - void setPlaylistMetadata(MediaMetadata playlistMetadata); MediaMetadata getPlaylistMetadata(); diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java index 6eb5406951..c80e832a97 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java @@ -76,7 +76,6 @@ import static androidx.media3.session.MediaUtils.calculateBufferedPercentage; import static androidx.media3.session.MediaUtils.intersect; import static androidx.media3.session.SessionCommand.COMMAND_CODE_CUSTOM; -import static androidx.media3.session.SessionCommand.COMMAND_CODE_SESSION_SET_MEDIA_URI; import static androidx.media3.session.SessionCommand.COMMAND_CODE_SESSION_SET_RATING; import static androidx.media3.session.SessionResult.RESULT_ERROR_PERMISSION_DENIED; import static androidx.media3.session.SessionResult.RESULT_ERROR_SESSION_DISCONNECTED; @@ -93,7 +92,6 @@ import android.content.ServiceConnection; import android.graphics.Rect; import android.graphics.SurfaceTexture; -import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -934,14 +932,6 @@ public void setMediaItems(List mediaItems, int startIndex, long start mediaItems, startIndex, startPositionMs, /* resetToDefaultPosition= */ false); } - @Override - public ListenableFuture setMediaUri(Uri uri, Bundle extras) { - return dispatchRemoteSessionTaskWithSessionCommand( - COMMAND_CODE_SESSION_SET_MEDIA_URI, - (RemoteSessionTask) - (iSession, seq) -> iSession.setMediaUri(controllerStub, seq, uri, extras)); - } - @Override public void setPlaylistMetadata(MediaMetadata playlistMetadata) { if (!isPlayerCommandAvailable(COMMAND_SET_MEDIA_ITEMS_METADATA)) { diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java index 05fb4335cf..6a2dc56c1f 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java @@ -44,7 +44,6 @@ import android.app.PendingIntent; import android.content.Context; import android.media.AudioManager; -import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.ResultReceiver; @@ -667,12 +666,6 @@ public void setMediaItems(List mediaItems, int startIndex, long start } } - @Override - public ListenableFuture setMediaUri(Uri uri, Bundle extras) { - Log.w(TAG, "Session doesn't support setMediaUri"); - return Futures.immediateCancelledFuture(); - } - @Override public void setPlaylistMetadata(MediaMetadata playlistMetadata) { Log.w(TAG, "Session doesn't support setting playlist metadata"); diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSession.java b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java index 71edff1179..d170298328 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSession.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java @@ -940,24 +940,6 @@ default ListenableFuture onSetRating( return Futures.immediateFuture(new SessionResult(RESULT_ERROR_NOT_SUPPORTED)); } - /** - * Called when a controller requested to set the specific media item(s) represented by a URI - * through {@link MediaController#setMediaUri(Uri, Bundle)}. - * - *

    The implementation should create proper {@link MediaItem media item(s)} for the given - * {@code uri} and call {@link Player#setMediaItems}. - * - * @param session The session for this event. - * @param controller The controller information. - * @param uri The uri. - * @param extras An extra {@link Bundle}. May be empty. - * @return A result code. - */ - default @SessionResult.Code int onSetMediaUri( - MediaSession session, ControllerInfo controller, Uri uri, Bundle extras) { - return RESULT_ERROR_NOT_SUPPORTED; - } - /** * Called when a controller sent a custom command through {@link * MediaController#sendCustomCommand(SessionCommand, Bundle)}. diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java b/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java index 57d1533c9a..6fce21470f 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java @@ -442,11 +442,6 @@ public void onDisconnectedOnHandler(ControllerInfo controller) { callback.onDisconnected(instance, controller); } - public @SessionResult.Code int onSetMediaUriOnHandler( - ControllerInfo controller, Uri uri, Bundle extras) { - return callback.onSetMediaUri(instance, controller, uri, extras); - } - public @SessionResult.Code int onPlayerCommandRequestOnHandler( ControllerInfo controller, @Player.Command int playerCommand) { return callback.onPlayerCommandRequest(instance, controller, playerCommand); diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java b/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java index 109d6afc1d..1b5e554298 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionStub.java @@ -49,10 +49,8 @@ import static androidx.media3.session.SessionCommand.COMMAND_CODE_LIBRARY_SEARCH; import static androidx.media3.session.SessionCommand.COMMAND_CODE_LIBRARY_SUBSCRIBE; import static androidx.media3.session.SessionCommand.COMMAND_CODE_LIBRARY_UNSUBSCRIBE; -import static androidx.media3.session.SessionCommand.COMMAND_CODE_SESSION_SET_MEDIA_URI; import static androidx.media3.session.SessionCommand.COMMAND_CODE_SESSION_SET_RATING; -import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; @@ -1013,21 +1011,6 @@ public void setMediaItemsWithStartIndex( player.setMediaItems(mediaItems, startIndex, startPositionMs))); } - @Override - public void setMediaUri( - @Nullable IMediaController caller, int seq, @Nullable Uri uri, @Nullable Bundle extras) { - if (caller == null || uri == null || extras == null) { - return; - } - dispatchSessionTaskWithSessionCommand( - caller, - seq, - COMMAND_CODE_SESSION_SET_MEDIA_URI, - (sessionImpl, controller) -> - new SessionResult(sessionImpl.onSetMediaUriOnHandler(controller, uri, extras)), - MediaSessionStub::sendSessionResult); - } - @Override public void setPlaylistMetadata( @Nullable IMediaController caller, int seq, @Nullable Bundle playlistMetadataBundle) { diff --git a/libraries/session/src/main/java/androidx/media3/session/SessionCommand.java b/libraries/session/src/main/java/androidx/media3/session/SessionCommand.java index 256a92c3ff..35ef391826 100644 --- a/libraries/session/src/main/java/androidx/media3/session/SessionCommand.java +++ b/libraries/session/src/main/java/androidx/media3/session/SessionCommand.java @@ -49,7 +49,6 @@ public final class SessionCommand implements Bundleable { @Target(TYPE_USE) @IntDef({ COMMAND_CODE_CUSTOM, - COMMAND_CODE_SESSION_SET_MEDIA_URI, COMMAND_CODE_SESSION_SET_RATING, COMMAND_CODE_LIBRARY_GET_LIBRARY_ROOT, COMMAND_CODE_LIBRARY_SUBSCRIBE, @@ -74,11 +73,8 @@ public final class SessionCommand implements Bundleable { /** Command code for {@link MediaController#setRating(String, Rating)}. */ public static final int COMMAND_CODE_SESSION_SET_RATING = 40010; - /** Command code for {@link MediaController#setMediaUri}. */ - public static final int COMMAND_CODE_SESSION_SET_MEDIA_URI = 40011; - /* package */ static final ImmutableList SESSION_COMMANDS = - ImmutableList.of(COMMAND_CODE_SESSION_SET_RATING, COMMAND_CODE_SESSION_SET_MEDIA_URI); + ImmutableList.of(COMMAND_CODE_SESSION_SET_RATING); ////////////////////////////////////////////////////////////////////////////////////////////////// // Library commands (i.e. commands to {@link MediaLibrarySession#MediaLibrarySessionCallback}) diff --git a/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaController.aidl b/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaController.aidl index cf4e6ebf6c..0f611d7be5 100644 --- a/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaController.aidl +++ b/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaController.aidl @@ -52,7 +52,6 @@ interface IRemoteMediaController { void setMediaItemsWithStartIndex( String controllerId, in List mediaItems, int startIndex, long startPositionMs); void createAndSetFakeMediaItems(String controllerId, int size); - void setMediaUri(String controllerId, in Uri uri, in Bundle extras); void setPlaylistMetadata(String controllerId, in Bundle playlistMetadata); void addMediaItem(String controllerId, in Bundle mediaitem); void addMediaItemWithIndex(String controllerId, int index, in Bundle mediaitem); diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerTest.java index d4a597f410..2cfaf781b6 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerTest.java @@ -24,6 +24,7 @@ import static androidx.media3.session.MediaTestUtils.createTimeline; import static androidx.media3.session.MediaUtils.createPlayerCommandsWith; import static androidx.media3.session.MediaUtils.createPlayerCommandsWithout; +import static androidx.media3.session.SessionCommand.COMMAND_CODE_SESSION_SET_RATING; import static androidx.media3.session.SessionResult.RESULT_SUCCESS; import static androidx.media3.test.session.common.CommonConstants.DEFAULT_TEST_NAME; import static androidx.media3.test.session.common.CommonConstants.MOCK_MEDIA3_LIBRARY_SERVICE; @@ -1535,7 +1536,8 @@ public void onAvailableSessionCommandsChanged( SessionCommands commands = new SessionCommands.Builder() - .add(new SessionCommand(SessionCommand.COMMAND_CODE_SESSION_SET_RATING)) + .addAllSessionCommands() + .remove(COMMAND_CODE_SESSION_SET_RATING) .build(); remoteSession.setAvailableCommands(commands, Player.Commands.EMPTY); diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerTest.java index f24070f94f..80b893e9d3 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerTest.java @@ -943,7 +943,7 @@ public void isCommandAvailable_withUnavailableCommand_returnsFalse() throws Exce public void isSessionCommandAvailable_withAvailablePredefinedSessionCommand_returnsTrue() throws Exception { @SessionCommand.CommandCode - int sessionCommandCode = SessionCommand.COMMAND_CODE_SESSION_SET_MEDIA_URI; + int sessionCommandCode = SessionCommand.COMMAND_CODE_SESSION_SET_RATING; SessionCommand sessionCommand = new SessionCommand(sessionCommandCode); Bundle tokenExtras = new Bundle(); tokenExtras.putBundle( @@ -969,7 +969,7 @@ public void isSessionCommandAvailable_withAvailablePredefinedSessionCommand_retu public void isSessionCommandAvailable_withUnavailablePredefinedSessionCommand_returnsFalse() throws Exception { @SessionCommand.CommandCode - int sessionCommandCode = SessionCommand.COMMAND_CODE_SESSION_SET_MEDIA_URI; + int sessionCommandCode = SessionCommand.COMMAND_CODE_SESSION_SET_RATING; SessionCommand sessionCommand = new SessionCommand(sessionCommandCode); Bundle tokenExtras = new Bundle(); tokenExtras.putBundle( diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionCallbackTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionCallbackTest.java index b079208c35..d145758606 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionCallbackTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionCallbackTest.java @@ -27,7 +27,6 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import android.content.Context; -import android.net.Uri; import android.os.Bundle; import android.text.TextUtils; import androidx.media3.common.MediaItem; @@ -239,43 +238,6 @@ public ListenableFuture onCustomCommand( assertThat(TestUtils.equals(testArgs, argsRef.get())).isTrue(); } - @Test - public void onSetMediaUri() throws Exception { - Uri testUri = Uri.parse("foo://boo"); - Bundle testExtras = TestUtils.createTestBundle(); - CountDownLatch latch = new CountDownLatch(1); - AtomicReference uriRef = new AtomicReference<>(); - AtomicReference extrasRef = new AtomicReference<>(); - MediaSession.Callback callback = - new MediaSession.Callback() { - @Override - public int onSetMediaUri( - MediaSession session, ControllerInfo controller, Uri uri, Bundle extras) { - if (!TextUtils.equals(controller.getPackageName(), SUPPORT_APP_PACKAGE_NAME)) { - return RESULT_INFO_SKIPPED; - } - - uriRef.set(uri); - extrasRef.set(extras); - latch.countDown(); - return RESULT_SUCCESS; - } - }; - MediaSession session = - sessionTestRule.ensureReleaseAfterTest( - new MediaSession.Builder(context, player) - .setCallback(callback) - .setId("testOnSetMediaUri") - .build()); - RemoteMediaController controller = - controllerTestRule.createRemoteController(session.getToken()); - - controller.setMediaUri(testUri, testExtras); - assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); - assertThat(uriRef.get()).isEqualTo(testUri); - assertThat(TestUtils.equals(testExtras, extrasRef.get())).isTrue(); - } - @Test public void onSetRatingWithMediaId() throws Exception { float ratingValue = 3.5f; diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionPermissionTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionPermissionTest.java index 80a61f8d12..8d82012e32 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionPermissionTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionPermissionTest.java @@ -27,7 +27,6 @@ import static androidx.media3.common.Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS; import static androidx.media3.session.MediaUtils.createPlayerCommandsWith; import static androidx.media3.session.MediaUtils.createPlayerCommandsWithout; -import static androidx.media3.session.SessionCommand.COMMAND_CODE_SESSION_SET_MEDIA_URI; import static androidx.media3.session.SessionCommand.COMMAND_CODE_SESSION_SET_RATING; import static androidx.media3.session.SessionResult.RESULT_SUCCESS; import static androidx.media3.test.session.common.CommonConstants.SUPPORT_APP_PACKAGE_NAME; @@ -37,7 +36,6 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import android.content.Context; -import android.net.Uri; import android.os.Bundle; import android.text.TextUtils; import androidx.media3.common.MediaItem; @@ -51,7 +49,6 @@ import androidx.media3.test.session.common.MainLooperTestRule; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.ext.truth.os.BundleSubject; import androidx.test.filters.LargeTest; import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.Futures; @@ -184,31 +181,6 @@ public void setDeviceMuted() throws Exception { testOnCommandRequest(COMMAND_SET_DEVICE_VOLUME, controller -> controller.setDeviceMuted(true)); } - @Test - public void setMediaUri() throws Exception { - Uri uri = Uri.parse("media://uri"); - createSession( - createSessionCommandsWith(new SessionCommand(COMMAND_CODE_SESSION_SET_MEDIA_URI)), - Player.Commands.EMPTY); - controllerTestRule - .createRemoteController(session.getToken()) - .setMediaUri(uri, /* extras= */ Bundle.EMPTY); - - assertThat(callback.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); - assertThat(callback.onSetMediaUriCalled).isTrue(); - assertThat(callback.uri).isEqualTo(uri); - BundleSubject.assertThat(callback.extras).isEmpty(); - - createSession( - createSessionCommandsWith(new SessionCommand(COMMAND_CODE_SESSION_SET_RATING)), - Player.Commands.EMPTY); - controllerTestRule - .createRemoteController(session.getToken()) - .setMediaUri(uri, /* extras= */ Bundle.EMPTY); - assertThat(callback.countDownLatch.await(NO_RESPONSE_TIMEOUT_MS, MILLISECONDS)).isFalse(); - assertThat(callback.onSetMediaUriCalled).isFalse(); - } - @Test public void setRating() throws Exception { String mediaId = "testSetRating"; @@ -223,9 +195,7 @@ public void setRating() throws Exception { assertThat(callback.mediaId).isEqualTo(mediaId); assertThat(callback.rating).isEqualTo(rating); - createSession( - createSessionCommandsWith(new SessionCommand(COMMAND_CODE_SESSION_SET_MEDIA_URI)), - Player.Commands.EMPTY); + createSession(SessionCommands.EMPTY, Player.Commands.EMPTY); controllerTestRule.createRemoteController(session.getToken()).setRating(mediaId, rating); assertThat(callback.countDownLatch.await(NO_RESPONSE_TIMEOUT_MS, MILLISECONDS)).isFalse(); assertThat(callback.onSetRatingCalled).isFalse(); @@ -248,9 +218,7 @@ public void changingPermissionForSessionCommandWithSetAvailableCommands() throws // Change allowed commands. session.setAvailableCommands( - getTestControllerInfo(), - createSessionCommandsWith(new SessionCommand(COMMAND_CODE_SESSION_SET_MEDIA_URI)), - Player.Commands.EMPTY); + getTestControllerInfo(), SessionCommands.EMPTY, Player.Commands.EMPTY); controller.setRating(mediaId, rating); assertThat(callback.countDownLatch.await(NO_RESPONSE_TIMEOUT_MS, MILLISECONDS)).isFalse(); @@ -315,12 +283,10 @@ private static class MySessionCallback implements MediaSession.Callback { public @Player.Command int command; public String mediaId; - public Uri uri; public Bundle extras; public Rating rating; public boolean onCommandRequestCalled; - public boolean onSetMediaUriCalled; public boolean onSetRatingCalled; public MySessionCallback() { @@ -333,7 +299,6 @@ public void reset() { mediaId = null; onCommandRequestCalled = false; - onSetMediaUriCalled = false; onSetRatingCalled = false; } @@ -347,17 +312,6 @@ public int onPlayerCommandRequest( return MediaSession.Callback.super.onPlayerCommandRequest(session, controller, command); } - @Override - public int onSetMediaUri( - MediaSession session, ControllerInfo controller, Uri uri, Bundle extras) { - assertThat(TextUtils.equals(SUPPORT_APP_PACKAGE_NAME, controller.getPackageName())).isTrue(); - onSetMediaUriCalled = true; - this.uri = uri; - this.extras = extras; - countDownLatch.countDown(); - return RESULT_SUCCESS; - } - @Override public ListenableFuture onSetRating( MediaSession session, ControllerInfo controller, String mediaId, Rating rating) { diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/MediaControllerProviderService.java b/libraries/test_session_current/src/main/java/androidx/media3/session/MediaControllerProviderService.java index 2912517f69..7d263e9c71 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/MediaControllerProviderService.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/MediaControllerProviderService.java @@ -23,7 +23,6 @@ import android.content.Context; import android.content.Intent; import android.media.AudioManager; -import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; @@ -366,16 +365,6 @@ public void createAndSetFakeMediaItems(String controllerId, int size) throws Rem }); } - @Override - @SuppressWarnings("FutureReturnValueIgnored") - public void setMediaUri(String controllerId, Uri uri, Bundle extras) throws RemoteException { - runOnHandler( - () -> { - MediaController controller = mediaControllerMap.get(controllerId); - controller.setMediaUri(uri, extras); - }); - } - @Override public void setPlaylistMetadata(String controllerId, Bundle playlistMetadataBundle) throws RemoteException { diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaController.java b/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaController.java index 4c34fded93..6b0449ce25 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaController.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaController.java @@ -25,7 +25,6 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; @@ -180,10 +179,6 @@ public void createAndSetFakeMediaItems(int size) throws RemoteException { binder.createAndSetFakeMediaItems(controllerId, size); } - public void setMediaUri(Uri uri, Bundle extras) throws RemoteException { - binder.setMediaUri(controllerId, uri, extras); - } - public void setPlaylistMetadata(MediaMetadata playlistMetadata) throws RemoteException { binder.setPlaylistMetadata(controllerId, playlistMetadata.toBundle()); } From 99cdc515ae13b2fecba620102a854fc6b312c3c9 Mon Sep 17 00:00:00 2001 From: olly Date: Wed, 15 Jun 2022 14:08:00 +0000 Subject: [PATCH 18/73] Cleanup: Remove unnecessary self-refs in Util PiperOrigin-RevId: 455121899 --- .../androidx/media3/common/util/Util.java | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/libraries/common/src/main/java/androidx/media3/common/util/Util.java b/libraries/common/src/main/java/androidx/media3/common/util/Util.java index 659d9ba3d8..bb0c2205ee 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/Util.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/Util.java @@ -200,7 +200,7 @@ public static byte[] toByteArray(InputStream inputStream) throws IOException { @UnstableApi @Nullable public static ComponentName startForegroundService(Context context, Intent intent) { - if (Util.SDK_INT >= 26) { + if (SDK_INT >= 26) { return context.startForegroundService(intent); } else { return context.startService(intent); @@ -216,7 +216,7 @@ public static ComponentName startForegroundService(Context context, Intent inten * @return Whether a permission request was made. */ public static boolean maybeRequestReadExternalStoragePermission(Activity activity, Uri... uris) { - if (Util.SDK_INT < 23) { + if (SDK_INT < 23) { return false; } for (Uri uri : uris) { @@ -239,7 +239,7 @@ public static boolean maybeRequestReadExternalStoragePermission(Activity activit */ public static boolean maybeRequestReadExternalStoragePermission( Activity activity, MediaItem... mediaItems) { - if (Util.SDK_INT < 23) { + if (SDK_INT < 23) { return false; } for (MediaItem mediaItem : mediaItems) { @@ -261,7 +261,7 @@ public static boolean maybeRequestReadExternalStoragePermission( } private static boolean maybeRequestReadExternalStoragePermission(Activity activity, Uri uri) { - return Util.SDK_INT >= 23 && (isLocalFileUri(uri) || isMediaStoreExternalContentUri(uri)) + return SDK_INT >= 23 && (isLocalFileUri(uri) || isMediaStoreExternalContentUri(uri)) ? requestExternalStoragePermission(activity) : false; } @@ -287,7 +287,7 @@ private static boolean isMediaStoreExternalContentUri(Uri uri) { * @return Whether it may be possible to load the URIs of the given media items. */ public static boolean checkCleartextTrafficPermitted(MediaItem... mediaItems) { - if (Util.SDK_INT < 24) { + if (SDK_INT < 24) { // We assume cleartext traffic is permitted. return true; } @@ -672,7 +672,7 @@ public static String getLocaleLanguageTag(Locale locale) { normalizedTag = language; } normalizedTag = Ascii.toLowerCase(normalizedTag); - String mainLanguage = Util.splitAtFirst(normalizedTag, "-")[0]; + String mainLanguage = splitAtFirst(normalizedTag, "-")[0]; if (languageTagReplacementMap == null) { languageTagReplacementMap = createIsoLanguageReplacementMap(); } @@ -1734,9 +1734,9 @@ public static int getAudioTrackChannelConfig(int channelCount) { case 7: return AudioFormat.CHANNEL_OUT_5POINT1 | AudioFormat.CHANNEL_OUT_BACK_CENTER; case 8: - if (Util.SDK_INT >= 23) { + if (SDK_INT >= 23) { return AudioFormat.CHANNEL_OUT_7POINT1_SURROUND; - } else if (Util.SDK_INT >= 21) { + } else if (SDK_INT >= 21) { // Equal to AudioFormat.CHANNEL_OUT_7POINT1_SURROUND, which is hidden before Android M. return AudioFormat.CHANNEL_OUT_5POINT1 | AudioFormat.CHANNEL_OUT_SIDE_LEFT @@ -2027,7 +2027,7 @@ public static UUID getDrmUuid(String drmScheme) { public static @ContentType int inferContentTypeForUriAndMimeType( Uri uri, @Nullable String mimeType) { if (mimeType == null) { - return Util.inferContentType(uri); + return inferContentType(uri); } switch (mimeType) { case MimeTypes.APPLICATION_MPD: @@ -2367,7 +2367,7 @@ public static String[] getSystemLanguageCodes() { /** Returns the default {@link Locale.Category#DISPLAY DISPLAY} {@link Locale}. */ @UnstableApi public static Locale getDefaultDisplayLocale() { - return Util.SDK_INT >= 24 ? Locale.getDefault(Locale.Category.DISPLAY) : Locale.getDefault(); + return SDK_INT >= 24 ? Locale.getDefault(Locale.Category.DISPLAY) : Locale.getDefault(); } /** @@ -2442,7 +2442,7 @@ public static boolean isTv(Context context) { */ @UnstableApi public static boolean isAutomotive(Context context) { - return Util.SDK_INT >= 23 + return SDK_INT >= 23 && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); } @@ -2461,7 +2461,7 @@ public static boolean isAutomotive(Context context) { @UnstableApi public static Point getCurrentDisplayModeSize(Context context) { @Nullable Display defaultDisplay = null; - if (Util.SDK_INT >= 17) { + if (SDK_INT >= 17) { @Nullable DisplayManager displayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); @@ -2510,7 +2510,7 @@ public static Point getCurrentDisplayModeSize(Context context, Display display) // vendor.display-size instead. @Nullable String displaySize = - Util.SDK_INT < 28 + SDK_INT < 28 ? getSystemProperty("sys.display-size") : getSystemProperty("vendor.display-size"); // If we managed to read the display size, attempt to parse it. @@ -2531,17 +2531,17 @@ public static Point getCurrentDisplayModeSize(Context context, Display display) } // Sony Android TVs advertise support for 4k output via a system feature. - if ("Sony".equals(Util.MANUFACTURER) - && Util.MODEL.startsWith("BRAVIA") + if ("Sony".equals(MANUFACTURER) + && MODEL.startsWith("BRAVIA") && context.getPackageManager().hasSystemFeature("com.sony.dtv.hardware.panel.qfhd")) { return new Point(3840, 2160); } } Point displaySize = new Point(); - if (Util.SDK_INT >= 23) { + if (SDK_INT >= 23) { getDisplaySizeV23(display, displaySize); - } else if (Util.SDK_INT >= 17) { + } else if (SDK_INT >= 17) { getDisplaySizeV17(display, displaySize); } else { getDisplaySizeV16(display, displaySize); @@ -2768,7 +2768,7 @@ private static String[] getSystemLocales() { @RequiresApi(24) private static String[] getSystemLocalesV24(Configuration config) { - return Util.split(config.getLocales().toLanguageTags(), ","); + return split(config.getLocales().toLanguageTags(), ","); } @RequiresApi(21) From 958105c91c931fa942ce7de4e8311589eca76564 Mon Sep 17 00:00:00 2001 From: bachinger Date: Wed, 15 Jun 2022 14:48:34 +0000 Subject: [PATCH 19/73] Updating translations #minor-release PiperOrigin-RevId: 455128997 --- .../src/main/res/values-af/strings.xml | 1 + .../src/main/res/values-am/strings.xml | 1 + .../src/main/res/values-ar/strings.xml | 1 + .../src/main/res/values-az/strings.xml | 1 + .../src/main/res/values-b+sr+Latn/strings.xml | 1 + .../src/main/res/values-be/strings.xml | 1 + .../src/main/res/values-bg/strings.xml | 1 + .../src/main/res/values-bn/strings.xml | 1 + .../src/main/res/values-bs/strings.xml | 1 + .../src/main/res/values-ca/strings.xml | 1 + .../src/main/res/values-cs/strings.xml | 1 + .../src/main/res/values-da/strings.xml | 1 + .../src/main/res/values-de/strings.xml | 1 + .../src/main/res/values-el/strings.xml | 1 + .../src/main/res/values-en-rAU/strings.xml | 1 + .../src/main/res/values-en-rGB/strings.xml | 1 + .../src/main/res/values-en-rIN/strings.xml | 1 + .../src/main/res/values-es-rUS/strings.xml | 1 + .../src/main/res/values-es/strings.xml | 1 + .../src/main/res/values-et/strings.xml | 1 + .../src/main/res/values-eu/strings.xml | 1 + .../src/main/res/values-fa/strings.xml | 1 + .../src/main/res/values-fi/strings.xml | 1 + .../src/main/res/values-fr-rCA/strings.xml | 1 + .../src/main/res/values-fr/strings.xml | 1 + .../src/main/res/values-gl/strings.xml | 1 + .../src/main/res/values-gu/strings.xml | 1 + .../src/main/res/values-hi/strings.xml | 1 + .../src/main/res/values-hr/strings.xml | 1 + .../src/main/res/values-hu/strings.xml | 1 + .../src/main/res/values-hy/strings.xml | 1 + .../src/main/res/values-in/strings.xml | 1 + .../src/main/res/values-is/strings.xml | 1 + .../src/main/res/values-it/strings.xml | 1 + .../src/main/res/values-iw/strings.xml | 1 + .../src/main/res/values-ja/strings.xml | 1 + .../src/main/res/values-ka/strings.xml | 1 + .../src/main/res/values-kk/strings.xml | 1 + .../src/main/res/values-km/strings.xml | 1 + .../src/main/res/values-kn/strings.xml | 1 + .../src/main/res/values-ko/strings.xml | 1 + .../src/main/res/values-ky/strings.xml | 1 + .../src/main/res/values-lo/strings.xml | 1 + .../src/main/res/values-lt/strings.xml | 1 + .../src/main/res/values-lv/strings.xml | 1 + .../src/main/res/values-mk/strings.xml | 1 + .../src/main/res/values-ml/strings.xml | 1 + .../src/main/res/values-mn/strings.xml | 1 + .../src/main/res/values-mr/strings.xml | 1 + .../src/main/res/values-ms/strings.xml | 1 + .../src/main/res/values-my/strings.xml | 1 + .../src/main/res/values-nb/strings.xml | 1 + .../src/main/res/values-ne/strings.xml | 1 + .../src/main/res/values-nl/strings.xml | 1 + .../src/main/res/values-pa/strings.xml | 1 + .../src/main/res/values-pl/strings.xml | 1 + .../src/main/res/values-pt-rPT/strings.xml | 1 + .../src/main/res/values-pt/strings.xml | 1 + .../src/main/res/values-ro/strings.xml | 1 + .../src/main/res/values-ru/strings.xml | 1 + .../src/main/res/values-si/strings.xml | 1 + .../src/main/res/values-sk/strings.xml | 1 + .../src/main/res/values-sl/strings.xml | 1 + .../src/main/res/values-sq/strings.xml | 1 + .../src/main/res/values-sr/strings.xml | 1 + .../src/main/res/values-sv/strings.xml | 1 + .../src/main/res/values-sw/strings.xml | 1 + .../src/main/res/values-ta/strings.xml | 1 + .../src/main/res/values-te/strings.xml | 1 + .../src/main/res/values-th/strings.xml | 1 + .../src/main/res/values-tl/strings.xml | 1 + .../src/main/res/values-tr/strings.xml | 1 + .../src/main/res/values-uk/strings.xml | 1 + .../src/main/res/values-ur/strings.xml | 1 + .../src/main/res/values-uz/strings.xml | 1 + .../src/main/res/values-vi/strings.xml | 1 + .../src/main/res/values-zh-rCN/strings.xml | 1 + .../src/main/res/values-zh-rHK/strings.xml | 1 + .../src/main/res/values-zh-rTW/strings.xml | 1 + .../src/main/res/values-zu/strings.xml | 1 + .../ui/src/main/res/values-af/strings.xml | 10 ++++---- .../ui/src/main/res/values-am/strings.xml | 10 ++++---- .../ui/src/main/res/values-ar/strings.xml | 10 ++++---- .../ui/src/main/res/values-az/strings.xml | 10 ++++---- .../src/main/res/values-b+sr+Latn/strings.xml | 10 ++++---- .../ui/src/main/res/values-be/strings.xml | 12 +++++----- .../ui/src/main/res/values-bg/strings.xml | 10 ++++---- .../ui/src/main/res/values-bn/strings.xml | 10 ++++---- .../ui/src/main/res/values-bs/strings.xml | 10 ++++---- .../ui/src/main/res/values-ca/strings.xml | 10 ++++---- .../ui/src/main/res/values-cs/strings.xml | 10 ++++---- .../ui/src/main/res/values-da/strings.xml | 10 ++++---- .../ui/src/main/res/values-de/strings.xml | 10 ++++---- .../ui/src/main/res/values-el/strings.xml | 10 ++++---- .../ui/src/main/res/values-en-rAU/strings.xml | 10 ++++---- .../ui/src/main/res/values-en-rGB/strings.xml | 10 ++++---- .../ui/src/main/res/values-en-rIN/strings.xml | 10 ++++---- .../ui/src/main/res/values-es-rUS/strings.xml | 10 ++++---- .../ui/src/main/res/values-es/strings.xml | 10 ++++---- .../ui/src/main/res/values-et/strings.xml | 10 ++++---- .../ui/src/main/res/values-eu/strings.xml | 10 ++++---- .../ui/src/main/res/values-fa/strings.xml | 10 ++++---- .../ui/src/main/res/values-fi/strings.xml | 10 ++++---- .../ui/src/main/res/values-fr-rCA/strings.xml | 12 ++++------ .../ui/src/main/res/values-fr/strings.xml | 12 ++++------ .../ui/src/main/res/values-gl/strings.xml | 10 ++++---- .../ui/src/main/res/values-gu/strings.xml | 10 ++++---- .../ui/src/main/res/values-hi/strings.xml | 10 ++++---- .../ui/src/main/res/values-hr/strings.xml | 10 ++++---- .../ui/src/main/res/values-hu/strings.xml | 10 ++++---- .../ui/src/main/res/values-hy/strings.xml | 10 ++++---- .../ui/src/main/res/values-in/strings.xml | 10 ++++---- .../ui/src/main/res/values-is/strings.xml | 10 ++++---- .../ui/src/main/res/values-it/strings.xml | 14 +++++------ .../ui/src/main/res/values-iw/strings.xml | 24 +++++++++++++++---- .../ui/src/main/res/values-ja/strings.xml | 10 ++++---- .../ui/src/main/res/values-ka/strings.xml | 10 ++++---- .../ui/src/main/res/values-kk/strings.xml | 10 ++++---- .../ui/src/main/res/values-km/strings.xml | 10 ++++---- .../ui/src/main/res/values-kn/strings.xml | 12 +++++----- .../ui/src/main/res/values-ko/strings.xml | 10 ++++---- .../ui/src/main/res/values-ky/strings.xml | 10 ++++---- .../ui/src/main/res/values-lo/strings.xml | 10 ++++---- .../ui/src/main/res/values-lt/strings.xml | 10 ++++---- .../ui/src/main/res/values-lv/strings.xml | 10 ++++---- .../ui/src/main/res/values-mk/strings.xml | 10 ++++---- .../ui/src/main/res/values-ml/strings.xml | 10 ++++---- .../ui/src/main/res/values-mn/strings.xml | 10 ++++---- .../ui/src/main/res/values-mr/strings.xml | 10 ++++---- .../ui/src/main/res/values-ms/strings.xml | 10 ++++---- .../ui/src/main/res/values-my/strings.xml | 10 ++++---- .../ui/src/main/res/values-nb/strings.xml | 10 ++++---- .../ui/src/main/res/values-ne/strings.xml | 10 ++++---- .../ui/src/main/res/values-nl/strings.xml | 10 ++++---- .../ui/src/main/res/values-pa/strings.xml | 10 ++++---- .../ui/src/main/res/values-pl/strings.xml | 10 ++++---- .../ui/src/main/res/values-pt-rPT/strings.xml | 14 +++++------ .../ui/src/main/res/values-pt/strings.xml | 10 ++++---- .../ui/src/main/res/values-ro/strings.xml | 10 ++++---- .../ui/src/main/res/values-ru/strings.xml | 10 ++++---- .../ui/src/main/res/values-si/strings.xml | 10 ++++---- .../ui/src/main/res/values-sk/strings.xml | 10 ++++---- .../ui/src/main/res/values-sl/strings.xml | 10 ++++---- .../ui/src/main/res/values-sq/strings.xml | 10 ++++---- .../ui/src/main/res/values-sr/strings.xml | 10 ++++---- .../ui/src/main/res/values-sv/strings.xml | 10 ++++---- .../ui/src/main/res/values-sw/strings.xml | 10 ++++---- .../ui/src/main/res/values-ta/strings.xml | 14 +++++------ .../ui/src/main/res/values-te/strings.xml | 10 ++++---- .../ui/src/main/res/values-th/strings.xml | 10 ++++---- .../ui/src/main/res/values-tl/strings.xml | 10 ++++---- .../ui/src/main/res/values-tr/strings.xml | 10 ++++---- .../ui/src/main/res/values-uk/strings.xml | 10 ++++---- .../ui/src/main/res/values-ur/strings.xml | 10 ++++---- .../ui/src/main/res/values-uz/strings.xml | 10 ++++---- .../ui/src/main/res/values-vi/strings.xml | 10 ++++---- .../ui/src/main/res/values-zh-rCN/strings.xml | 10 ++++---- .../ui/src/main/res/values-zh-rHK/strings.xml | 10 ++++---- .../ui/src/main/res/values-zh-rTW/strings.xml | 10 ++++---- .../ui/src/main/res/values-zu/strings.xml | 10 ++++---- 160 files changed, 502 insertions(+), 412 deletions(-) diff --git a/libraries/session/src/main/res/values-af/strings.xml b/libraries/session/src/main/res/values-af/strings.xml index ac138172bf..8ff1ece685 100755 --- a/libraries/session/src/main/res/values-af/strings.xml +++ b/libraries/session/src/main/res/values-af/strings.xml @@ -21,4 +21,5 @@ Soek tot by volgende item Soek agtertoe Soek vorentoe + Stawing word vereis diff --git a/libraries/session/src/main/res/values-am/strings.xml b/libraries/session/src/main/res/values-am/strings.xml index dca4e40a42..167aa23d48 100755 --- a/libraries/session/src/main/res/values-am/strings.xml +++ b/libraries/session/src/main/res/values-am/strings.xml @@ -21,4 +21,5 @@ ወደ ቀጣዩ ንጥል ፈልግ ወደኋላ ፈልግ ወደፊት ፈልግ + ማረጋገጥ ያስፈልጋል diff --git a/libraries/session/src/main/res/values-ar/strings.xml b/libraries/session/src/main/res/values-ar/strings.xml index 884e85ceb2..140f15247b 100755 --- a/libraries/session/src/main/res/values-ar/strings.xml +++ b/libraries/session/src/main/res/values-ar/strings.xml @@ -21,4 +21,5 @@ تقديم إلى العنصر التالي ترجيع تقديم + المصادقة مطلوبة diff --git a/libraries/session/src/main/res/values-az/strings.xml b/libraries/session/src/main/res/values-az/strings.xml index 94293d9202..9b026dc789 100755 --- a/libraries/session/src/main/res/values-az/strings.xml +++ b/libraries/session/src/main/res/values-az/strings.xml @@ -21,4 +21,5 @@ Növbəti elementə keçin Geri keçin İrəli keçin + Doğrulanma tələb olunur diff --git a/libraries/session/src/main/res/values-b+sr+Latn/strings.xml b/libraries/session/src/main/res/values-b+sr+Latn/strings.xml index 7d382d23ad..aab80ab5a7 100755 --- a/libraries/session/src/main/res/values-b+sr+Latn/strings.xml +++ b/libraries/session/src/main/res/values-b+sr+Latn/strings.xml @@ -21,4 +21,5 @@ Premotaj na sledeću stavku Premotaj unazad Premotaj unapred + Potrebna je potvrda identiteta diff --git a/libraries/session/src/main/res/values-be/strings.xml b/libraries/session/src/main/res/values-be/strings.xml index e334cb47ef..b01d57052a 100755 --- a/libraries/session/src/main/res/values-be/strings.xml +++ b/libraries/session/src/main/res/values-be/strings.xml @@ -21,4 +21,5 @@ Перайсці да наступнага элемента Перайсці назад Перайсці ўперад + Патрабуецца аўтэнтыфікацыя diff --git a/libraries/session/src/main/res/values-bg/strings.xml b/libraries/session/src/main/res/values-bg/strings.xml index 87b50ddf78..e24ec1e9bc 100755 --- a/libraries/session/src/main/res/values-bg/strings.xml +++ b/libraries/session/src/main/res/values-bg/strings.xml @@ -21,4 +21,5 @@ Придвижване към следващия елемент Придвижване назад Придвижване напред + Изисква се удостоверяване diff --git a/libraries/session/src/main/res/values-bn/strings.xml b/libraries/session/src/main/res/values-bn/strings.xml index f54c3792fd..2694309f6a 100755 --- a/libraries/session/src/main/res/values-bn/strings.xml +++ b/libraries/session/src/main/res/values-bn/strings.xml @@ -21,4 +21,5 @@ পরের আইটেমে যান ফিরে যাওয়ার বোতাম এগিয়ে যান + যাচাইকরণ প্রয়োজন diff --git a/libraries/session/src/main/res/values-bs/strings.xml b/libraries/session/src/main/res/values-bs/strings.xml index c9c4ac8985..2441a1fca8 100755 --- a/libraries/session/src/main/res/values-bs/strings.xml +++ b/libraries/session/src/main/res/values-bs/strings.xml @@ -21,4 +21,5 @@ Pomicanje na sljedeću stavku Pomicanje nazad Pomicanje naprijed + Potrebna je autentifikacija diff --git a/libraries/session/src/main/res/values-ca/strings.xml b/libraries/session/src/main/res/values-ca/strings.xml index fc4e653346..f9bf84a263 100755 --- a/libraries/session/src/main/res/values-ca/strings.xml +++ b/libraries/session/src/main/res/values-ca/strings.xml @@ -21,4 +21,5 @@ Ves a l\'element següent Retrocedeix Avança + Autenticació obligatòria diff --git a/libraries/session/src/main/res/values-cs/strings.xml b/libraries/session/src/main/res/values-cs/strings.xml index 3eda37e6f8..9c1f3dc49f 100755 --- a/libraries/session/src/main/res/values-cs/strings.xml +++ b/libraries/session/src/main/res/values-cs/strings.xml @@ -21,4 +21,5 @@ Posunout na další položku Posunout zpět Posunout vpřed + Je vyžadováno ověření diff --git a/libraries/session/src/main/res/values-da/strings.xml b/libraries/session/src/main/res/values-da/strings.xml index a03e95d1cb..c8236d5ab0 100755 --- a/libraries/session/src/main/res/values-da/strings.xml +++ b/libraries/session/src/main/res/values-da/strings.xml @@ -21,4 +21,5 @@ Hop til næste element Hop tilbage Hop frem + Godkendelse er påkrævet diff --git a/libraries/session/src/main/res/values-de/strings.xml b/libraries/session/src/main/res/values-de/strings.xml index 27923da79d..f6685e5999 100755 --- a/libraries/session/src/main/res/values-de/strings.xml +++ b/libraries/session/src/main/res/values-de/strings.xml @@ -21,4 +21,5 @@ Zum nächsten Element Zurückspulen Vorspulen + Authentifizierung erforderlich diff --git a/libraries/session/src/main/res/values-el/strings.xml b/libraries/session/src/main/res/values-el/strings.xml index d3b6f555a6..0d90dca7f9 100755 --- a/libraries/session/src/main/res/values-el/strings.xml +++ b/libraries/session/src/main/res/values-el/strings.xml @@ -21,4 +21,5 @@ Αναζήτηση προς επόμενο στοιχείο Αναζήτηση προς τα πίσω Αναζήτηση προς τα εμπρός + Απαιτείται έλεγχος ταυτότητας diff --git a/libraries/session/src/main/res/values-en-rAU/strings.xml b/libraries/session/src/main/res/values-en-rAU/strings.xml index 75e283fba2..0bf10abd2d 100755 --- a/libraries/session/src/main/res/values-en-rAU/strings.xml +++ b/libraries/session/src/main/res/values-en-rAU/strings.xml @@ -21,4 +21,5 @@ Forward to next item Rewind Fast forward + Authentication required diff --git a/libraries/session/src/main/res/values-en-rGB/strings.xml b/libraries/session/src/main/res/values-en-rGB/strings.xml index 75e283fba2..0bf10abd2d 100755 --- a/libraries/session/src/main/res/values-en-rGB/strings.xml +++ b/libraries/session/src/main/res/values-en-rGB/strings.xml @@ -21,4 +21,5 @@ Forward to next item Rewind Fast forward + Authentication required diff --git a/libraries/session/src/main/res/values-en-rIN/strings.xml b/libraries/session/src/main/res/values-en-rIN/strings.xml index 75e283fba2..0bf10abd2d 100755 --- a/libraries/session/src/main/res/values-en-rIN/strings.xml +++ b/libraries/session/src/main/res/values-en-rIN/strings.xml @@ -21,4 +21,5 @@ Forward to next item Rewind Fast forward + Authentication required diff --git a/libraries/session/src/main/res/values-es-rUS/strings.xml b/libraries/session/src/main/res/values-es-rUS/strings.xml index 21866ca55c..c3ea5dcb07 100755 --- a/libraries/session/src/main/res/values-es-rUS/strings.xml +++ b/libraries/session/src/main/res/values-es-rUS/strings.xml @@ -21,4 +21,5 @@ Saltar al siguiente elemento Retroceder Avanzar + Se requiere autenticación diff --git a/libraries/session/src/main/res/values-es/strings.xml b/libraries/session/src/main/res/values-es/strings.xml index b4f698ba43..1a8880ecdb 100755 --- a/libraries/session/src/main/res/values-es/strings.xml +++ b/libraries/session/src/main/res/values-es/strings.xml @@ -21,4 +21,5 @@ Ir al elemento siguiente Volver Avanzar + Autenticación obligatoria diff --git a/libraries/session/src/main/res/values-et/strings.xml b/libraries/session/src/main/res/values-et/strings.xml index cb1fec5338..4bd8e64a45 100755 --- a/libraries/session/src/main/res/values-et/strings.xml +++ b/libraries/session/src/main/res/values-et/strings.xml @@ -21,4 +21,5 @@ Järgmise üksuse juurde liikumine Tagasikerimine Edasikerimine + Vajalik on autentimine diff --git a/libraries/session/src/main/res/values-eu/strings.xml b/libraries/session/src/main/res/values-eu/strings.xml index d9d9070d2a..f53cc746a7 100755 --- a/libraries/session/src/main/res/values-eu/strings.xml +++ b/libraries/session/src/main/res/values-eu/strings.xml @@ -21,4 +21,5 @@ Joan hurrengo elementura Atzeratu Aurreratu + Autentifikazioa behar da diff --git a/libraries/session/src/main/res/values-fa/strings.xml b/libraries/session/src/main/res/values-fa/strings.xml index c78caeb81f..eb8a961f98 100755 --- a/libraries/session/src/main/res/values-fa/strings.xml +++ b/libraries/session/src/main/res/values-fa/strings.xml @@ -21,4 +21,5 @@ رفتن به مورد بعدی رفتن به عقب رفتن به جلو + اصالت‌سنجی لازم است diff --git a/libraries/session/src/main/res/values-fi/strings.xml b/libraries/session/src/main/res/values-fi/strings.xml index c6cb5b69a0..a4d6637218 100755 --- a/libraries/session/src/main/res/values-fi/strings.xml +++ b/libraries/session/src/main/res/values-fi/strings.xml @@ -21,4 +21,5 @@ Siirry seuraavaan Siirry taaksepäin Siirry eteenpäin + Todennus vaaditaan diff --git a/libraries/session/src/main/res/values-fr-rCA/strings.xml b/libraries/session/src/main/res/values-fr-rCA/strings.xml index f963a8fa00..fe00e2480b 100755 --- a/libraries/session/src/main/res/values-fr-rCA/strings.xml +++ b/libraries/session/src/main/res/values-fr-rCA/strings.xml @@ -21,4 +21,5 @@ Rechercher vers l\'élément suivant Rechercher vers l\'arrière Rechercher vers l\'avant + Authentification requise diff --git a/libraries/session/src/main/res/values-fr/strings.xml b/libraries/session/src/main/res/values-fr/strings.xml index 2ebff97fd1..bda0e76cd5 100755 --- a/libraries/session/src/main/res/values-fr/strings.xml +++ b/libraries/session/src/main/res/values-fr/strings.xml @@ -21,4 +21,5 @@ Accéder à l\'élément suivant Revenir en arrière Avancer + Authentification requise diff --git a/libraries/session/src/main/res/values-gl/strings.xml b/libraries/session/src/main/res/values-gl/strings.xml index 185f983387..97c0b5ae91 100755 --- a/libraries/session/src/main/res/values-gl/strings.xml +++ b/libraries/session/src/main/res/values-gl/strings.xml @@ -21,4 +21,5 @@ Avanzar ao elemento seguinte Retroceder Avanzar + Requírese autenticación diff --git a/libraries/session/src/main/res/values-gu/strings.xml b/libraries/session/src/main/res/values-gu/strings.xml index d364ee783a..3c2e583039 100755 --- a/libraries/session/src/main/res/values-gu/strings.xml +++ b/libraries/session/src/main/res/values-gu/strings.xml @@ -21,4 +21,5 @@ આગલી આઇટમ શોધો પાછળ લઈ જાઓ આગળ લઈ જાઓ + પ્રમાણીકરણ આવશ્યક છે diff --git a/libraries/session/src/main/res/values-hi/strings.xml b/libraries/session/src/main/res/values-hi/strings.xml index 4088e7bf1a..99a792cdd5 100755 --- a/libraries/session/src/main/res/values-hi/strings.xml +++ b/libraries/session/src/main/res/values-hi/strings.xml @@ -21,4 +21,5 @@ अगले आइटम पर जाएं वापस जाएं आगे बढ़ाएं + पुष्टि करना ज़रूरी है diff --git a/libraries/session/src/main/res/values-hr/strings.xml b/libraries/session/src/main/res/values-hr/strings.xml index 4e1340b6da..3fa32acbfb 100755 --- a/libraries/session/src/main/res/values-hr/strings.xml +++ b/libraries/session/src/main/res/values-hr/strings.xml @@ -21,4 +21,5 @@ Idi na sljedeću stavku Skok unatrag Skok prema naprijed + Potrebna je autentifikacija diff --git a/libraries/session/src/main/res/values-hu/strings.xml b/libraries/session/src/main/res/values-hu/strings.xml index 891135833b..2ff84c81f9 100755 --- a/libraries/session/src/main/res/values-hu/strings.xml +++ b/libraries/session/src/main/res/values-hu/strings.xml @@ -21,4 +21,5 @@ Ugrás a következő elemre Ugrás vissza Ugrás előre + Hitelesítés szükséges diff --git a/libraries/session/src/main/res/values-hy/strings.xml b/libraries/session/src/main/res/values-hy/strings.xml index 5d3e7d9c70..c5507fa8a1 100755 --- a/libraries/session/src/main/res/values-hy/strings.xml +++ b/libraries/session/src/main/res/values-hy/strings.xml @@ -21,4 +21,5 @@ Անցնել հաջորդ տարրին Հետ գնալ Առաջ գնալ + Պահանջվում է նույնականացում diff --git a/libraries/session/src/main/res/values-in/strings.xml b/libraries/session/src/main/res/values-in/strings.xml index 1bf0d362dd..142339374a 100755 --- a/libraries/session/src/main/res/values-in/strings.xml +++ b/libraries/session/src/main/res/values-in/strings.xml @@ -21,4 +21,5 @@ Cari item berikutnya Mundur Maju + Perlu autentikasi diff --git a/libraries/session/src/main/res/values-is/strings.xml b/libraries/session/src/main/res/values-is/strings.xml index 19628ce30c..dfc6267d5a 100755 --- a/libraries/session/src/main/res/values-is/strings.xml +++ b/libraries/session/src/main/res/values-is/strings.xml @@ -21,4 +21,5 @@ Spóla að næsta atriði Spóla til baka Spóla áfram + Auðkenningar krafist diff --git a/libraries/session/src/main/res/values-it/strings.xml b/libraries/session/src/main/res/values-it/strings.xml index 93778ab509..0be1260e55 100755 --- a/libraries/session/src/main/res/values-it/strings.xml +++ b/libraries/session/src/main/res/values-it/strings.xml @@ -21,4 +21,5 @@ Vai all\'elemento successivo Vai indietro Vai avanti + Autenticazione richiesta diff --git a/libraries/session/src/main/res/values-iw/strings.xml b/libraries/session/src/main/res/values-iw/strings.xml index c69347b80b..d5232cf89b 100755 --- a/libraries/session/src/main/res/values-iw/strings.xml +++ b/libraries/session/src/main/res/values-iw/strings.xml @@ -21,4 +21,5 @@ דילוג לפריט הבא דילוג אחורה דילוג קדימה + נדרש אימות diff --git a/libraries/session/src/main/res/values-ja/strings.xml b/libraries/session/src/main/res/values-ja/strings.xml index 6d3640f4b8..44957a4eed 100755 --- a/libraries/session/src/main/res/values-ja/strings.xml +++ b/libraries/session/src/main/res/values-ja/strings.xml @@ -21,4 +21,5 @@ 次のアイテムに移動 巻き戻し 早送り + 認証が必要です diff --git a/libraries/session/src/main/res/values-ka/strings.xml b/libraries/session/src/main/res/values-ka/strings.xml index 7b88e9ad9d..44e49caf12 100755 --- a/libraries/session/src/main/res/values-ka/strings.xml +++ b/libraries/session/src/main/res/values-ka/strings.xml @@ -21,4 +21,5 @@ შემდეგ ერთეულზე გადახვევა უკან გადახვევა წინ გადახვევა + საჭიროა ავტორიზაცია diff --git a/libraries/session/src/main/res/values-kk/strings.xml b/libraries/session/src/main/res/values-kk/strings.xml index b056cc6910..98f22c7807 100755 --- a/libraries/session/src/main/res/values-kk/strings.xml +++ b/libraries/session/src/main/res/values-kk/strings.xml @@ -21,4 +21,5 @@ Келесі мазмұнға өту Артқа айналдыру Алға айналдыру + Аутентификация қажет diff --git a/libraries/session/src/main/res/values-km/strings.xml b/libraries/session/src/main/res/values-km/strings.xml index 190ffa4f1a..b12cf6a894 100755 --- a/libraries/session/src/main/res/values-km/strings.xml +++ b/libraries/session/src/main/res/values-km/strings.xml @@ -21,4 +21,5 @@ ទៅកាន់ធាតុបន្ទាប់ ថយក្រោយ រំលង​​ទៅ​មុខ + តម្រូវឱ្យ​មាន​ការផ្ទៀងផ្ទាត់ diff --git a/libraries/session/src/main/res/values-kn/strings.xml b/libraries/session/src/main/res/values-kn/strings.xml index 62f7b8bc58..485b09c0bf 100755 --- a/libraries/session/src/main/res/values-kn/strings.xml +++ b/libraries/session/src/main/res/values-kn/strings.xml @@ -21,4 +21,5 @@ ಮುಂದಿನ ಐಟಂಗೆ ಸೀಕ್ ಮಾಡಿ ಹಿಂದಕ್ಕೆ ಸೀಕ್ ಮಾಡಿ ಮುಂದಕ್ಕೆ ಸೀಕ್ ಮಾಡಿ + ದೃಢೀಕರಣದ ಅಗತ್ಯವಿದೆ diff --git a/libraries/session/src/main/res/values-ko/strings.xml b/libraries/session/src/main/res/values-ko/strings.xml index d649d822c8..015471fe5e 100755 --- a/libraries/session/src/main/res/values-ko/strings.xml +++ b/libraries/session/src/main/res/values-ko/strings.xml @@ -21,4 +21,5 @@ 다음 항목 찾기 뒤로 탐색 앞으로 탐색 + 인증 필요 diff --git a/libraries/session/src/main/res/values-ky/strings.xml b/libraries/session/src/main/res/values-ky/strings.xml index 833198482e..350724d9e0 100755 --- a/libraries/session/src/main/res/values-ky/strings.xml +++ b/libraries/session/src/main/res/values-ky/strings.xml @@ -21,4 +21,5 @@ Кийинки нерсеге өтүү Артка түрдүрүү Алдыга түрдүрүү + Аныктыгын текшерүү талап кылынат diff --git a/libraries/session/src/main/res/values-lo/strings.xml b/libraries/session/src/main/res/values-lo/strings.xml index be62a424b5..337bd7be33 100755 --- a/libraries/session/src/main/res/values-lo/strings.xml +++ b/libraries/session/src/main/res/values-lo/strings.xml @@ -21,4 +21,5 @@ ເລື່ອນໄປຫາລາຍການຕໍ່ໄປ ເລື່ອນກັບຫຼັງ ເລື່ອນໄປໜ້າ + ຕ້ອງມີການພິສູດຢືນຢັນ diff --git a/libraries/session/src/main/res/values-lt/strings.xml b/libraries/session/src/main/res/values-lt/strings.xml index 979e6b0f65..a8c02c98af 100755 --- a/libraries/session/src/main/res/values-lt/strings.xml +++ b/libraries/session/src/main/res/values-lt/strings.xml @@ -21,4 +21,5 @@ Prasukti į kitą elementą Prasukti atgal Prasukti pirmyn + Būtina nustatyti tapatybę diff --git a/libraries/session/src/main/res/values-lv/strings.xml b/libraries/session/src/main/res/values-lv/strings.xml index 55facd793b..030bb7a549 100755 --- a/libraries/session/src/main/res/values-lv/strings.xml +++ b/libraries/session/src/main/res/values-lv/strings.xml @@ -21,4 +21,5 @@ Pāriet uz nākamo vienumu Pāriet atpakaļ Pāriet uz priekšu + Nepieciešama autentificēšana diff --git a/libraries/session/src/main/res/values-mk/strings.xml b/libraries/session/src/main/res/values-mk/strings.xml index 509cc64d0d..19487a2d57 100755 --- a/libraries/session/src/main/res/values-mk/strings.xml +++ b/libraries/session/src/main/res/values-mk/strings.xml @@ -21,4 +21,5 @@ Премотај на следната ставка Премотај наназад Премотај нанапред + Потребна е проверка diff --git a/libraries/session/src/main/res/values-ml/strings.xml b/libraries/session/src/main/res/values-ml/strings.xml index 99055c910c..0b68af763f 100755 --- a/libraries/session/src/main/res/values-ml/strings.xml +++ b/libraries/session/src/main/res/values-ml/strings.xml @@ -21,4 +21,5 @@ അടുത്ത ഇനത്തിലേക്ക് നീക്കുക പിന്നോട്ട് നീക്കുക മുന്നോട്ട് നീക്കുക + പരിശോധിച്ചുറപ്പിക്കേണ്ടതുണ്ട് diff --git a/libraries/session/src/main/res/values-mn/strings.xml b/libraries/session/src/main/res/values-mn/strings.xml index 354d1ee4ed..5b9c2604fc 100755 --- a/libraries/session/src/main/res/values-mn/strings.xml +++ b/libraries/session/src/main/res/values-mn/strings.xml @@ -21,4 +21,5 @@ Дараагийн зүйл рүү гүйлгэх Буцаан гүйлгэх Урагшлуулах + Баталгаажуулалт шаардлагатай diff --git a/libraries/session/src/main/res/values-mr/strings.xml b/libraries/session/src/main/res/values-mr/strings.xml index 704ba97df2..35c8acf476 100755 --- a/libraries/session/src/main/res/values-mr/strings.xml +++ b/libraries/session/src/main/res/values-mr/strings.xml @@ -21,4 +21,5 @@ पुढील आयटमवर जा मागे जा पुढे जा + ऑथेंटिकेशन आवश्यक आहे diff --git a/libraries/session/src/main/res/values-ms/strings.xml b/libraries/session/src/main/res/values-ms/strings.xml index 8b9c87d24e..120211affc 100755 --- a/libraries/session/src/main/res/values-ms/strings.xml +++ b/libraries/session/src/main/res/values-ms/strings.xml @@ -21,4 +21,5 @@ Cari sehingga item seterusnya Mandir Mundar + Pengesahan diperlukan diff --git a/libraries/session/src/main/res/values-my/strings.xml b/libraries/session/src/main/res/values-my/strings.xml index 770c00baeb..ea9920abc4 100755 --- a/libraries/session/src/main/res/values-my/strings.xml +++ b/libraries/session/src/main/res/values-my/strings.xml @@ -21,4 +21,5 @@ ရှေ့တစ်ခုသို့ ရစ်ရန် နောက်သို့ ရစ်ရန် ရှေ့သို့ ရစ်ရန် + အထောက်အထားစိစစ်ခြင်း လိုအပ်သည် diff --git a/libraries/session/src/main/res/values-nb/strings.xml b/libraries/session/src/main/res/values-nb/strings.xml index c4f6f480a9..fefb5ea835 100755 --- a/libraries/session/src/main/res/values-nb/strings.xml +++ b/libraries/session/src/main/res/values-nb/strings.xml @@ -21,4 +21,5 @@ Hopp til det neste elementet Hopp bakover Hopp fremover + Autentisering kreves diff --git a/libraries/session/src/main/res/values-ne/strings.xml b/libraries/session/src/main/res/values-ne/strings.xml index 21f2219110..8d282366c8 100755 --- a/libraries/session/src/main/res/values-ne/strings.xml +++ b/libraries/session/src/main/res/values-ne/strings.xml @@ -21,4 +21,5 @@ अर्को वस्तुमा जानुहोस् पछाडि जानुहोस् अगाडि जानुहोस् + पुष्टि गर्नु पर्ने हुन्छ diff --git a/libraries/session/src/main/res/values-nl/strings.xml b/libraries/session/src/main/res/values-nl/strings.xml index 87e8eebf5c..f3735156e4 100755 --- a/libraries/session/src/main/res/values-nl/strings.xml +++ b/libraries/session/src/main/res/values-nl/strings.xml @@ -21,4 +21,5 @@ Naar volgende item springen Achteruit springen Vooruit springen + Verificatie vereist diff --git a/libraries/session/src/main/res/values-pa/strings.xml b/libraries/session/src/main/res/values-pa/strings.xml index 386426b882..86653fca74 100755 --- a/libraries/session/src/main/res/values-pa/strings.xml +++ b/libraries/session/src/main/res/values-pa/strings.xml @@ -21,4 +21,5 @@ ਅਗਲੀ ਆਈਟਮ \'ਤੇ ਜਾਓ ਪਿੱਛੇ ਲਿਜਾਓ ਅੱਗੇ ਵਧਾਓ + ਪ੍ਰਮਾਣੀਕਰਨ ਲੋੜੀਂਦਾ ਹੈ diff --git a/libraries/session/src/main/res/values-pl/strings.xml b/libraries/session/src/main/res/values-pl/strings.xml index 01a659b478..10eddbef38 100755 --- a/libraries/session/src/main/res/values-pl/strings.xml +++ b/libraries/session/src/main/res/values-pl/strings.xml @@ -21,4 +21,5 @@ Przewiń do następnego elementu Przewiń do tyłu Przewiń do przodu + Wymagane uwierzytelnienie diff --git a/libraries/session/src/main/res/values-pt-rPT/strings.xml b/libraries/session/src/main/res/values-pt-rPT/strings.xml index d6ac74420f..0be33ad385 100755 --- a/libraries/session/src/main/res/values-pt-rPT/strings.xml +++ b/libraries/session/src/main/res/values-pt-rPT/strings.xml @@ -21,4 +21,5 @@ Avançar para o item seguinte Retroceder Avançar + Autenticação necessária diff --git a/libraries/session/src/main/res/values-pt/strings.xml b/libraries/session/src/main/res/values-pt/strings.xml index 3f3150177f..7bd7d79520 100755 --- a/libraries/session/src/main/res/values-pt/strings.xml +++ b/libraries/session/src/main/res/values-pt/strings.xml @@ -21,4 +21,5 @@ Ir para o próximo item Retroceder Avançar + Autenticação necessária diff --git a/libraries/session/src/main/res/values-ro/strings.xml b/libraries/session/src/main/res/values-ro/strings.xml index 7a94921fd5..dd6fc779bd 100755 --- a/libraries/session/src/main/res/values-ro/strings.xml +++ b/libraries/session/src/main/res/values-ro/strings.xml @@ -21,4 +21,5 @@ Treci la elementul următor Derulează înapoi Derulează înainte + Autentificarea este obligatorie diff --git a/libraries/session/src/main/res/values-ru/strings.xml b/libraries/session/src/main/res/values-ru/strings.xml index 15539019ba..b643018ac0 100755 --- a/libraries/session/src/main/res/values-ru/strings.xml +++ b/libraries/session/src/main/res/values-ru/strings.xml @@ -21,4 +21,5 @@ К следующему файлу Перемотать назад Перемотать вперед + Требуется аутентификация diff --git a/libraries/session/src/main/res/values-si/strings.xml b/libraries/session/src/main/res/values-si/strings.xml index 720efff6d3..48c60ddef8 100755 --- a/libraries/session/src/main/res/values-si/strings.xml +++ b/libraries/session/src/main/res/values-si/strings.xml @@ -21,4 +21,5 @@ ඊළඟ අයිතමය වෙත අන්වේෂණය ආපස්සට අන්වේෂණය ඉදිරියට අන්වේෂණය + සත්‍යාපනය අවශ්‍යයි diff --git a/libraries/session/src/main/res/values-sk/strings.xml b/libraries/session/src/main/res/values-sk/strings.xml index dd71df61e3..f2d31acf05 100755 --- a/libraries/session/src/main/res/values-sk/strings.xml +++ b/libraries/session/src/main/res/values-sk/strings.xml @@ -21,4 +21,5 @@ Hľadať v ďalšej položke Hľadať smerom dozadu Hľadať smerom dopredu + Vyžaduje sa overenie diff --git a/libraries/session/src/main/res/values-sl/strings.xml b/libraries/session/src/main/res/values-sl/strings.xml index b77b1d15c9..ab3fa88897 100755 --- a/libraries/session/src/main/res/values-sl/strings.xml +++ b/libraries/session/src/main/res/values-sl/strings.xml @@ -21,4 +21,5 @@ Premakni na naslednji element Premakni nazaj Premakni naprej + Zahtevano je preverjanje pristnosti diff --git a/libraries/session/src/main/res/values-sq/strings.xml b/libraries/session/src/main/res/values-sq/strings.xml index ec16268eb5..c8ebb5046d 100755 --- a/libraries/session/src/main/res/values-sq/strings.xml +++ b/libraries/session/src/main/res/values-sq/strings.xml @@ -21,4 +21,5 @@ Kërko te artikulli tjetër Kërko prapa Kërko përpara + Kërkohet vërtetimi diff --git a/libraries/session/src/main/res/values-sr/strings.xml b/libraries/session/src/main/res/values-sr/strings.xml index 9713781784..e3f7665ac3 100755 --- a/libraries/session/src/main/res/values-sr/strings.xml +++ b/libraries/session/src/main/res/values-sr/strings.xml @@ -21,4 +21,5 @@ Премотај на следећу ставку Премотај уназад Премотај унапред + Потребна је потврда идентитета diff --git a/libraries/session/src/main/res/values-sv/strings.xml b/libraries/session/src/main/res/values-sv/strings.xml index 983e7a3647..ad53a1d6e4 100755 --- a/libraries/session/src/main/res/values-sv/strings.xml +++ b/libraries/session/src/main/res/values-sv/strings.xml @@ -21,4 +21,5 @@ Hoppa till nästa objekt Hoppa bakåt Hoppa framåt + Autentisering krävs diff --git a/libraries/session/src/main/res/values-sw/strings.xml b/libraries/session/src/main/res/values-sw/strings.xml index 25484e4f98..241fb50b78 100755 --- a/libraries/session/src/main/res/values-sw/strings.xml +++ b/libraries/session/src/main/res/values-sw/strings.xml @@ -21,4 +21,5 @@ Nenda kwenye maudhui yanayofuata Sogeza nyuma Sogeza mbele + Uthibitishaji unahitajika diff --git a/libraries/session/src/main/res/values-ta/strings.xml b/libraries/session/src/main/res/values-ta/strings.xml index c0ea3beac9..e0b65856a2 100755 --- a/libraries/session/src/main/res/values-ta/strings.xml +++ b/libraries/session/src/main/res/values-ta/strings.xml @@ -21,4 +21,5 @@ அடுத்ததற்குச் செல்லும் பின்செல்லும் முன்செல்லும் + அங்கீகாரம் தேவை diff --git a/libraries/session/src/main/res/values-te/strings.xml b/libraries/session/src/main/res/values-te/strings.xml index c32b4ba9cf..e8a3734789 100755 --- a/libraries/session/src/main/res/values-te/strings.xml +++ b/libraries/session/src/main/res/values-te/strings.xml @@ -21,4 +21,5 @@ తర్వాతి ఐటెమ్‌కు దాటవేయండి వెనుకకు దాటవేయండి ముందుకు ఫార్వర్డ్ చేయండి + ప్రామాణీకరణ అవసరం diff --git a/libraries/session/src/main/res/values-th/strings.xml b/libraries/session/src/main/res/values-th/strings.xml index dfd5bfc500..683e2aae68 100755 --- a/libraries/session/src/main/res/values-th/strings.xml +++ b/libraries/session/src/main/res/values-th/strings.xml @@ -21,4 +21,5 @@ กรอไปยังรายการถัดไป กรอกลับ กรอไปข้างหน้า + ต้องมีการตรวจสอบสิทธิ์ diff --git a/libraries/session/src/main/res/values-tl/strings.xml b/libraries/session/src/main/res/values-tl/strings.xml index ba200975d7..995740a809 100755 --- a/libraries/session/src/main/res/values-tl/strings.xml +++ b/libraries/session/src/main/res/values-tl/strings.xml @@ -21,4 +21,5 @@ Mag-seek sa susunod na item Mag-seek pabalik Mag-seek pasulong + Kinakailangan ang pag-authenticate diff --git a/libraries/session/src/main/res/values-tr/strings.xml b/libraries/session/src/main/res/values-tr/strings.xml index 9ecb219f1d..2795069c69 100755 --- a/libraries/session/src/main/res/values-tr/strings.xml +++ b/libraries/session/src/main/res/values-tr/strings.xml @@ -21,4 +21,5 @@ Sonraki öğeye sar Geri sar İleri sar + Kimlik doğrulama gerekiyor diff --git a/libraries/session/src/main/res/values-uk/strings.xml b/libraries/session/src/main/res/values-uk/strings.xml index c8766454d2..4786db3ce7 100755 --- a/libraries/session/src/main/res/values-uk/strings.xml +++ b/libraries/session/src/main/res/values-uk/strings.xml @@ -21,4 +21,5 @@ Перейти до наступного об’єкта Перемотати назад Перемотати вперед + Потрібна автентифікація diff --git a/libraries/session/src/main/res/values-ur/strings.xml b/libraries/session/src/main/res/values-ur/strings.xml index 5068306a6e..423908db8a 100755 --- a/libraries/session/src/main/res/values-ur/strings.xml +++ b/libraries/session/src/main/res/values-ur/strings.xml @@ -21,4 +21,5 @@ اگلے آئٹم پر جائیں واپس جائیں آگے جائیں + توثیق مطلوب ہے diff --git a/libraries/session/src/main/res/values-uz/strings.xml b/libraries/session/src/main/res/values-uz/strings.xml index 68e7154fd6..fed30dd627 100755 --- a/libraries/session/src/main/res/values-uz/strings.xml +++ b/libraries/session/src/main/res/values-uz/strings.xml @@ -21,4 +21,5 @@ Keyingi trekka oʻtish Orqaga surish Oldinga surish + Haqiqiylikni tekshirish talab etiladi diff --git a/libraries/session/src/main/res/values-vi/strings.xml b/libraries/session/src/main/res/values-vi/strings.xml index 096e2678ca..9307041370 100755 --- a/libraries/session/src/main/res/values-vi/strings.xml +++ b/libraries/session/src/main/res/values-vi/strings.xml @@ -21,4 +21,5 @@ Tua đến mục tiếp theo Tua lại Tua đi + Yêu cầu xác thực diff --git a/libraries/session/src/main/res/values-zh-rCN/strings.xml b/libraries/session/src/main/res/values-zh-rCN/strings.xml index 061d8cb750..0db7916594 100755 --- a/libraries/session/src/main/res/values-zh-rCN/strings.xml +++ b/libraries/session/src/main/res/values-zh-rCN/strings.xml @@ -21,4 +21,5 @@ 跳转到下一项 快退 快进 + 需要进行身份验证 diff --git a/libraries/session/src/main/res/values-zh-rHK/strings.xml b/libraries/session/src/main/res/values-zh-rHK/strings.xml index d92be1d68b..87716dc283 100755 --- a/libraries/session/src/main/res/values-zh-rHK/strings.xml +++ b/libraries/session/src/main/res/values-zh-rHK/strings.xml @@ -21,4 +21,5 @@ 跳去下一項 後移 快轉 + 需要驗證 diff --git a/libraries/session/src/main/res/values-zh-rTW/strings.xml b/libraries/session/src/main/res/values-zh-rTW/strings.xml index a8d4854687..e7603e7d90 100755 --- a/libraries/session/src/main/res/values-zh-rTW/strings.xml +++ b/libraries/session/src/main/res/values-zh-rTW/strings.xml @@ -21,4 +21,5 @@ 跳轉到下一個項目 倒轉 快轉 + 必須驗證 diff --git a/libraries/session/src/main/res/values-zu/strings.xml b/libraries/session/src/main/res/values-zu/strings.xml index d33df71dc5..4f5ee5dddd 100755 --- a/libraries/session/src/main/res/values-zu/strings.xml +++ b/libraries/session/src/main/res/values-zu/strings.xml @@ -21,4 +21,5 @@ Funa into elandelayo Funa okwangemuva Funa uye phambili + Ukufakazela ubuqiniso kudingekile diff --git a/libraries/ui/src/main/res/values-af/strings.xml b/libraries/ui/src/main/res/values-af/strings.xml index 4511839582..dd37229848 100644 --- a/libraries/ui/src/main/res/values-af/strings.xml +++ b/libraries/ui/src/main/res/values-af/strings.xml @@ -37,11 +37,11 @@ Spoel %d sekonde vinnig vorentoe Spoel %d sekondes vinnig vorentoe - Herhaal niks - Herhaal een - Herhaal alles - Skommel is aan - Skommel is af + Huidige modus: herhaal niks. Wissel herhaalmodus. + Huidige modus: herhaal een. Wissel herhaalmodus. + Huidige modus: herhaal alles. Wissel herhaalmodus. + Deaktiveer skommelmodus + Aktiveer skommelmodus VR-modus Deaktiveer onderskrifte Aktiveer onderskrifte diff --git a/libraries/ui/src/main/res/values-am/strings.xml b/libraries/ui/src/main/res/values-am/strings.xml index a35bf1a6f5..343e45fbb8 100644 --- a/libraries/ui/src/main/res/values-am/strings.xml +++ b/libraries/ui/src/main/res/values-am/strings.xml @@ -37,11 +37,11 @@ በ%d ሰከንዶች በፍጥነት ወደፊት ያሳልፉ በ%d ሰከንዶች በፍጥነት ወደፊት ያሳልፉ - ምንም አትድገም - አንድ ድገም - ሁሉንም ድገም - መበወዝ በርቷል - መበወዝ ጠፍቷል + የአሁኑ ሁነታ፦ ምንም አትድገም። የመድገም ሁነታን ቀያይር። + የአሁን ሁነታ፦ አንዱን ድገም። የመድገም ሁነታን ቀያይር። + የአሁን ሁነታ፦ ሁሉም ድገም። የመድገም ሁነታን ቀያይር። + የበውዝ ሁነታን አሰናክል + የበውዝ ሁነታን አንቃ የቪአር ሁነታ የግርጌ ጽሑፎችን አሰናክል የግርጌ ጽሑፎችን አንቃ diff --git a/libraries/ui/src/main/res/values-ar/strings.xml b/libraries/ui/src/main/res/values-ar/strings.xml index c7e48f7879..bef7a468e5 100644 --- a/libraries/ui/src/main/res/values-ar/strings.xml +++ b/libraries/ui/src/main/res/values-ar/strings.xml @@ -45,11 +45,11 @@ تقديم سريع للفيديو بمقدار %d ثانية تقديم سريع للفيديو بمقدار %d ثانية - عدم التكرار - تكرار مقطع صوتي واحد - تكرار الكل - تفعيل الترتيب العشوائي - إيقاف الترتيب العشوائي + الوضع الحالي: عدم التكرار. تبديل وضع التكرار + الوضع الحالي: التكرار مرة واحدة. تبديل وضع التكرار + الوضع الحالي: تكرار الكل. تبديل وضع التكرار + إيقاف وضع الترتيب العشوائي + تفعيل وضع الترتيب العشوائي وضع VR إيقاف الترجمة تفعيل الترجمة diff --git a/libraries/ui/src/main/res/values-az/strings.xml b/libraries/ui/src/main/res/values-az/strings.xml index 5f8cce18e3..86ea052268 100644 --- a/libraries/ui/src/main/res/values-az/strings.xml +++ b/libraries/ui/src/main/res/values-az/strings.xml @@ -37,11 +37,11 @@ %d saniyə irəli çəkin %d saniyə irəli çəkin - Heç biri təkrarlanmasın - Biri təkrarlansın - Hamısı təkrarlansın - Qarışdırma aktivdir - Qarışdırma deaktivdir + Cari rejim: Heç birini təkrarlamayın. Təkrarlanma rejimini keçirin. + Cari rejim: Birini təkrarlayın. Təkrarlanma rejimini keçirin. + Cari rejim: Hamısını təkrarlayın. Təkrarlanma rejimini keçirin. + Qarışdırma rejimini deaktiv edin + Qarışdırma rejimini aktiv edin VR rejimi Subtitrləri deaktiv edin Subtitrləri aktiv edin diff --git a/libraries/ui/src/main/res/values-b+sr+Latn/strings.xml b/libraries/ui/src/main/res/values-b+sr+Latn/strings.xml index 8173fb6361..2acf688bca 100644 --- a/libraries/ui/src/main/res/values-b+sr+Latn/strings.xml +++ b/libraries/ui/src/main/res/values-b+sr+Latn/strings.xml @@ -39,11 +39,11 @@ Premotajte %d sekunde unapred Premotajte %d sekundi unapred - Ne ponavljaj nijednu - Ponovi jednu - Ponovi sve - Nasumično puštanje je uključeno - Nasumično puštanje je isključeno + Vaš režim: Bez ponavljanja. Uključite/isključite. + Vaš režim: Ponovi jedno. Uključite/isključite. + Vaš režim: Ponovi sve. Uključite/isključite. + Onemogućite nasumični režim + Omogućite nasumični režim VR režim Onemogući titlove Omogući titlove diff --git a/libraries/ui/src/main/res/values-be/strings.xml b/libraries/ui/src/main/res/values-be/strings.xml index 82518faecf..05ea71c472 100644 --- a/libraries/ui/src/main/res/values-be/strings.xml +++ b/libraries/ui/src/main/res/values-be/strings.xml @@ -41,11 +41,11 @@ Пераматаць уперад на %d секунд Пераматаць уперад на %d секунды - Не паўтараць нічога - Паўтарыць адзін элемент - Паўтарыць усе - Перамешванне ўключана - Перамешванне выключана + Цяпер: без паўтораў. Змяніць. + Цяпер: паўтараць фрагмент. Змяніць. + Цяпер: паўтараць усё. Змяніць. + Выключыць рэжым перамешвання + Уключыць рэжым перамешвання VR-рэжым Выключыць субцітры Уключыць субцітры @@ -74,7 +74,7 @@ Альтэрнатыўны запіс Дадатковы запіс Каментарыі - Цітры + Субцітры %1$.2f Мбіт/с %1$s, %2$s diff --git a/libraries/ui/src/main/res/values-bg/strings.xml b/libraries/ui/src/main/res/values-bg/strings.xml index 056c5b9e83..3a898ed4bd 100644 --- a/libraries/ui/src/main/res/values-bg/strings.xml +++ b/libraries/ui/src/main/res/values-bg/strings.xml @@ -37,11 +37,11 @@ Превъртане с %d секунда напред Превъртане с(ъс) %d секунди напред - Без повтаряне - Повтаряне на един елемент - Повтаряне на всички - Разбъркването е включено - Разбъркването е изключено + Текущ режим: Без повтаряне. Превкл. режима за повтаряне. + Текущ режим: Повтар. на 1 елемент. Превкл. режима за повтаряне. + Текущ режим: Повтар. на всички. Превкл. режима за повтаряне. + Деактивиране на режима за разбъркване + Активиране на режима за разбъркване режим за VR Деактивиране на субтитрите Активиране на субтитрите diff --git a/libraries/ui/src/main/res/values-bn/strings.xml b/libraries/ui/src/main/res/values-bn/strings.xml index bf438cc335..2235db434b 100644 --- a/libraries/ui/src/main/res/values-bn/strings.xml +++ b/libraries/ui/src/main/res/values-bn/strings.xml @@ -37,11 +37,11 @@ %d সেকেন্ড ফাস্ট ফরওয়ার্ড করুন %d সেকেন্ড ফাস্ট ফরওয়ার্ড করুন - কোনও আইটেম আবার চালাবেন না - একটি আইটেম আবার চালান - সবগুলি আইটেম আবার চালান - শাফেল মোড চালু করা হয়েছে - শাফেল মোড বন্ধ করা হয়েছে + \'বর্তমান\' মোড: রিপিট হয় না। \'রিপিট\' মোড টগল হয়। + \'বর্তমান\' মোড: একটি রিপিট হয়। \'রিপিট\' মোড টগল হয়। + \'বর্তমান\' মোড: সব রিপিট হয়। \'রিপিট\' মোড টগল হয়। + \'শাফেল\' মোড বন্ধ করে + \'শাফেল\' মোড চালু করে ভিআর মোড সাবটাইটেল বন্ধ করুন সাবটাইটেল চালু করুন diff --git a/libraries/ui/src/main/res/values-bs/strings.xml b/libraries/ui/src/main/res/values-bs/strings.xml index 8ce4cf7648..3793c330c1 100644 --- a/libraries/ui/src/main/res/values-bs/strings.xml +++ b/libraries/ui/src/main/res/values-bs/strings.xml @@ -39,11 +39,11 @@ Premotavanje %d sekunde naprijed Premotavanje %d sekundi naprijed - Ne ponavljaj - Ponovi jedno - Ponovi sve - Uključi nasumično - Isključi nasumično + Trenutni način: Ne ponavljaj. Uklj./isklj. ponavlj. + Trenutni način: Ponovi jedno. Uklj./isklj. ponavlj. + Trenutni način: Ponovi sve. Uklj./isklj. ponavlj. + Onemogućavanje nasumičnog načina rada + Omogućavanje nasumičnog načina rada VR način rada Onemogućavanje titlova Omogućavanje titlova diff --git a/libraries/ui/src/main/res/values-ca/strings.xml b/libraries/ui/src/main/res/values-ca/strings.xml index 46aef87dd1..ba2e8374a9 100644 --- a/libraries/ui/src/main/res/values-ca/strings.xml +++ b/libraries/ui/src/main/res/values-ca/strings.xml @@ -37,11 +37,11 @@ Avança ràpidament %d segon Avança ràpidament %d segons - No en repeteixis cap - Repeteix una - Repeteix tot - Activa reproducció aleatòria - Desactiva reproducció aleatòria + Actual: no repeteixis. Commuta mode repetició. + Actual: repeteix un. Commuta mode repetició. + Actual: repeteix tot. Commuta mode repetició. + Desactiva el mode aleatori + Activa el mode aleatori Mode RV Desactiva els subtítols Activa els subtítols diff --git a/libraries/ui/src/main/res/values-cs/strings.xml b/libraries/ui/src/main/res/values-cs/strings.xml index 6144f3cad3..bb0f85369a 100644 --- a/libraries/ui/src/main/res/values-cs/strings.xml +++ b/libraries/ui/src/main/res/values-cs/strings.xml @@ -41,11 +41,11 @@ Posunout vpřed o %d sekundy Posunout vpřed o %d sekund - Neopakovat - Opakovat jednu - Opakovat vše - Náhodné přehrávání zapnuto - Náhodné přehrávání vypnuto + Aktuálně: Nic neopakovat. Zapněte režim opakování. + Aktuálně: Opakovat jednu položku. Zapněte režim opakování. + Aktuálně: Opakovat vše. Zapněte režim opakování. + Deaktivovat náhodné přehrávání + Aktivovat náhodné přehrávání Režim VR Vypnout titulky Zapnout titulky diff --git a/libraries/ui/src/main/res/values-da/strings.xml b/libraries/ui/src/main/res/values-da/strings.xml index e7a07fef48..71ff36a1a3 100644 --- a/libraries/ui/src/main/res/values-da/strings.xml +++ b/libraries/ui/src/main/res/values-da/strings.xml @@ -37,11 +37,11 @@ Spol %d sekund frem Spol %d sekunder frem - Gentag ingen - Gentag én - Gentag alle - Bland er slået til - Bland er slået fra + Tilstand: Gentag ikke. Slå Gentag til/fra. + Tilstand: Gentag én. Slå Gentag til/fra. + Tilstand: Gentag alle. Slå Gentag til/fra. + Deaktiver Bland + Aktivér Bland VR-tilstand Deaktiver undertekster Aktivér undertekster diff --git a/libraries/ui/src/main/res/values-de/strings.xml b/libraries/ui/src/main/res/values-de/strings.xml index 05087df6a2..ff160f6a6a 100644 --- a/libraries/ui/src/main/res/values-de/strings.xml +++ b/libraries/ui/src/main/res/values-de/strings.xml @@ -37,11 +37,11 @@ %d Sekunde vorspulen %d Sekunden vorspulen - Keinen wiederholen - Einen wiederholen - Alle wiederholen - Zufallsmix an - Zufallsmix aus + Aktueller Modus: nichts wiederholen. Wiederholungsmodus ändern. + Aktueller Modus: einen Titel wiederholen. Wiederholungsmodus ändern. + Aktueller Modus: alles wiederholen. Wiederholungsmodus ändern. + Zufallsmix deaktivieren + Zufallsmix aktivieren VR-Modus Untertitel deaktivieren Untertitel aktivieren diff --git a/libraries/ui/src/main/res/values-el/strings.xml b/libraries/ui/src/main/res/values-el/strings.xml index d7d00f184e..c4ed289bef 100644 --- a/libraries/ui/src/main/res/values-el/strings.xml +++ b/libraries/ui/src/main/res/values-el/strings.xml @@ -37,11 +37,11 @@ Γρήγορη προώθηση κατά %d δευτερόλεπτο Γρήγορη προώθηση κατά %d δευτερόλεπτα - Καμία επανάληψη - Επανάληψη ενός κομματιού - Επανάληψη όλων - Τυχαία αναπαραγωγή: Ενεργή - Τυχαία αναπαραγωγή: Ανενεργή + Τρέχ. λειτουργία: Καμία επανάλ. Εναλλαγή λειτουργ. επανάλ. + Τρέχ. λειτουργία: Επανάλ. ενός. Εναλλαγή λειτουργ. επανάλ. + Τρέχ. λειτουργία: Επανάλ. όλων Εναλλαγή λειτουργ. επανάλ. + Απενεργ. λειτουργ. τυχαίας αναπαραγωγής + Ενεργοπ. λειτουργ. τυχαίας αναπαραγωγής Λειτουργία VR mode Απενεργοποίηση υπότιτλων Ενεργοποίηση υπότιτλων diff --git a/libraries/ui/src/main/res/values-en-rAU/strings.xml b/libraries/ui/src/main/res/values-en-rAU/strings.xml index c3a1c8a5aa..af85902797 100644 --- a/libraries/ui/src/main/res/values-en-rAU/strings.xml +++ b/libraries/ui/src/main/res/values-en-rAU/strings.xml @@ -37,11 +37,11 @@ Fast-forward %d second Fast-forward %d seconds - Repeat none - Repeat one - Repeat all - Shuffle on - Shuffle off + Current mode: Repeat none. Toggle repeat mode. + Current mode: Repeat one. Toggle repeat mode. + Current mode: Repeat all. Toggle repeat mode. + Disable shuffle mode + Enable shuffle mode VR mode Disable subtitles Enable subtitles diff --git a/libraries/ui/src/main/res/values-en-rGB/strings.xml b/libraries/ui/src/main/res/values-en-rGB/strings.xml index c3a1c8a5aa..af85902797 100644 --- a/libraries/ui/src/main/res/values-en-rGB/strings.xml +++ b/libraries/ui/src/main/res/values-en-rGB/strings.xml @@ -37,11 +37,11 @@ Fast-forward %d second Fast-forward %d seconds - Repeat none - Repeat one - Repeat all - Shuffle on - Shuffle off + Current mode: Repeat none. Toggle repeat mode. + Current mode: Repeat one. Toggle repeat mode. + Current mode: Repeat all. Toggle repeat mode. + Disable shuffle mode + Enable shuffle mode VR mode Disable subtitles Enable subtitles diff --git a/libraries/ui/src/main/res/values-en-rIN/strings.xml b/libraries/ui/src/main/res/values-en-rIN/strings.xml index c3a1c8a5aa..af85902797 100644 --- a/libraries/ui/src/main/res/values-en-rIN/strings.xml +++ b/libraries/ui/src/main/res/values-en-rIN/strings.xml @@ -37,11 +37,11 @@ Fast-forward %d second Fast-forward %d seconds - Repeat none - Repeat one - Repeat all - Shuffle on - Shuffle off + Current mode: Repeat none. Toggle repeat mode. + Current mode: Repeat one. Toggle repeat mode. + Current mode: Repeat all. Toggle repeat mode. + Disable shuffle mode + Enable shuffle mode VR mode Disable subtitles Enable subtitles diff --git a/libraries/ui/src/main/res/values-es-rUS/strings.xml b/libraries/ui/src/main/res/values-es-rUS/strings.xml index faaf430448..0bc0f6c546 100644 --- a/libraries/ui/src/main/res/values-es-rUS/strings.xml +++ b/libraries/ui/src/main/res/values-es-rUS/strings.xml @@ -37,11 +37,11 @@ Adelantar %d segundo Adelantar %d segundos - No repetir - Repetir uno - Repetir todo - Reprod. aleatoria activada - Reprod. aleatoria desactivada + Ahora: no repite. Cambia modo. + Ahora: repetir 1. Cambia modo. + Ahora: rep. todo. Cambia modo. + Inhabilitar reproducción aleatoria + Habilitar reproducción aleatoria Modo RV Inhabilitar subtítulos Habilitar subtítulos diff --git a/libraries/ui/src/main/res/values-es/strings.xml b/libraries/ui/src/main/res/values-es/strings.xml index f333c1d068..924d349038 100644 --- a/libraries/ui/src/main/res/values-es/strings.xml +++ b/libraries/ui/src/main/res/values-es/strings.xml @@ -37,11 +37,11 @@ Avanzar %d segundo Avanzar %d segundos - No repetir - Repetir uno - Repetir todo - Con reproducción aleatoria - Sin reproducción aleatoria + Modo actual: No repetir. Cambiar de modo. + Modo actual: Repetir uno. Cambiar de modo. + Modo actual: Repetir todo. Cambiar de modo. + Inhabilitar modo aleatorio + Habilitar modo aleatorio Modo RV Inhabilitar subtítulos Habilitar subtítulos diff --git a/libraries/ui/src/main/res/values-et/strings.xml b/libraries/ui/src/main/res/values-et/strings.xml index 1f15da226d..faa44e483f 100644 --- a/libraries/ui/src/main/res/values-et/strings.xml +++ b/libraries/ui/src/main/res/values-et/strings.xml @@ -37,11 +37,11 @@ Keri %d sekund edasi Keri %d sekundit edasi - Ära korda ühtegi - Korda ühte - Korda kõiki - Lülita juh. järj. esit. sisse - Lülita juh. järj. esit. välja + Praegune režiim: Ära korda. Aktiveerige kordusrežiim. + Praegune režiim: Korda ühte. Aktiveerige kordusrežiim. + Praegune režiim: Korda kõiki. Aktiveerige kordusrežiim. + Juhuesituse režiimi keelamine + Juhuesituse režiimi lubamine VR-režiim Keela subtiitrid Luba subtiitrid diff --git a/libraries/ui/src/main/res/values-eu/strings.xml b/libraries/ui/src/main/res/values-eu/strings.xml index 9fb7fa9ce0..90441518b1 100644 --- a/libraries/ui/src/main/res/values-eu/strings.xml +++ b/libraries/ui/src/main/res/values-eu/strings.xml @@ -37,11 +37,11 @@ Aurreratu %d segundo Aurreratu %d segundo - Ez errepikatu - Errepikatu bat - Errepikatu guztiak - Ausazko erreprodukzioa aktibatuta - Ausazko erreprodukzioa desaktibatuta + Oraingo modua: ez errepikatu. Aldatu errepikatzeko modua. + Oraingo modua: errepikatu bat. Aldatu errepikatzeko modua. + Oraingo modua: errepikatu guztiak. Aldatu errepikatzeko modua. + Desgaitu ausaz erreproduzitzeko modua + Gaitu ausaz erreproduzitzeko modua EBko modua Desgaitu azpitituluak Gaitu azpitituluak diff --git a/libraries/ui/src/main/res/values-fa/strings.xml b/libraries/ui/src/main/res/values-fa/strings.xml index 5fd0d954ca..c25aa14a7c 100644 --- a/libraries/ui/src/main/res/values-fa/strings.xml +++ b/libraries/ui/src/main/res/values-fa/strings.xml @@ -37,11 +37,11 @@ %d ثانیه سریع به‌جلو بردن %d ثانیه سریع به‌جلو بردن - تکرار هیچ‌کدام - یکبار تکرار - تکرار همه - پخش درهم روشن - پخش درهم خاموش + حالت کنونی: تکرار هیچ‌کدام. روشن/ خاموش کردن حالت تکرار. + حالت کنونی: تکرار یک مورد. روشن/ خاموش کردن حالت تکرار. + حالت کنونی: تکرار همه. روشن/ خاموش کردن حالت تکرار. + غیرفعال کردن حالت درهم + فعال کردن حالت درهم حالت واقعیت مجازی غیرفعال کردن زیرنویس فعال کردن زیرنویس diff --git a/libraries/ui/src/main/res/values-fi/strings.xml b/libraries/ui/src/main/res/values-fi/strings.xml index cc8acd5635..f57744643c 100644 --- a/libraries/ui/src/main/res/values-fi/strings.xml +++ b/libraries/ui/src/main/res/values-fi/strings.xml @@ -37,11 +37,11 @@ Siirry eteenpäin %d sekunti Siirry eteenpäin %d sekuntia - Ei uudelleentoistoa - Toista yksi uudelleen - Toista kaikki uudelleen - Satunnaistoisto käytössä - Satunnaistoisto ei käytössä + Tila: Älä toista. Vaihda. + Tila: Toista yksi. Vaihda. + Tila: Toista kaikki. Vaihda. + Poista satunnaistoisto käytöstä + Ota satunnaistoisto käyttöön VR-tila Poista tekstitykset käytöstä Ota tekstitykset käyttöön diff --git a/libraries/ui/src/main/res/values-fr-rCA/strings.xml b/libraries/ui/src/main/res/values-fr-rCA/strings.xml index fbcc917ee7..5faeb0b5b2 100644 --- a/libraries/ui/src/main/res/values-fr-rCA/strings.xml +++ b/libraries/ui/src/main/res/values-fr-rCA/strings.xml @@ -31,19 +31,17 @@ Reculer de %d seconde Reculer de %d secondes - Reculer de %d secondes Avance rapide Avancer rapidement de %d seconde Avancer rapidement de %d secondes - Avancer rapidement de %d secondes - Ne rien lire en boucle - Lire une chanson en boucle - Tout lire en boucle - Lecture aléatoire activée - Lecture aléatoire désactivée + Mode actuel : aucune répétition. Basculer le mode répétition. + Mode actuel : répéter une fois. Basculer le mode répétition. + Mode actuel : tout répéter. Basculer le mode répétition. + Désactiver le mode lecture aléatoire + Activer le mode lecture aléatoire Mode RV Désactiver les sous-titres Activer les sous-titres diff --git a/libraries/ui/src/main/res/values-fr/strings.xml b/libraries/ui/src/main/res/values-fr/strings.xml index 5c50bbd517..cc876a8bf3 100644 --- a/libraries/ui/src/main/res/values-fr/strings.xml +++ b/libraries/ui/src/main/res/values-fr/strings.xml @@ -31,19 +31,17 @@ Revenir en arrière de %d seconde Revenir en arrière de %d secondes - Revenir en arrière de %d secondes Avance rapide Avancer de %d seconde Avancer de %d secondes - Avancer de %d secondes - Ne rien lire en boucle - Lire un titre en boucle - Tout lire en boucle - Lecture aléatoire activée - Lecture aléatoire désactivée + Mode actuel : sans répétition. Changer le mode répétition. + Mode actuel : une répétition. Changer le mode répétition. + Mode actuel : tout répéter. Changer le mode répétition. + Désactiver le mode aléatoire + Activer le mode aléatoire Mode RV Désactiver les sous-titres Activer les sous-titres diff --git a/libraries/ui/src/main/res/values-gl/strings.xml b/libraries/ui/src/main/res/values-gl/strings.xml index fa815e60b1..932434af28 100644 --- a/libraries/ui/src/main/res/values-gl/strings.xml +++ b/libraries/ui/src/main/res/values-gl/strings.xml @@ -37,11 +37,11 @@ Avanza rapidamente %d segundo Avanza rapidamente %d segundos - Non repetir - Repetir unha pista - Repetir todas as pistas - Reprodución aleatoria activada - Reprodución aleat. desactivada + Modo actual: Non repetir. Alternar modo de repetición. + Modo actual: Repetir unha pista. Alternar modo de repetición. + Modo actual: Repetir todas as pistas. Alternar modo de repetición. + Desactivar modo de reprodución aleatoria + Activar modo de reprodución aleatoria Modo RV Desactiva os subtítulos Activa os subtítulos diff --git a/libraries/ui/src/main/res/values-gu/strings.xml b/libraries/ui/src/main/res/values-gu/strings.xml index b870f1400a..955ccf1f93 100644 --- a/libraries/ui/src/main/res/values-gu/strings.xml +++ b/libraries/ui/src/main/res/values-gu/strings.xml @@ -37,11 +37,11 @@ %d સેકન્ડ ફાસ્ટ ફૉરવર્ડ કરો %d સેકન્ડ ફાસ્ટ ફૉરવર્ડ કરો - કોઈ રિપીટ કરતા નહીં - એક રિપીટ કરો - બધાને રિપીટ કરો - શફલ ચાલુ છે - શફલ બંધ છે + વર્તમાન મોડ: કંઈ રિપીટ ન કરો. રિપીટ મોડ ટૉગલ કરો. + વર્તમાન મોડ: એક રિપીટ કરો. રિપીટ મોડ ટૉગલ કરો. + વર્તમાન મોડ: બધું રિપીટ કરો. રિપીટ મોડ ટૉગલ કરો. + શફલ મોડ બંધ કરો + શફલ મોડ ચાલુ કરો VR મોડ સબટાઇટલ બંધ કરો સબટાઇટલ ચાલુ કરો diff --git a/libraries/ui/src/main/res/values-hi/strings.xml b/libraries/ui/src/main/res/values-hi/strings.xml index c45305429f..fe18f2a16a 100644 --- a/libraries/ui/src/main/res/values-hi/strings.xml +++ b/libraries/ui/src/main/res/values-hi/strings.xml @@ -37,11 +37,11 @@ वीडियो को %d सेकंड आगे बढ़ाएं वीडियो को %d सेकंड आगे बढ़ाएं - किसी को न दोहराएं - एक को दोहराएं - सभी को दोहराएं - शफ़ल करना चालू है - शफ़ल करना बंद है + मौजूदा मोड: किसी को न दोहराएं. रिपीट मोड टॉगल करें. + मौजूदा मोड: एक को दोहराएं. रिपीट मोड टॉगल करें. + मौजूदा मोड: सभी को दोहराएं. रिपीट मोड टॉगल करें. + शफ़ल मोड बंद करें + शफ़ल मोड चालू करें VR मोड सबटाइटल बंद करें सबटाइटल चालू करें diff --git a/libraries/ui/src/main/res/values-hr/strings.xml b/libraries/ui/src/main/res/values-hr/strings.xml index 38f630ac58..320e47aef8 100644 --- a/libraries/ui/src/main/res/values-hr/strings.xml +++ b/libraries/ui/src/main/res/values-hr/strings.xml @@ -39,11 +39,11 @@ Premotavanje unaprijed za %d sekunde Premotavanje unaprijed za %d sekundi - Bez ponavljanja - Ponovi jedno - Ponovi sve - Nasumična reproduk. uključena - Nasumična reproduk. isključena + Trenutačno: Bez ponavljanja. Promijenite način ponavljanja. + Trenutačno: Ponovi jedno. Promijenite način ponavljanja. + Trenutačno: Ponovi sve. Promijenite način ponavljanja. + Onemogućite način nasumične reprodukcije + Omogućite način nasumične reprodukcije VR način Onemogući titlove Omogući titlove diff --git a/libraries/ui/src/main/res/values-hu/strings.xml b/libraries/ui/src/main/res/values-hu/strings.xml index c987398225..7f24082f54 100644 --- a/libraries/ui/src/main/res/values-hu/strings.xml +++ b/libraries/ui/src/main/res/values-hu/strings.xml @@ -37,11 +37,11 @@ Előretekerés %d másodperccel Előretekerés %d másodperccel - Nincs ismétlés - Egy szám ismétlése - Összes szám ismétlése - Keverés bekapcsolva - Keverés kikapcsolva + Jelenlegi: Nincs ismétlés. Ismétlés mód be/ki. + Jelenlegi: Egy ismétlése. Ismétlés mód be/ki. + Jelenlegi: Összes ismétlése. Ismétlés mód be/ki. + Keverés mód kikapcsolása + Keverés mód bekapcsolása VR-mód Feliratok kikapcsolása Feliratok bekapcsolása diff --git a/libraries/ui/src/main/res/values-hy/strings.xml b/libraries/ui/src/main/res/values-hy/strings.xml index 2b8c7a7612..f77b183118 100644 --- a/libraries/ui/src/main/res/values-hy/strings.xml +++ b/libraries/ui/src/main/res/values-hy/strings.xml @@ -37,11 +37,11 @@ %d վայրկյան առաջ տալ %d վայրկյան առաջ տալ - Չկրկնել - Կրկնել մեկը - Կրկնել բոլորը - Խառնումը միացված է - Խառնումն անջատված է + Ընթացիկ ռեժիմը՝ «Չկրկնել»։ Փոխել կրկնության ռեժիմը։ + Ընթացիկ ռեժիմը՝ «Կրկնել մեկը»։ Փոխել կրկնության ռեժիմը։ + Ընթացիկ ռեժիմը՝ «Կրկնել բոլորը»։ Փոխել կրկնության ռեժիմը։ + Անջատել խառը նվագարկման ռեժիմը + Միացնել խառը նվագարկման ռեժիմը VR ռեժիմ Անջատել ենթագրերը Միացնել ենթագրերը diff --git a/libraries/ui/src/main/res/values-in/strings.xml b/libraries/ui/src/main/res/values-in/strings.xml index dd5571b4d5..b010d3c739 100644 --- a/libraries/ui/src/main/res/values-in/strings.xml +++ b/libraries/ui/src/main/res/values-in/strings.xml @@ -37,11 +37,11 @@ Maju cepat %d detik Maju cepat %d detik - Jangan ulangi - Ulangi 1 - Ulangi semua - Acak aktif - Acak tidak aktif + Mode saat ini: Tidak berulang. Alihkan mode berulang. + Mode saat ini: Ulang sekali. Alihkan mode berulang. + Mode saat ini: Ulang semua. Alihkan mode berulang. + Nonaktifkan mode acak + Aktifkan mode acak Mode VR Nonaktifkan subtitel Aktifkan subtitel diff --git a/libraries/ui/src/main/res/values-is/strings.xml b/libraries/ui/src/main/res/values-is/strings.xml index 01f3bcb362..20f603c476 100644 --- a/libraries/ui/src/main/res/values-is/strings.xml +++ b/libraries/ui/src/main/res/values-is/strings.xml @@ -37,11 +37,11 @@ Spóla áfram um %d sekúndu Spóla áfram um %d sekúndur - Endurtaka ekkert - Endurtaka eitt - Endurtaka allt - Kveikt á stokkun - Slökkt á stokkun + Stilling nú: Endurtaka ekkert. Breyta endurtekningastillingu. + Stilling nú: Endurtaka eitt. Breyta endurtekningastillingu. + Stilling nú: Endurtaka allt. Breyta endurtekningastillingu. + Slökkva á stokkun + Kveikja á stokkun sýndarveruleikastilling Slökkva á skjátexta Kveikja á skjátexta diff --git a/libraries/ui/src/main/res/values-it/strings.xml b/libraries/ui/src/main/res/values-it/strings.xml index 8b50689367..b97ae06645 100644 --- a/libraries/ui/src/main/res/values-it/strings.xml +++ b/libraries/ui/src/main/res/values-it/strings.xml @@ -29,19 +29,19 @@ Interrompi Riavvolgi - Indietro di %d secondi + Indietro di %d secondo Indietro di %d secondi Avanti veloce - Avanti di %d secondi + Avanti di %d secondo Avanti di %d secondi - Non ripetere nulla - Ripeti uno - Ripeti tutto - Attiva riproduzione casuale - Disattiva riproduzione casuale + Modalità attuale: Non ripetere nulla. Cambia modalità di ripetizione. + Modalità attuale: Ripeti uno. Cambia modalità di ripetizione. + Modalità attuale: Ripeti tutto. Cambia modalità di ripetizione. + Disattiva la riproduzione casuale + Attiva la riproduzione casuale Modalità VR Disattiva i sottotitoli Attiva i sottotitoli diff --git a/libraries/ui/src/main/res/values-iw/strings.xml b/libraries/ui/src/main/res/values-iw/strings.xml index adbe03100b..c5499212c4 100644 --- a/libraries/ui/src/main/res/values-iw/strings.xml +++ b/libraries/ui/src/main/res/values-iw/strings.xml @@ -13,6 +13,20 @@ See the License for the specific language governing permissions and limitations under the License. --> + הצגת פקדי הנגן הסתרת פקדי הנגן @@ -41,11 +55,11 @@ הרצה %d שניות קדימה הרצה %d שניות קדימה - אל תחזור על אף פריט - חזור על פריט אחד - חזור על הכול - ההשמעה האקראית מופעלת - ההשמעה האקראית מושבתת + המצב הנוכחי: ללא חזרה. לחצן להחלפת מצב החזרה. + המצב הנוכחי: חזרה על פריט אחד. לחצן להחלפת מצב החזרה. + המצב הנוכחי: חזרה על כל הפריטים. לחצן להחלפת מצב החזרה. + השבתת מצב ההפעלה האקראית + הפעלת מצב ההפעלה האקראית מצב VR השבתת כתוביות הפעלת כתוביות diff --git a/libraries/ui/src/main/res/values-ja/strings.xml b/libraries/ui/src/main/res/values-ja/strings.xml index 7333b977d4..f8970f64ee 100644 --- a/libraries/ui/src/main/res/values-ja/strings.xml +++ b/libraries/ui/src/main/res/values-ja/strings.xml @@ -37,11 +37,11 @@ %d 秒早送り %d 秒早送り - リピートなし - 1 曲をリピート - 全曲をリピート - シャッフル ON - シャッフル OFF + 現在: リピートなし。モードを切り替えます。 + 現在: 1 曲リピート。モードを切り替えます。 + 現在: 全曲リピート。モードを切り替えます。 + シャッフル モードを無効にする + シャッフル モードを有効にする VR モード 字幕の無効化 字幕の有効化 diff --git a/libraries/ui/src/main/res/values-ka/strings.xml b/libraries/ui/src/main/res/values-ka/strings.xml index a18089e129..2ff75b72dd 100644 --- a/libraries/ui/src/main/res/values-ka/strings.xml +++ b/libraries/ui/src/main/res/values-ka/strings.xml @@ -37,11 +37,11 @@ წინ გადახვევა %d წამით წინ გადახვევა %d წამით - არცერთის გამეორება - ერთის გამეორება - ყველას გამეორება - არეულად დაკვრა ჩართულია - არეულად დაკვრა გამორთულია + მიმდინარე რეჟიმი: არაფრის გამეორება. გადართეთ გამეორების რეჟიმი. + მიმდინარე რეჟიმი: ერთის გამეორება. გადართეთ გამეორების რეჟიმი. + მიმდინარე რეჟიმი: ყველას გამეორება. გადართეთ გამეორების რეჟიმი. + არეულად დაკვრის რეჟიმის გათიშვა + არეულად დაკვრის რეჟიმის ჩართვა VR რეჟიმი სუბტიტრების გათიშვა სუბტიტრების ჩართვა diff --git a/libraries/ui/src/main/res/values-kk/strings.xml b/libraries/ui/src/main/res/values-kk/strings.xml index be14948ef1..86d41df02b 100644 --- a/libraries/ui/src/main/res/values-kk/strings.xml +++ b/libraries/ui/src/main/res/values-kk/strings.xml @@ -37,11 +37,11 @@ %d секунд алға айналдыру %d секунд алға айналдыру - Ешқайсысын қайталамау - Біреуін қайталау - Барлығын қайталау - Араластыру режимі қосулы. - Араластыру режимі өшірулі. + Қазіргі режим: еш мазмұн қайталанбайды. Қайталау режимін ауыстыру. + Қазіргі режим: бір мазмұн қайталанады. Қайталау режимін ауыстыру. + Қазіргі режим: барлық мазмұн қайталанады Қайталау режимін ауыстыру. + Араластыру режимін өшіру + Араластыру режимін қосу VR режимі Субтитрді өшіру Субтитрді қосу diff --git a/libraries/ui/src/main/res/values-km/strings.xml b/libraries/ui/src/main/res/values-km/strings.xml index 4e1f62bd90..3e8fd004a1 100644 --- a/libraries/ui/src/main/res/values-km/strings.xml +++ b/libraries/ui/src/main/res/values-km/strings.xml @@ -37,11 +37,11 @@ ខា​ទៅមុខ %d វិនាទី ខា​ទៅមុខ %d វិនាទី - មិន​លេង​ឡើងវិញ - លេង​ឡើង​វិញ​ម្ដង - លេង​ឡើងវិញ​ទាំងអស់ - បើក​ការ​ច្របល់ - បិទ​ការ​ច្របល់ + មុខងារបច្ចុប្បន្ន៖ មិនចាក់ឡើងវិញ។ បិទ/បើកមុខងារចាក់ឡើងវិញ។ + មុខងារបច្ចុប្បន្ន៖ ចាក់ឡើងវិញមួយ។ បិទ/បើកមុខងារចាក់ឡើងវិញ។ + មុខងារបច្ចុប្បន្ន៖ ចាក់ឡើងវិញទាំងអស់។ បិទ/បើកមុខងារចាក់ឡើងវិញ។ + បិទ​មុខងារច្របល់ + បើក​មុខងារច្របល់ មុខងារ VR បិទអក្សររត់ បើកអក្សររត់ diff --git a/libraries/ui/src/main/res/values-kn/strings.xml b/libraries/ui/src/main/res/values-kn/strings.xml index 28c9496216..45b2417f5b 100644 --- a/libraries/ui/src/main/res/values-kn/strings.xml +++ b/libraries/ui/src/main/res/values-kn/strings.xml @@ -37,11 +37,11 @@ %d ಸೆಕೆಂಡ್‌ಗಳಷ್ಟು ಫಾಸ್ಟ್ ಫಾರ್ವರ್ಡ್ ಮಾಡಿ %d ಸೆಕೆಂಡ್‌ಗಳಷ್ಟು ಫಾಸ್ಟ್ ಫಾರ್ವರ್ಡ್ ಮಾಡಿ - ಯಾವುದನ್ನೂ ಪುನರಾವರ್ತಿಸಬೇಡಿ - ಒಂದನ್ನು ಪುನರಾವರ್ತಿಸಿ - ಎಲ್ಲವನ್ನು ಪುನರಾವರ್ತಿಸಿ - ಶಫಲ್ ಆನ್ ಆಗಿದೆ - ಶಫಲ್ ಆಫ್ ಆಗಿದೆ + ಈಗಿನ ಮೋಡ್: ಯಾವುದನ್ನು ರಿಪೀಟ್ ಮಾಡಬೇಡಿ. ರಿಪೀಟ್ ಮೋಡ್ ಟಾಗಲ್ ಮಾಡಿ. + ಈಗಿನ ಮೋಡ್: ಒಂದನ್ನು ರಿಪೀಟ್ ಮಾಡಿ. ರಿಪೀಟ್ ಮೋಡ್ ಟಾಗಲ್ ಮಾಡಿ. + ಈಗಿನ ಮೋಡ್: ಎಲ್ಲವನ್ನು ರಿಪೀಟ್ ಮಾಡಿ. ರಿಪೀಟ್ ಮೋಡ್ ಟಾಗಲ್ ಮಾಡಿ. + ಶಫಲ್ ಮೋಡ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ + ಶಫಲ್ ಮೋಡ್ ಅನ್ನುಸಕ್ರಿಯಗೊಳಿಸಿ VR ಮೋಡ್ ಸಬ್‌ಟೈಟಲ್‌ಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ ಸಬ್‌ಟೈಟಲ್‌ಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ @@ -56,7 +56,7 @@ 2 ಪಟ್ಟು ವೀಡಿಯೊ - ಆಡಿಯೊ + ಆಡಿಯೋ ಪಠ್ಯ ಯಾವುದೂ ಅಲ್ಲ ಸ್ವಯಂ diff --git a/libraries/ui/src/main/res/values-ko/strings.xml b/libraries/ui/src/main/res/values-ko/strings.xml index 0c06366b57..b6e8d231ea 100644 --- a/libraries/ui/src/main/res/values-ko/strings.xml +++ b/libraries/ui/src/main/res/values-ko/strings.xml @@ -37,11 +37,11 @@ %d초 빨리 감기 %d초 빨리 감기 - 반복 안함 - 현재 미디어 반복 - 모두 반복 - 셔플 사용 - 셔플 사용 안함 + 현재 모드: 반복 안함. 반목 모드 전환. + 현재 모드: 한 개 반복. 반목 모드 전환. + 현재 모드: 모두 반복. 반목 모드 전환. + 셔플 모드 사용 중지 + 셔플 모드 사용 설정 가상 현실 모드 자막 사용 중지 자막 사용 설정 diff --git a/libraries/ui/src/main/res/values-ky/strings.xml b/libraries/ui/src/main/res/values-ky/strings.xml index 4cb3932247..29601c0253 100644 --- a/libraries/ui/src/main/res/values-ky/strings.xml +++ b/libraries/ui/src/main/res/values-ky/strings.xml @@ -37,11 +37,11 @@ %d секунд алдыга түрдүрүү %d секунд алдыга түрдүрүү - Кайталанбасын - Бирөөнү кайталоо - Баарын кайталоо - Аралаштыруу күйүк - Аралаштыруу өчүк + Учурдагы режим: Кайталанбасын. Кайталоо режимин өчүрүү/күйгүзүү. + Учурдагы режим: Бир медианы кайталоо. Кайталоо режимин өчүрүү/күйгүзүү. + Учурдагы режим: Баарын кайталоо. Кайталоо режимин өчүрүү/күйгүзүү. + Аралаштыруу режимин өчүрүү + Аралаштыруу режимин күйгүзүү VR режими Коштомо жазууларды өчүрүү Коштомо жазууларды иштетүү diff --git a/libraries/ui/src/main/res/values-lo/strings.xml b/libraries/ui/src/main/res/values-lo/strings.xml index 8581b0bbc0..bd0f103425 100644 --- a/libraries/ui/src/main/res/values-lo/strings.xml +++ b/libraries/ui/src/main/res/values-lo/strings.xml @@ -37,11 +37,11 @@ ເລື່ອນໄປໜ້າ %d ວິນາທີ ເລື່ອນໄປໜ້າ %d ວິນາທີ - ບໍ່ຫຼິ້ນຊ້ຳ - ຫຼິ້ນຊໍ້າ - ຫຼິ້ນຊ້ຳທັງໝົດ - ເປີດການສຸ່ມເພງແລ້ວ - ປິດການສຸ່ມເພງແລ້ວ + ໂໝດປັດຈຸບັນ: ບໍ່ເປີດຊ້ຳ. ສະຫຼັບໂໝດເປີດຊ້ຳ. + ໂໝດປັດຈຸບັນ: ເປີດຊ້ຳອັນດຽວ. ສະຫຼັບໂໝດເປີດຊ້ຳ. + ໂໝດປັດຈຸບັນ: ເປີດຊ້ຳທັງໝົດ. ສະຫຼັບໂໝດເປີດຊ້ຳ. + ປິດການນຳໃຊ້ໂໝດສັບ + ເປີດການນຳໃຊ້ໂໝດສັບ ໂໝດ VR ປິດການນຳໃຊ້ຄຳແປ ເປີດການນຳໃຊ້ຄຳແປ diff --git a/libraries/ui/src/main/res/values-lt/strings.xml b/libraries/ui/src/main/res/values-lt/strings.xml index b8233d76a9..f1d221e9bf 100644 --- a/libraries/ui/src/main/res/values-lt/strings.xml +++ b/libraries/ui/src/main/res/values-lt/strings.xml @@ -41,11 +41,11 @@ Prasukti pirmyn %d sekundės Prasukti pirmyn %d sekundžių - Nekartoti nieko - Kartoti vieną - Kartoti viską - Maišymas įjungtas - Maišymas išjungtas + Dabart. rež.: nekart. nieko. Perj. pakart. r. + Dabart. rež.: kart. vieną. Perj. pakart. r. + Dabart. rež.: kart. viską. Perj. pakart. r. + Išjungti maišymo režimą + Įgalinti maišymo režimą VR režimas Išjungti subtitrus Įgalinti subtitrus diff --git a/libraries/ui/src/main/res/values-lv/strings.xml b/libraries/ui/src/main/res/values-lv/strings.xml index 61f1c8f4dd..0d0ec51c3c 100644 --- a/libraries/ui/src/main/res/values-lv/strings.xml +++ b/libraries/ui/src/main/res/values-lv/strings.xml @@ -39,11 +39,11 @@ Pārtīt uz priekšu par %d sekundi Pārtīt uz priekšu par %d sekundēm - Neatkārtot nevienu - Atkārtot vienu - Atkārtot visu - Atsk. jauktā secībā ieslēgta - Atsk. jauktā secībā izslēgta + Iesl.: neatkārtot nevienu. Pārslēdziet režīmu. + Iesl.: atkārtot vienu. Pārslēdziet režīmu. + Iesl.: atkārtot visu. Pārslēdziet režīmu. + Atspējot atskaņošanu jauktā secībā + Iespējot atskaņošanu jauktā secībā VR režīms Atspējot subtitrus Iespējot subtitrus diff --git a/libraries/ui/src/main/res/values-mk/strings.xml b/libraries/ui/src/main/res/values-mk/strings.xml index 8a4ff03039..a5d13326e4 100644 --- a/libraries/ui/src/main/res/values-mk/strings.xml +++ b/libraries/ui/src/main/res/values-mk/strings.xml @@ -37,11 +37,11 @@ Премотајте напред %d секунда Премотајте напред %d секунди - Не повторувај ниту една - Повтори една - Повтори ги сите - Мешањето е вклучено - Мешањето е исклучено + Тековно: не повторувај. Вклучи/исклучи повторување. + Тековно: повтори една. Вклучи/исклучи повторување. + Тековно: повтори ги сите. Вклучи/исклучи повторување. + Оневозможи режим на мешање + Овозможи режим на мешање Режим на VR Оневозможете ги титловите Овозможете ги титловите diff --git a/libraries/ui/src/main/res/values-ml/strings.xml b/libraries/ui/src/main/res/values-ml/strings.xml index 12de370917..4d1e4e995a 100644 --- a/libraries/ui/src/main/res/values-ml/strings.xml +++ b/libraries/ui/src/main/res/values-ml/strings.xml @@ -37,11 +37,11 @@ വേഗത്തിൽ %d സെക്കൻഡ് മുന്നോട്ട് നീക്കുക വേഗത്തിൽ %d സെക്കൻഡ് മുന്നോട്ട് നീക്കുക - ഒന്നും ആവർത്തിക്കരുത് - ഒരെണ്ണം ആവർത്തിക്കുക - എല്ലാം ആവർത്തിക്കുക - ഇടകലർത്തൽ ഓണാക്കുക - ഇടകലർത്തൽ ഓഫാക്കുക + നിലവിലെ മോഡ്: ഒന്നും ആവർത്തിക്കരുത്. ആവർത്തന മോഡ് മാറ്റൂ. + നിലവിലെ മോഡ്: ഒന്ന് ആവർത്തിക്കുക. ആവർത്തന മോഡ് മാറ്റൂ. + നിലവിലെ മോഡ്: എല്ലാം ആവർത്തിക്കുക. ആവർത്തന മോഡ് മാറ്റൂ. + ഷഫിൾ മോഡ് പ്രവർത്തനരഹിതമാക്കുക + ഷഫിൾ മോഡ് പ്രവർത്തനക്ഷമമാക്കുക VR മോഡ് സബ്‌ടൈറ്റിലുകൾ പ്രവർത്തനരഹിതമാക്കുക സബ്‌ടൈറ്റിലുകൾ പ്രവർത്തനക്ഷമമാക്കുക diff --git a/libraries/ui/src/main/res/values-mn/strings.xml b/libraries/ui/src/main/res/values-mn/strings.xml index e9fbf7fe53..56273ce0e5 100644 --- a/libraries/ui/src/main/res/values-mn/strings.xml +++ b/libraries/ui/src/main/res/values-mn/strings.xml @@ -37,11 +37,11 @@ %d секундээр хурдан урагшлуулах %d секундээр хурдан урагшлуулах - Алийг нь ч дахин тоглуулахгүй - Одоогийн тоглуулж буй медиаг дахин тоглуулах - Бүгдийг нь дахин тоглуулах - Холих асаалттай - Холих унтраалттай + Одоогийн горим: Алийг нь ч дахин тоглуулахгүй. Дахин тоглуулах горимыг асаана уу/унтраана уу. + Одоогийн горим: Нэгийг дахин тоглуулна уу. Дахин тоглуулах горимыг асаана уу/унтраана уу. + Одоогийн горим: Бүгдийг дахин тоглуулна уу. Дахин тоглуулах горимыг асаана уу/унтраана уу. + Холих горимыг идэвхгүй болгох + Холих горимыг идэвхжүүлэх VR горим Хадмалыг идэвхгүй болгох Хадмалыг идэвхжүүлэх diff --git a/libraries/ui/src/main/res/values-mr/strings.xml b/libraries/ui/src/main/res/values-mr/strings.xml index 5641af2a47..303f5ca52f 100644 --- a/libraries/ui/src/main/res/values-mr/strings.xml +++ b/libraries/ui/src/main/res/values-mr/strings.xml @@ -37,11 +37,11 @@ %d सेकंद फास्ट फॉरवर्ड करा %d सेकंद फास्ट फॉरवर्ड करा - रीपीट करू नका - एक रीपीट करा - सर्व रीपीट करा - शफल करा सुरू करा - शफल करा बंद करा + सध्याचा मोड: काहीही रिपीट करू नका. रिपीट मोड टॉगल करा. + सध्याचा मोड: एक रिपीट करा. रिपीट मोड टॉगल करा. + सध्याचा मोड: सर्व रिपीट करा. रिपीट मोड टॉगल करा. + शफल मोड बंद करा + शफल मोड सुरू करा VR मोड सबटायटल बंद करा सबटायटल सुरू करा diff --git a/libraries/ui/src/main/res/values-ms/strings.xml b/libraries/ui/src/main/res/values-ms/strings.xml index 60cce968c2..2758851781 100644 --- a/libraries/ui/src/main/res/values-ms/strings.xml +++ b/libraries/ui/src/main/res/values-ms/strings.xml @@ -37,11 +37,11 @@ Mundar laju %d saat Mundar laju %d saat - Jangan ulang - Ulang satu - Ulang semua - Hidupkan rombak - Matikan rombak + Mod semasa: Tidak berulang. Togol mod ulang. + Mod semasa: Ulang satu. Togol mod ulang. + Mod semasa: Ulang semua. Togol mod ulang. + Lumpuhkan mod rombak + Dayakan mod rombak Mod VR Lumpuhkan sari kata Dayakan sari kata diff --git a/libraries/ui/src/main/res/values-my/strings.xml b/libraries/ui/src/main/res/values-my/strings.xml index 07f0ad05ff..89ad8e5636 100644 --- a/libraries/ui/src/main/res/values-my/strings.xml +++ b/libraries/ui/src/main/res/values-my/strings.xml @@ -37,11 +37,11 @@ ရှေ့သို့ %d စက္ကန့်ရစ်ရန် ရှေ့သို့ %d စက္ကန့်ရစ်ရန် - မည်သည်ကိုမျှ ပြန်မကျော့ရန် - တစ်ခုကို ပြန်ကျော့ရန် - အားလုံး ပြန်ကျော့ရန် - ရောသမမွှေကို ဖွင့်ထားသည် - ရောသမမွှေကို ပိတ်ထားသည် + လက်ရှိမုဒ်- ပြန်မကျော့ပါနှင့်။ ပြန်ကျော့မုဒ် ပြောင်းရန်။ + လက်ရှိမုဒ်- တစ်ခုပြန်ကျော့ရန်။ ပြန်ကျော့မုဒ် ပြောင်းရန်။ + လက်ရှိမုဒ်- အားလုံးပြန်ကျော့ရန်။ ပြန်ကျော့မုဒ် ပြောင်းရန်။ + ရောသမမွှေမုဒ် ပိတ်ရန် + ရောသမမွှေမုဒ် ဖွင့်ရန် VR မုဒ် စာတန်းထိုး ပိတ်ပါ စာတန်းထိုး ဖွင့်ပါ diff --git a/libraries/ui/src/main/res/values-nb/strings.xml b/libraries/ui/src/main/res/values-nb/strings.xml index 03a2216962..075270b6dc 100644 --- a/libraries/ui/src/main/res/values-nb/strings.xml +++ b/libraries/ui/src/main/res/values-nb/strings.xml @@ -37,11 +37,11 @@ Spol %d sekund fremover Spol %d sekunder fremover - Ikke gjenta noen - Gjenta én - Gjenta alle - Tilfeldig rekkefølge er på - Tilfeldig rekkefølge er av + Modus: gjenta ingen. Endre gjentakelsesmodus. + Modus: gjenta én. Endre gjentakelsesmodus. + Modus: gjenta alle. Endre gjentakelsesmodus. + Slå av modus for tilfeldig rekkefølge + Slå på modus for tilfeldig rekkefølge VR-modus Slå av undertekstene Slå på undertekstene diff --git a/libraries/ui/src/main/res/values-ne/strings.xml b/libraries/ui/src/main/res/values-ne/strings.xml index 2806463f0b..586aea713f 100644 --- a/libraries/ui/src/main/res/values-ne/strings.xml +++ b/libraries/ui/src/main/res/values-ne/strings.xml @@ -37,11 +37,11 @@ %d सेकेन्ड फास्ट फर्वार्ड गर्नुहोस् %d सेकेन्ड फास्ट फर्वार्ड गर्नुहोस् - कुनै पनि नदोहोर्‍याउनुहोस् - एउटा दोहोर्‍याउनुहोस् - सबै दोहोर्‍याउनुहोस् - मिसाउने सुविधा सक्रिय छ - मिसाउने सुविधा निष्क्रिय छ + हालको मोड: नदोहोरिने। दोहोरिने मोड टगल गर्नुहोस्। + हालको मोड: एक पटक दोहोरिने। दोहोरिने मोड टगल गर्नुहोस्। + हालको मोड: सबै दोहोरिने। दोहोरिने मोड टगल गर्नुहोस्। + सफल मोड अफ गर्नुहोस् + सफल मोड अन गर्नुहोस् VR मोड सबटाइटलहरू असक्षम पार्नुहोस् सबटाइटलहरू सक्षम पार्नुहोस् diff --git a/libraries/ui/src/main/res/values-nl/strings.xml b/libraries/ui/src/main/res/values-nl/strings.xml index 0b7c590443..eaf3659200 100644 --- a/libraries/ui/src/main/res/values-nl/strings.xml +++ b/libraries/ui/src/main/res/values-nl/strings.xml @@ -37,11 +37,11 @@ %d seconde vooruitspoelen %d seconden vooruitspoelen - Niets herhalen - Eén herhalen - Alles herhalen - Shuffle aan - Shuffle uit + Huidige modus: Niets herhalen. Herhaalmodus schakelen. + Huidige modus: 1 herhalen. Herhaalmodus schakelen. + Huidige modus: Alles herhalen. Herhaalmodus schakelen. + Shuffle uitzetten + Shuffle aanzetten VR-modus Ondertiteling uitzetten Ondertiteling aanzetten diff --git a/libraries/ui/src/main/res/values-pa/strings.xml b/libraries/ui/src/main/res/values-pa/strings.xml index efe5b908ab..e2579cd646 100644 --- a/libraries/ui/src/main/res/values-pa/strings.xml +++ b/libraries/ui/src/main/res/values-pa/strings.xml @@ -37,11 +37,11 @@ ਤੇਜ਼ੀ ਨਾਲ %d ਸਕਿੰਟ ਅੱਗੇ ਕਰੋ ਤੇਜ਼ੀ ਨਾਲ %d ਸਕਿੰਟ ਅੱਗੇ ਕਰੋ - ਕਿਸੇ ਨੂੰ ਨਾ ਦੁਹਰਾਓ - ਇੱਕ ਵਾਰ ਦੁਹਰਾਓ - ਸਾਰਿਆਂ ਨੂੰ ਦੁਹਰਾਓ - \'ਬੇਤਰਤੀਬ ਕਰੋ\' ਮੋਡ ਚਾਲੂ ਹੈ - \'ਬੇਤਰਤੀਬ ਕਰੋ\' ਮੋਡ ਬੰਦ ਹੈ + ਮੌਜੂਦਾ ਮੋਡ: ਕਿਸੇ ਨੂੰ ਨਾ ਦੁਹਰਾਓ। ਦੁਹਰਾਓ ਮੋਡ ਟੌਗਲ ਕਰੋ। + ਮੌਜੂਦਾ ਮੋਡ: ਇੱਕ ਨੂੰ ਦੁਹਰਾਓ। ਦੁਹਰਾਓ ਮੋਡ ਟੌਗਲ ਕਰੋ। + ਮੌਜੂਦਾ ਮੋਡ: ਸਭ ਦੁਹਰਾਓ। ਦੁਹਰਾਓ ਮੋਡ ਟੌਗਲ ਕਰੋ। + ਬੇਤਰਤੀਬ ਮੋਡ ਬੰਦ ਕਰੋ + ਬੇਤਰਤੀਬ ਮੋਡ ਚਾਲੂ ਕਰੋ VR ਮੋਡ ਉਪਸਿਰਲੇਖਾਂ ਨੂੰ ਬੰਦ ਕਰੋ ਉਪਸਿਰਲੇਖਾਂ ਨੂੰ ਚਾਲੂ ਕਰੋ diff --git a/libraries/ui/src/main/res/values-pl/strings.xml b/libraries/ui/src/main/res/values-pl/strings.xml index f12915791b..ec5bfca158 100644 --- a/libraries/ui/src/main/res/values-pl/strings.xml +++ b/libraries/ui/src/main/res/values-pl/strings.xml @@ -41,11 +41,11 @@ Przewiń do przodu o %d sekund Przewiń do przodu o %d sekundy - Nie powtarzaj - Powtórz jeden - Powtórz wszystkie - Włącz odtwarzanie losowe - Wyłącz odtwarzanie losowe + Bieżący tryb: Nie powtarzaj. Przełącz na tryb powtarzania. + Bieżący tryb: Powtórz jeden. Przełącz na tryb powtarzania. + Bieżący tryb: Powtórz wszystkie. Przełącz na tryb powtarzania. + Wyłącz tryb odtwarzania losowego + Włącz tryb odtwarzania losowego Tryb VR Wyłącz napisy Włącz napisy diff --git a/libraries/ui/src/main/res/values-pt-rPT/strings.xml b/libraries/ui/src/main/res/values-pt-rPT/strings.xml index f791718436..6e70f79c53 100644 --- a/libraries/ui/src/main/res/values-pt-rPT/strings.xml +++ b/libraries/ui/src/main/res/values-pt-rPT/strings.xml @@ -29,19 +29,19 @@ Parar Recuar - Retroceder %d segundo(s) + Retroceder %d segundo Retroceder %d segundos Avançar - Avançar %d segundo(s) + Avançar %d segundo Avançar %d segundos - Não repetir nenhum - Repetir um - Repetir tudo - Reprodução aleatória ativada - Reprodução aleatória desativ. + Modo atual: não repetir. Ative/des. repetição. + Modo atual: repetir um. Ative/des. repetição. + Modo atual: repet. tudo. Ative/des. repetição. + Desativar modo aleatório + Ativar modo aleatório Modo de RV Desativar legendas Ativar legendas diff --git a/libraries/ui/src/main/res/values-pt/strings.xml b/libraries/ui/src/main/res/values-pt/strings.xml index af04650a35..80a7f42669 100644 --- a/libraries/ui/src/main/res/values-pt/strings.xml +++ b/libraries/ui/src/main/res/values-pt/strings.xml @@ -37,11 +37,11 @@ Avançar %d segundo Avançar %d segundos - Não repetir - Repetir uma - Repetir tudo - Ordem aleatória ativada - Ordem aleatória desativada + Modo atual: não repetir. Alternar modo de repetição. + Modo atual: repetir um item. Alternar modo de repetição. + Modo atual: repetir tudo. Alternar modo de repetição. + Desativar o modo de ordem aleatória + Ativar o modo de ordem aleatória Modo RV Desativar legendas Ativar legendas diff --git a/libraries/ui/src/main/res/values-ro/strings.xml b/libraries/ui/src/main/res/values-ro/strings.xml index db77aa55d1..0448518b56 100644 --- a/libraries/ui/src/main/res/values-ro/strings.xml +++ b/libraries/ui/src/main/res/values-ro/strings.xml @@ -39,11 +39,11 @@ Derulează rapid înainte cu %d secunde Derulează rapid înainte cu %d de secunde - Nu repetați niciunul - Repetați unul - Repetați-le pe toate - Redare aleatorie activată - Redare aleatorie dezactivată + Mod actual: nu se repetă. Comutați modul repetare. + Mod actual: se repetă una. Comutați modul repetare. + Mod curent: se repetă tot. Comutați modul repetare. + Dezactivați modul sortare aleatorie + Activați modul sortare aleatorie Mod RV Dezactivați subtitrările Activați subtitrările diff --git a/libraries/ui/src/main/res/values-ru/strings.xml b/libraries/ui/src/main/res/values-ru/strings.xml index 542517da8b..36d9b4c01e 100644 --- a/libraries/ui/src/main/res/values-ru/strings.xml +++ b/libraries/ui/src/main/res/values-ru/strings.xml @@ -41,11 +41,11 @@ Перемотать на %d секунд вперед Перемотать на %d секунды вперед - Не повторять - Повторять трек - Повторять все - Перемешивание включено - Перемешивание отключено + Выбрано: не повторять. Изменить режим повтора. + Выбрано: повторять один раз. Изменить режим повтора. + Выбрано: повторять все. Изменить режим повтора. + Отключить перемешивание + Включить перемешивание VR-режим Выключить субтитры Включить субтитры diff --git a/libraries/ui/src/main/res/values-si/strings.xml b/libraries/ui/src/main/res/values-si/strings.xml index 2f56ca1699..a78f859718 100644 --- a/libraries/ui/src/main/res/values-si/strings.xml +++ b/libraries/ui/src/main/res/values-si/strings.xml @@ -37,11 +37,11 @@ තත්පර %dක් වේගයෙන් ඉදිරියට තත්පර %dක් වේගයෙන් ඉදිරියට - කිසිවක් පුනරාවර්තනය නොකරන්න - එකක් පුනරාවර්තනය කරන්න - සියල්ල පුනරාවර්තනය කරන්න - කලවම් කිරීම ක්‍රියාත්මකයි - කලවම් කිරීම ක්‍රියා විරහිතයි + වත්මන් ප්‍රකාරය: කිසිවක් පුනරාවර්තනය නොකරන්න. පුනරාවර්තන ප්‍රකාරය ටොගල කරන්න. + වත්මන් ප්‍රකාරය: එකක් පුනරාවර්තනය කරන්න. පුනරාවර්තන ප්‍රකාරය ටොගල කරන්න. + වත්මන් ප්‍රකාරය: සියල්ල පුනරාවර්තනය කරන්න. පුනරාවර්තන ප්‍රකාරය ටොගල කරන්න. + කළවම් ප්‍රකාරය අබල කරන්න + කළවම් ප්‍රකාරය සබල කරන්න VR ප්‍රකාරය උපසිරැසි අබල කරන්න උපසිරැසි සබල කරන්න diff --git a/libraries/ui/src/main/res/values-sk/strings.xml b/libraries/ui/src/main/res/values-sk/strings.xml index 4f365fb034..75204eed52 100644 --- a/libraries/ui/src/main/res/values-sk/strings.xml +++ b/libraries/ui/src/main/res/values-sk/strings.xml @@ -41,11 +41,11 @@ Pretočiť dopredu o %d sekundy Pretočiť dopredu o %d sekúnd - Neopakovať - Opakovať jednu - Opakovať všetko - Náhodné prehrávanie je zapnuté - Náhodné prehrávanie je vypnuté + Aktuálny režim: Neopakovať. Prepnúť režim opakovania + Aktuálny režim: Opakovať jedno. Prepnúť režim opakovania + Aktuálny režim: Opakovať všetky. Prepnúť režim opakovania + Vypnúť režim náhodného prehrávania + Zapnúť režim náhodného prehrávania režim VR Zakázať titulky Povoliť titulky diff --git a/libraries/ui/src/main/res/values-sl/strings.xml b/libraries/ui/src/main/res/values-sl/strings.xml index 1ddc0ba757..5bc58e7ae8 100644 --- a/libraries/ui/src/main/res/values-sl/strings.xml +++ b/libraries/ui/src/main/res/values-sl/strings.xml @@ -41,11 +41,11 @@ Premik naprej za %d sekunde Premik naprej za %d sekund - Brez ponavljanja - Ponavljanje ene - Ponavljanje vseh - Naklj. predvajanje vklopljeno - Naklj. predvajanje izklopljeno + Trenutni način: Brez ponavljanja. Preklopite način ponavljanja. + Trenutni način: Ponovi eno. Preklopite način ponavljanja. + Trenutni način: Ponovi vse. Preklopite način ponavljanja. + Onemogočanje načina naključnega predvajanja + Omogočanje načina naključnega predvajanja Način VR Onemogočanje podnapisov Omogočanje podnapisov diff --git a/libraries/ui/src/main/res/values-sq/strings.xml b/libraries/ui/src/main/res/values-sq/strings.xml index 59941e5e8e..0357753ac8 100644 --- a/libraries/ui/src/main/res/values-sq/strings.xml +++ b/libraries/ui/src/main/res/values-sq/strings.xml @@ -37,11 +37,11 @@ Shpejt përpara %d sekondë Shpejt përpara %d sekonda - Mos përsërit asnjë - Përsërit një - Përsërit të gjitha - Përzierja aktive - Përzierja joaktive + Modaliteti aktual: Mos përsërit asnjë. Aktivizo/çaktivizo modalitetin e përsëritjes. + Modaliteti aktual: Përsërit një. Aktivizo/çaktivizo modalitetin e përsëritjes. + Modaliteti aktual: Përsërit të gjitha. Aktivizo/çaktivizo modalitetin e përsëritjes. + Çaktivizo modalitetin e përzierjes + Aktivizo modalitetin e përzierjes Modaliteti RV Çaktivizo titrat Aktivizo titrat diff --git a/libraries/ui/src/main/res/values-sr/strings.xml b/libraries/ui/src/main/res/values-sr/strings.xml index c748764e9b..d20d287b1c 100644 --- a/libraries/ui/src/main/res/values-sr/strings.xml +++ b/libraries/ui/src/main/res/values-sr/strings.xml @@ -39,11 +39,11 @@ Премотајте %d секунде унапред Премотајте %d секунди унапред - Не понављај ниједну - Понови једну - Понови све - Насумично пуштање је укључено - Насумично пуштање је искључено + Ваш режим: Без понављања. Укључите/искључите. + Ваш режим: Понови једно. Укључите/искључите. + Ваш режим: Понови све. Укључите/искључите. + Онемогућите насумични режим + Омогућите насумични режим ВР режим Онемогући титлове Омогући титлове diff --git a/libraries/ui/src/main/res/values-sv/strings.xml b/libraries/ui/src/main/res/values-sv/strings.xml index bb23c56b56..73edb04ff0 100644 --- a/libraries/ui/src/main/res/values-sv/strings.xml +++ b/libraries/ui/src/main/res/values-sv/strings.xml @@ -37,11 +37,11 @@ Spola framåt %d sekund Spola framåt %d sekunder - Upprepa inga - Upprepa en - Upprepa alla - Blanda spår - Blanda inte spår + Aktuellt läge: Upprepa inga. Ändra läge för upprepning. + Aktuellt läge: Upprepa en. Ändra läge för upprepning. + Aktuellt läge: Upprepa alla. Ändra läge för upprepning. + Inaktivera blandningsläget + Aktivera blandningsläget VR-läge Inaktivera undertexter Aktivera undertexter diff --git a/libraries/ui/src/main/res/values-sw/strings.xml b/libraries/ui/src/main/res/values-sw/strings.xml index c594838faf..015e31701d 100644 --- a/libraries/ui/src/main/res/values-sw/strings.xml +++ b/libraries/ui/src/main/res/values-sw/strings.xml @@ -37,11 +37,11 @@ Sogeza mbele haraka kwa sekunde %d Sogeza mbele haraka kwa sekunde %d - Usirudie yoyote - Rudia moja - Rudia zote - Hali ya kuchanganya imewashwa - Hali ya kuchanganya imezimwa + Hali ya sasa: Usirudie yoyote Geuza hali ya kurudia. + Hali ya sasa: Rudia moja. Geuza hali ya kurudia. + Hali ya sasa: Rudia zote. Geuza hali ya kurudia. + Zima hali ya kuchanganya + Washa hali ya kuchanganya Hali ya Uhalisia Pepe Zima manukuu Washa manukuu diff --git a/libraries/ui/src/main/res/values-ta/strings.xml b/libraries/ui/src/main/res/values-ta/strings.xml index d107f42a10..36172865b9 100644 --- a/libraries/ui/src/main/res/values-ta/strings.xml +++ b/libraries/ui/src/main/res/values-ta/strings.xml @@ -37,14 +37,14 @@ %d வினாடி ஃபாஸ்ட் ஃபார்வர்ட் ஆகும் %d வினாடிகள் ஃபாஸ்ட் ஃபார்வர்ட் ஆகும் - எதையும் மீண்டும் இயக்காதே - இதை மட்டும் மீண்டும் இயக்கு - அனைத்தையும் மீண்டும் இயக்கு - கலைத்துப் போடுதல்: ஆன் - கலைத்துப் போடுதல்: ஆஃப் + தற்போதைய பயன்முறை: எதையும் மீண்டும் இயக்காது. மீண்டும் இயக்குதலை நிலைமாற்றும். + தற்போதைய பயன்முறை: ஒன்றை மட்டும் மீண்டும் இயக்கும். மீண்டும் இயக்குதலை நிலைமாற்றும். + தற்போதைய பயன்முறை: அனைத்தையும் மீண்டும் இயக்கும். மீண்டும் இயக்குதலை நிலைமாற்றும். + கலைத்துப் போடும் பயன்முறையை முடக்கும் + கலைத்துப் போடும் பயன்முறையை இயக்கும் VR பயன்முறை - வசனங்களை முடக்கும் - வசனங்களை இயக்கும் + சப்டைட்டில்களை முடக்கும் + சப்டைட்டில்களை இயக்கும் வேகம் 0.25x diff --git a/libraries/ui/src/main/res/values-te/strings.xml b/libraries/ui/src/main/res/values-te/strings.xml index 435128311e..124b8a99ba 100644 --- a/libraries/ui/src/main/res/values-te/strings.xml +++ b/libraries/ui/src/main/res/values-te/strings.xml @@ -37,11 +37,11 @@ %d సెకండ్ వేగంగా ఫార్వర్డ్ చేయండి %d సెకన్లు వేగంగా ఫార్వర్డ్ చేయండి - దేన్నీ పునరావృతం చేయకండి - ఒకదాన్ని పునరావృతం చేయండి - అన్నింటినీ పునరావృతం చేయండి - షఫుల్‌ను ఆన్ చేస్తుంది - షఫుల్‌ను ఆఫ్ చేస్తుంది + ప్రస్తుత మోడ్: ఏదీ పునరావృతం చేయవద్దు. పునరావృతం మోడ్‌ను టోగుల్ చేయండి. + ప్రస్తుత మోడ్: ఒకదానిని పునరావృతం చేయండి. పునరావృతం మోడ్‌ను టోగుల్ చేయండి. + ప్రస్తుత మోడ్: అన్నింటిని పునరావృతం చేయండి. పునరావృతం మోడ్‌ను టోగుల్ చేయండి. + షఫుల్ మోడ్‌ను డిజేబుల్ చేయండి + షఫుల్ మోడ్‌ను ఎనేబుల్ చేయండి వర్చువల్ రియాలిటీ మోడ్ ఉప శీర్షికలను డిజేబుల్ చేయి ఉప శీర్షికలను ఎనేబుల్ చేయి diff --git a/libraries/ui/src/main/res/values-th/strings.xml b/libraries/ui/src/main/res/values-th/strings.xml index 387e9fffe3..fdb108348e 100644 --- a/libraries/ui/src/main/res/values-th/strings.xml +++ b/libraries/ui/src/main/res/values-th/strings.xml @@ -37,11 +37,11 @@ กรอไปข้างหน้า %d วินาที กรอไปข้างหน้า %d วินาที - ไม่เล่นซ้ำ - เล่นซ้ำเพลงเดียว - เล่นซ้ำทั้งหมด - เปิดการสุ่มเพลงอยู่ - ปิดการสุ่มเพลงอยู่ + โหมดปัจจุบัน: ไม่เล่นซ้ำ สลับโหมดเล่นซ้ำ + โหมดปัจจุบัน: เล่นซ้ำรายการเดียว สลับโหมดเล่นซ้ำ + โหมดปัจจุบัน: เล่นซ้ำทั้งหมด สลับโหมดเล่นซ้ำ + ปิดใช้โหมดสุ่มเพลง + เปิดใช้โหมดสุ่มเพลง โหมด VR ปิดใช้คำบรรยาย เปิดใช้คำบรรยาย diff --git a/libraries/ui/src/main/res/values-tl/strings.xml b/libraries/ui/src/main/res/values-tl/strings.xml index 5715b393ac..0757b261da 100644 --- a/libraries/ui/src/main/res/values-tl/strings.xml +++ b/libraries/ui/src/main/res/values-tl/strings.xml @@ -37,11 +37,11 @@ I-fast forward nang %d segundo I-fast forward nang %d na segundo - Walang uulitin - Mag-ulit ng isa - Ulitin lahat - Naka-on ang pag-shuffle - Naka-off ang pag-shuffle + Current mode: Walang uulitin. I-toggle ang repeat mode. + Current mode: Walang uulitin. I-toggle ang repeat mode. + Current mode: Ulitin lahat. I-toggle ang repeat mode. + I-disable ang shuffle mode + I-enable ang shuffle mode VR mode I-disable ang mga subtitle I-enable ang mga subtitle diff --git a/libraries/ui/src/main/res/values-tr/strings.xml b/libraries/ui/src/main/res/values-tr/strings.xml index f367f44bb2..b2fd8b6fa4 100644 --- a/libraries/ui/src/main/res/values-tr/strings.xml +++ b/libraries/ui/src/main/res/values-tr/strings.xml @@ -37,11 +37,11 @@ %d saniye ileri sar %d saniye ileri sar - Hiçbirini tekrarlama - Birini tekrarla - Tümünü tekrarla - Karıştırma açık - Karıştırma kapalı + Geçerli mod: Tekrarlama. Tekrarlamayı aç/kapat. + Geçerli mod: Birini tekrarla. Tekrarlamayı aç/kapat. + Geçerli mod: Tümünü tekrarla. Tekrarlamayı aç/kapat. + Karıştırma modunu devre dışı bırak + Karıştırma modunu etkinleştir VR modu Altyazıları devre dışı bırak Altyazıları etkinleştir diff --git a/libraries/ui/src/main/res/values-uk/strings.xml b/libraries/ui/src/main/res/values-uk/strings.xml index f8f2c47064..2ffcc61d1c 100644 --- a/libraries/ui/src/main/res/values-uk/strings.xml +++ b/libraries/ui/src/main/res/values-uk/strings.xml @@ -41,11 +41,11 @@ Перемотати вперед на %d секунд Перемотати вперед на %d секунди - Не повторювати - Повторити 1 - Повторити всі - Перемішування ввімкнено - Перемішування вимкнено + Поточний режим: не повторювати. Перемкнути режим повторення. + Поточний режим: повторювати один медіафайл. Перемкнути режим повторення. + Поточний режим: повторювати все. Перемкнути режим повторення. + Вимкнути режим перемішування + Увімкнути режим перемішування Режим віртуальної реальності Вимкнути субтитри Увімкнути субтитри diff --git a/libraries/ui/src/main/res/values-ur/strings.xml b/libraries/ui/src/main/res/values-ur/strings.xml index f7b46d01f4..1e410c9712 100644 --- a/libraries/ui/src/main/res/values-ur/strings.xml +++ b/libraries/ui/src/main/res/values-ur/strings.xml @@ -37,11 +37,11 @@ %d سیکنڈ تیزی سے فارورڈ کریں %d سیکنڈز تیزی سے فارورڈ کریں - کسی کو نہ دہرائیں - ایک کو دہرائیں - سبھی کو دہرائیں - شفل آن - شفل آف + موجودہ موڈ: کچھ نہ دہرائیں۔ رپیٹ موڈ ٹوگل کریں۔ + موجودہ موڈ: ایک دہرائیں۔ رپیٹ موڈ ٹوگل کریں۔ + موجودہ موڈ: سبھی دہرائیں۔ رپیٹ موڈ ٹوگل کریں۔ + شفل موڈ کو غیر فعال کریں + شفل موڈ کو فعال کریں VR موڈ سب ٹائٹلز کو غیر فعال کریں سب ٹائٹلز کو فعال کریں diff --git a/libraries/ui/src/main/res/values-uz/strings.xml b/libraries/ui/src/main/res/values-uz/strings.xml index f0c4677b9c..f7639dd95b 100644 --- a/libraries/ui/src/main/res/values-uz/strings.xml +++ b/libraries/ui/src/main/res/values-uz/strings.xml @@ -37,11 +37,11 @@ %d soniya oldinga %d soniya oldinga - Takrorlanmasin - Bittasini takrorlash - Hammasini takrorlash - Tasodifiy ijro yoqilgan - Tasodifiy ijro yoqilmagan + Joriy rejim: Hech qaysi takrorlanmaydi. Takrorlash rejimiga oʻting. + Joriy rejim: Bittasi takrorlanadi. Takrorlash rejimiga oʻting. + Joriy rejim: Barchasi takrorlanadi. Takrorlash rejimiga oʻting. + Tasodifiy rejimni faolsizlantiring + Tasodifiy rejimni yoqing VR rejimi Taglavhalarni faolsizlantirish Taglavhalarni yoqish diff --git a/libraries/ui/src/main/res/values-vi/strings.xml b/libraries/ui/src/main/res/values-vi/strings.xml index 290d96f167..400d321f5e 100644 --- a/libraries/ui/src/main/res/values-vi/strings.xml +++ b/libraries/ui/src/main/res/values-vi/strings.xml @@ -37,11 +37,11 @@ Tua nhanh %d giây Tua nhanh %d giây - Không lặp lại - Lặp lại một - Lặp lại tất cả - Chế độ trộn bài đang bật - Chế độ trộn bài đang tắt + Chế độ hiện tại: Không lặp lại. Bật/tắt chế độ lặp lại. + Chế độ hiện tại: Lặp lại một nội dung. Bật/tắt chế độ lặp lại. + Chế độ hiện tại: Lặp lại tất cả nội dung. Bật/tắt chế độ lặp lại. + Tắt chế độ trộn bài + Bật chế độ trộn bài Chế độ thực tế ảo Tắt phụ đề Bật phụ đề diff --git a/libraries/ui/src/main/res/values-zh-rCN/strings.xml b/libraries/ui/src/main/res/values-zh-rCN/strings.xml index 436449df6d..4fedf2ae07 100644 --- a/libraries/ui/src/main/res/values-zh-rCN/strings.xml +++ b/libraries/ui/src/main/res/values-zh-rCN/strings.xml @@ -37,11 +37,11 @@ 快进 %d 秒 快进 %d 秒 - 不重复播放 - 重复播放一项 - 全部重复播放 - 随机播放功能已开启 - 随机播放功能已关闭 + 当前模式:不重复。切换重复播放模式。 + 当前模式:重复播放当前项目。切换重复播放模式。 + 当前模式:重复播放所有项目。切换重复播放模式。 + 停用随机播放模式 + 启用随机播放模式 VR 模式 停用字幕 启用字幕 diff --git a/libraries/ui/src/main/res/values-zh-rHK/strings.xml b/libraries/ui/src/main/res/values-zh-rHK/strings.xml index 4fe9ee9b41..88a0239c57 100644 --- a/libraries/ui/src/main/res/values-zh-rHK/strings.xml +++ b/libraries/ui/src/main/res/values-zh-rHK/strings.xml @@ -37,11 +37,11 @@ 快轉 %d 秒 快轉 %d 秒 - 不重複播放 - 重複播放單一項目 - 全部重複播放 - 已開啟隨機播放功能 - 已關閉隨機播放功能 + 宜家嘅模式:唔重複播放。轉做重複播放模式。 + 宜家嘅模式:重複播放一個項目。轉做重複播放模式。 + 宜家嘅模式:重複播放所有項目。轉做重複播放模式。 + 停用隨機播放模式 + 啟用隨機播放模式 虛擬現實模式 停用字幕 啟用字幕 diff --git a/libraries/ui/src/main/res/values-zh-rTW/strings.xml b/libraries/ui/src/main/res/values-zh-rTW/strings.xml index 591afff6b5..27dc2bcfd6 100644 --- a/libraries/ui/src/main/res/values-zh-rTW/strings.xml +++ b/libraries/ui/src/main/res/values-zh-rTW/strings.xml @@ -37,11 +37,11 @@ 快轉 %d 秒 快轉 %d 秒 - 不重複播放 - 重複播放單一項目 - 重複播放所有項目 - 隨機播放已開啟 - 隨機播放已關閉 + 目前模式:不重複播放。切換重複播放模式。 + 目前模式:重複播放單一項目。切換重複播放模式。 + 目前模式:重複播放所有項目。切換重複播放模式。 + 停用隨機播放模式 + 啟用隨機播放模式 虛擬實境模式 停用字幕 (Subtitle) 啟用字幕 (Subtitle) diff --git a/libraries/ui/src/main/res/values-zu/strings.xml b/libraries/ui/src/main/res/values-zu/strings.xml index 409adc0e70..05d78e556e 100644 --- a/libraries/ui/src/main/res/values-zu/strings.xml +++ b/libraries/ui/src/main/res/values-zu/strings.xml @@ -37,11 +37,11 @@ Dlulisela phambili ngamasekhondi angu-%d Dlulisela phambili ngamasekhondi angu-%d - Phinda okungekho - Phinda okukodwa - Phinda konke - Ukushova kuvuliwe - Ukushova kuvaliwe + Imodeli yamanje: Ungaphindi lutho. Guqula imodi yokuphinda. + Imodi yamanje: Phinda kanye. Guqula imodi yokuphinda. + Imodi yamanje: Phinda konke. Guqula imodi yokuphinda. + Khubaza imodi yokushova + Nika amandla imodi yokushova Inqubo ye-VR Khubaza imibhalo engezansi Nika amandla imibhalo engezansi From 691b392b246522fb664cdb1ce196e16c3449926c Mon Sep 17 00:00:00 2001 From: olly Date: Wed, 15 Jun 2022 15:00:47 +0000 Subject: [PATCH 20/73] Don't export broadcast receivers that don't require it Issue: google/ExoPlayer#10287 PiperOrigin-RevId: 455131138 --- .../common/util/NetworkTypeObserver.java | 2 +- .../androidx/media3/common/util/Util.java | 50 +++++++++++++++++++ .../exoplayer/AudioBecomingNoisyManager.java | 5 +- .../media3/exoplayer/StreamVolumeManager.java | 2 +- .../exoplayer/audio/AudioCapabilities.java | 4 +- .../audio/AudioCapabilitiesReceiver.java | 6 +-- .../exoplayer/scheduler/Requirements.java | 8 +-- .../scheduler/RequirementsWatcher.java | 2 +- 8 files changed, 64 insertions(+), 15 deletions(-) diff --git a/libraries/common/src/main/java/androidx/media3/common/util/NetworkTypeObserver.java b/libraries/common/src/main/java/androidx/media3/common/util/NetworkTypeObserver.java index c6421efd61..4e97ab796c 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/NetworkTypeObserver.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/NetworkTypeObserver.java @@ -94,7 +94,7 @@ private NetworkTypeObserver(Context context) { networkType = C.NETWORK_TYPE_UNKNOWN; IntentFilter filter = new IntentFilter(); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); - context.registerReceiver(/* receiver= */ new Receiver(), filter); + Util.registerReceiverNotExported(context, new Receiver(), filter); } /** diff --git a/libraries/common/src/main/java/androidx/media3/common/util/Util.java b/libraries/common/src/main/java/androidx/media3/common/util/Util.java index bb0c2205ee..02fab9ce93 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/Util.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/Util.java @@ -34,9 +34,11 @@ import android.annotation.SuppressLint; import android.app.Activity; import android.app.UiModeManager; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -189,6 +191,54 @@ public static byte[] toByteArray(InputStream inputStream) throws IOException { return outputStream.toByteArray(); } + /** + * Registers a {@link BroadcastReceiver} that's not intended to receive broadcasts from other + * apps. This will be enforced by specifying {@link Context#RECEIVER_NOT_EXPORTED} if {@link + * #SDK_INT} is 33 or above. + * + * @param context The context on which {@link Context#registerReceiver} will be called. + * @param receiver The {@link BroadcastReceiver} to register. This value may be null. + * @param filter Selects the Intent broadcasts to be received. + * @return The first sticky intent found that matches {@code filter}, or null if there are none. + */ + @UnstableApi + @Nullable + public static Intent registerReceiverNotExported( + Context context, @Nullable BroadcastReceiver receiver, IntentFilter filter) { + if (SDK_INT < 33) { + return context.registerReceiver(receiver, filter); + } else { + return context.registerReceiver(receiver, filter, Context.RECEIVER_NOT_EXPORTED); + } + } + + /** + * Registers a {@link BroadcastReceiver} that's not intended to receive broadcasts from other + * apps. This will be enforced by specifying {@link Context#RECEIVER_NOT_EXPORTED} if {@link + * #SDK_INT} is 33 or above. + * + * @param context The context on which {@link Context#registerReceiver} will be called. + * @param receiver The {@link BroadcastReceiver} to register. This value may be null. + * @param filter Selects the Intent broadcasts to be received. + * @param handler Handler identifying the thread that will receive the Intent. + * @return The first sticky intent found that matches {@code filter}, or null if there are none. + */ + @UnstableApi + @Nullable + public static Intent registerReceiverNotExported( + Context context, BroadcastReceiver receiver, IntentFilter filter, Handler handler) { + if (SDK_INT < 33) { + return context.registerReceiver(receiver, filter, /* broadcastPermission= */ null, handler); + } else { + return context.registerReceiver( + receiver, + filter, + /* broadcastPermission= */ null, + handler, + Context.RECEIVER_NOT_EXPORTED); + } + } + /** * Calls {@link Context#startForegroundService(Intent)} if {@link #SDK_INT} is 26 or higher, or * {@link Context#startService(Intent)} otherwise. diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioBecomingNoisyManager.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioBecomingNoisyManager.java index 04fd1482bd..625c6090b6 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioBecomingNoisyManager.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/AudioBecomingNoisyManager.java @@ -21,6 +21,7 @@ import android.content.IntentFilter; import android.media.AudioManager; import android.os.Handler; +import androidx.media3.common.util.Util; /* package */ final class AudioBecomingNoisyManager { @@ -46,8 +47,8 @@ public AudioBecomingNoisyManager(Context context, Handler eventHandler, EventLis */ public void setEnabled(boolean enabled) { if (enabled && !receiverRegistered) { - context.registerReceiver( - receiver, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); + Util.registerReceiverNotExported( + context, receiver, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); receiverRegistered = true; } else if (!enabled && receiverRegistered) { context.unregisterReceiver(receiver); diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/StreamVolumeManager.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/StreamVolumeManager.java index c5a8230154..1fc7dc4828 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/StreamVolumeManager.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/StreamVolumeManager.java @@ -75,7 +75,7 @@ public StreamVolumeManager(Context context, Handler eventHandler, Listener liste VolumeChangeReceiver receiver = new VolumeChangeReceiver(); IntentFilter filter = new IntentFilter(VOLUME_CHANGED_ACTION); try { - applicationContext.registerReceiver(receiver, filter); + Util.registerReceiverNotExported(applicationContext, receiver, filter); this.receiver = receiver; } catch (RuntimeException e) { Log.w(TAG, "Error registering stream volume receiver", e); diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilities.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilities.java index 9888db45a6..6cb10f0731 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilities.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilities.java @@ -88,8 +88,8 @@ public final class AudioCapabilities { @SuppressWarnings("InlinedApi") public static AudioCapabilities getCapabilities(Context context) { Intent intent = - context.registerReceiver( - /* receiver= */ null, new IntentFilter(AudioManager.ACTION_HDMI_AUDIO_PLUG)); + Util.registerReceiverNotExported( + context, /* receiver= */ null, new IntentFilter(AudioManager.ACTION_HDMI_AUDIO_PLUG)); return getCapabilities(context, intent); } diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilitiesReceiver.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilitiesReceiver.java index 241e914ff0..1cfef2accc 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilitiesReceiver.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioCapabilitiesReceiver.java @@ -90,12 +90,10 @@ public AudioCapabilities register() { if (externalSurroundSoundSettingObserver != null) { externalSurroundSoundSettingObserver.register(); } - Intent stickyIntent = null; + @Nullable Intent stickyIntent = null; if (receiver != null) { IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_HDMI_AUDIO_PLUG); - stickyIntent = - context.registerReceiver( - receiver, intentFilter, /* broadcastPermission= */ null, handler); + stickyIntent = Util.registerReceiverNotExported(context, receiver, intentFilter, handler); } audioCapabilities = AudioCapabilities.getCapabilities(context, stickyIntent); return audioCapabilities; diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/scheduler/Requirements.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/scheduler/Requirements.java index 53ad113710..ab87aa361c 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/scheduler/Requirements.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/scheduler/Requirements.java @@ -184,8 +184,8 @@ public boolean checkRequirements(Context context) { private boolean isDeviceCharging(Context context) { @Nullable Intent batteryStatus = - context.registerReceiver( - /* receiver= */ null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + Util.registerReceiverNotExported( + context, /* receiver= */ null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); if (batteryStatus == null) { return false; } @@ -203,8 +203,8 @@ private boolean isDeviceIdle(Context context) { } private boolean isStorageNotLow(Context context) { - return context.registerReceiver( - /* receiver= */ null, new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW)) + return Util.registerReceiverNotExported( + context, /* receiver= */ null, new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW)) == null; } diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/scheduler/RequirementsWatcher.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/scheduler/RequirementsWatcher.java index c7ae614e05..541224221c 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/scheduler/RequirementsWatcher.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/scheduler/RequirementsWatcher.java @@ -111,7 +111,7 @@ public RequirementsWatcher(Context context, Listener listener, Requirements requ filter.addAction(Intent.ACTION_DEVICE_STORAGE_OK); } receiver = new DeviceStatusChangeReceiver(); - context.registerReceiver(receiver, filter, null, handler); + Util.registerReceiverNotExported(context, receiver, filter, handler); return notMetRequirements; } From 646bf565c35c43ff59d4a7d51ee60036368339b6 Mon Sep 17 00:00:00 2001 From: tonihei Date: Wed, 15 Jun 2022 15:46:43 +0000 Subject: [PATCH 21/73] Update initial bitrate estimates #minor-release PiperOrigin-RevId: 455140203 --- .../upstream/DefaultBandwidthMeter.java | 455 +++++++++--------- .../upstream/DefaultBandwidthMeterTest.java | 3 + 2 files changed, 226 insertions(+), 232 deletions(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/upstream/DefaultBandwidthMeter.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/upstream/DefaultBandwidthMeter.java index 5a7c7e268b..0c9352f003 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/upstream/DefaultBandwidthMeter.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/upstream/DefaultBandwidthMeter.java @@ -47,27 +47,27 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList /** Default initial Wifi bitrate estimate in bits per second. */ public static final ImmutableList DEFAULT_INITIAL_BITRATE_ESTIMATES_WIFI = - ImmutableList.of(5_400_000L, 3_300_000L, 2_000_000L, 1_300_000L, 760_000L); + ImmutableList.of(4_800_000L, 3_100_000L, 2_100_000L, 1_500_000L, 800_000L); /** Default initial 2G bitrate estimates in bits per second. */ public static final ImmutableList DEFAULT_INITIAL_BITRATE_ESTIMATES_2G = - ImmutableList.of(1_700_000L, 820_000L, 450_000L, 180_000L, 130_000L); + ImmutableList.of(1_500_000L, 1_000_000L, 730_000L, 440_000L, 170_000L); /** Default initial 3G bitrate estimates in bits per second. */ public static final ImmutableList DEFAULT_INITIAL_BITRATE_ESTIMATES_3G = - ImmutableList.of(2_300_000L, 1_300_000L, 1_000_000L, 820_000L, 570_000L); + ImmutableList.of(2_200_000L, 1_400_000L, 1_100_000L, 910_000L, 620_000L); /** Default initial 4G bitrate estimates in bits per second. */ public static final ImmutableList DEFAULT_INITIAL_BITRATE_ESTIMATES_4G = - ImmutableList.of(3_400_000L, 2_000_000L, 1_400_000L, 1_000_000L, 620_000L); + ImmutableList.of(3_000_000L, 1_900_000L, 1_400_000L, 1_000_000L, 660_000L); /** Default initial 5G-NSA bitrate estimates in bits per second. */ public static final ImmutableList DEFAULT_INITIAL_BITRATE_ESTIMATES_5G_NSA = - ImmutableList.of(7_500_000L, 5_200_000L, 3_700_000L, 1_800_000L, 1_100_000L); + ImmutableList.of(6_000_000L, 4_100_000L, 3_200_000L, 1_800_000L, 1_000_000L); /** Default initial 5G-SA bitrate estimates in bits per second. */ public static final ImmutableList DEFAULT_INITIAL_BITRATE_ESTIMATES_5G_SA = - ImmutableList.of(3_300_000L, 1_900_000L, 1_700_000L, 1_500_000L, 1_200_000L); + ImmutableList.of(2_800_000L, 2_400_000L, 1_600_000L, 1_100_000L, 950_000L); /** * Default initial bitrate estimate used when the device is offline or the network type cannot be @@ -477,402 +477,393 @@ private static boolean isTransferAtFullNetworkSpeed(DataSpec dataSpec, boolean i private static int[] getInitialBitrateCountryGroupAssignment(String country) { switch (country) { case "AE": - return new int[] {1, 4, 4, 4, 3, 2}; + return new int[] {1, 4, 4, 4, 4, 0}; case "AG": - return new int[] {2, 3, 1, 2, 2, 2}; + return new int[] {2, 4, 1, 2, 2, 2}; + case "AI": + return new int[] {0, 2, 0, 3, 2, 2}; case "AM": - return new int[] {2, 3, 2, 4, 2, 2}; - case "AR": - return new int[] {2, 4, 1, 1, 2, 2}; + return new int[] {2, 3, 2, 3, 2, 2}; + case "AO": + return new int[] {4, 4, 3, 2, 2, 2}; case "AS": - return new int[] {2, 2, 2, 3, 2, 2}; + return new int[] {2, 2, 3, 3, 2, 2}; + case "AT": + return new int[] {1, 0, 1, 1, 0, 0}; case "AU": - return new int[] {0, 1, 0, 1, 2, 2}; + return new int[] {0, 1, 1, 1, 2, 0}; + case "AW": + return new int[] {1, 3, 4, 4, 2, 2}; + case "BA": + return new int[] {1, 2, 1, 1, 2, 2}; + case "BD": + return new int[] {2, 1, 3, 3, 2, 2}; case "BE": - return new int[] {0, 0, 3, 3, 2, 2}; + return new int[] {0, 1, 4, 4, 3, 2}; case "BF": return new int[] {4, 3, 4, 3, 2, 2}; case "BH": - return new int[] {1, 2, 2, 4, 4, 2}; + return new int[] {1, 2, 1, 3, 4, 2}; case "BJ": - return new int[] {4, 4, 3, 4, 2, 2}; - case "BN": - return new int[] {3, 2, 1, 1, 2, 2}; + return new int[] {4, 4, 3, 3, 2, 2}; case "BO": - return new int[] {1, 3, 3, 2, 2, 2}; - case "BQ": - return new int[] {1, 2, 2, 0, 2, 2}; + return new int[] {1, 2, 3, 2, 2, 2}; case "BS": - return new int[] {4, 2, 2, 3, 2, 2}; + return new int[] {4, 4, 2, 2, 2, 2}; case "BT": return new int[] {3, 1, 3, 2, 2, 2}; + case "BW": + return new int[] {3, 2, 1, 0, 2, 2}; case "BY": - return new int[] {0, 1, 1, 3, 2, 2}; + return new int[] {0, 1, 2, 3, 2, 2}; case "BZ": - return new int[] {2, 4, 2, 2, 2, 2}; + return new int[] {2, 4, 2, 1, 2, 2}; case "CA": - return new int[] {0, 2, 1, 2, 4, 1}; + return new int[] {0, 2, 2, 2, 3, 2}; case "CD": - return new int[] {4, 2, 3, 1, 2, 2}; - case "CF": return new int[] {4, 2, 3, 2, 2, 2}; - case "CI": - return new int[] {3, 3, 3, 4, 2, 2}; - case "CK": - return new int[] {2, 2, 2, 1, 2, 2}; - case "AO": + case "CH": + return new int[] {0, 0, 0, 1, 0, 2}; case "CM": - return new int[] {3, 4, 3, 2, 2, 2}; + return new int[] {3, 3, 3, 3, 2, 2}; case "CN": - return new int[] {2, 0, 2, 2, 3, 1}; + return new int[] {2, 0, 1, 1, 3, 2}; case "CO": - return new int[] {2, 2, 4, 2, 2, 2}; + return new int[] {2, 3, 4, 3, 2, 2}; case "CR": - return new int[] {2, 2, 4, 4, 2, 2}; + return new int[] {2, 3, 4, 4, 2, 2}; case "CV": - return new int[] {2, 3, 1, 0, 2, 2}; + return new int[] {2, 1, 0, 0, 2, 2}; + case "BN": case "CW": return new int[] {2, 2, 0, 0, 2, 2}; - case "CY": - return new int[] {1, 0, 0, 0, 1, 2}; case "DE": - return new int[] {0, 0, 2, 2, 1, 2}; - case "DJ": - return new int[] {4, 1, 4, 4, 2, 2}; + return new int[] {0, 1, 2, 2, 2, 3}; case "DK": - return new int[] {0, 0, 1, 0, 0, 2}; + return new int[] {0, 0, 3, 2, 0, 2}; + case "DO": + return new int[] {3, 4, 4, 4, 4, 2}; case "EC": - return new int[] {2, 4, 2, 1, 2, 2}; - case "EG": - return new int[] {3, 4, 2, 3, 2, 2}; + return new int[] {2, 3, 2, 1, 2, 2}; case "ET": - return new int[] {4, 4, 3, 1, 2, 2}; + return new int[] {4, 3, 3, 1, 2, 2}; case "FI": - return new int[] {0, 0, 0, 1, 0, 2}; + return new int[] {0, 0, 0, 3, 0, 2}; case "FJ": - return new int[] {3, 1, 3, 3, 2, 2}; + return new int[] {3, 1, 2, 2, 2, 2}; case "FM": - return new int[] {3, 2, 4, 2, 2, 2}; + return new int[] {4, 2, 4, 1, 2, 2}; case "FR": - return new int[] {1, 1, 2, 1, 1, 1}; - case "GA": - return new int[] {2, 3, 1, 1, 2, 2}; + return new int[] {1, 2, 3, 1, 0, 2}; case "GB": - return new int[] {0, 0, 1, 1, 2, 3}; + return new int[] {0, 0, 1, 1, 1, 1}; case "GE": - return new int[] {1, 1, 1, 3, 2, 2}; + return new int[] {1, 1, 1, 2, 2, 2}; case "BB": + case "DM": case "FO": - case "GG": + case "GI": return new int[] {0, 2, 0, 0, 2, 2}; - case "GH": - return new int[] {3, 2, 3, 2, 2, 2}; + case "AF": + case "GM": + return new int[] {4, 3, 3, 4, 2, 2}; case "GN": return new int[] {4, 3, 4, 2, 2, 2}; case "GQ": - return new int[] {4, 2, 3, 4, 2, 2}; + return new int[] {4, 2, 1, 4, 2, 2}; case "GT": - return new int[] {2, 3, 2, 1, 2, 2}; - case "AW": - case "GU": - return new int[] {1, 2, 4, 4, 2, 2}; - case "BW": + return new int[] {2, 3, 2, 2, 2, 2}; + case "CG": + case "EG": + case "GW": + return new int[] {3, 4, 3, 3, 2, 2}; case "GY": - return new int[] {3, 4, 1, 0, 2, 2}; + return new int[] {3, 2, 2, 1, 2, 2}; case "HK": return new int[] {0, 1, 2, 3, 2, 0}; case "HU": return new int[] {0, 0, 0, 1, 3, 2}; case "ID": - return new int[] {3, 2, 3, 3, 3, 2}; + return new int[] {3, 1, 2, 2, 3, 2}; case "ES": case "IE": return new int[] {0, 1, 1, 1, 2, 2}; + case "CL": case "IL": - return new int[] {1, 1, 2, 3, 4, 2}; - case "IM": - return new int[] {0, 2, 0, 1, 2, 2}; + return new int[] {1, 2, 2, 2, 3, 2}; case "IN": - return new int[] {1, 1, 3, 2, 4, 3}; + return new int[] {1, 1, 3, 2, 3, 3}; + case "IQ": + return new int[] {3, 2, 2, 3, 2, 2}; case "IR": - return new int[] {3, 0, 1, 1, 3, 0}; + return new int[] {3, 0, 1, 1, 4, 1}; case "IT": - return new int[] {0, 1, 0, 1, 1, 2}; - case "JE": - return new int[] {3, 2, 1, 2, 2, 2}; - case "DO": + return new int[] {0, 0, 0, 1, 1, 2}; case "JM": - return new int[] {3, 4, 4, 4, 2, 2}; + return new int[] {2, 4, 3, 2, 2, 2}; + case "JO": + return new int[] {2, 1, 1, 2, 2, 2}; case "JP": - return new int[] {0, 1, 0, 1, 1, 1}; - case "KE": - return new int[] {3, 3, 2, 2, 2, 2}; - case "KG": - return new int[] {2, 1, 1, 1, 2, 2}; + return new int[] {0, 1, 1, 2, 2, 4}; case "KH": - return new int[] {1, 1, 4, 2, 2, 2}; + return new int[] {2, 1, 4, 2, 2, 2}; + case "CF": + case "KI": + return new int[] {4, 2, 4, 2, 2, 2}; + case "FK": + case "KE": + case "KP": + return new int[] {3, 2, 2, 2, 2, 2}; case "KR": - return new int[] {0, 0, 1, 3, 4, 4}; + return new int[] {0, 1, 1, 3, 4, 4}; + case "CY": case "KW": - return new int[] {1, 1, 0, 0, 0, 2}; - case "AL": - case "BA": - case "KY": - return new int[] {1, 2, 0, 1, 2, 2}; + return new int[] {1, 0, 0, 0, 0, 2}; case "KZ": - return new int[] {1, 1, 2, 2, 2, 2}; + return new int[] {2, 1, 2, 2, 2, 2}; + case "LA": + return new int[] {1, 2, 1, 3, 2, 2}; case "LB": - return new int[] {3, 2, 1, 4, 2, 2}; - case "AD": - case "BM": - case "GL": - case "LC": - return new int[] {1, 2, 0, 0, 2, 2}; + return new int[] {3, 3, 2, 4, 2, 2}; case "LK": - return new int[] {3, 1, 3, 4, 4, 2}; + return new int[] {3, 1, 3, 3, 4, 2}; + case "CI": + case "DZ": case "LR": - return new int[] {3, 4, 4, 3, 2, 2}; + return new int[] {3, 4, 4, 4, 2, 2}; case "LS": - return new int[] {3, 3, 4, 3, 2, 2}; + return new int[] {3, 3, 2, 2, 2, 2}; + case "LT": + return new int[] {0, 0, 0, 0, 2, 2}; case "LU": - return new int[] {1, 0, 2, 2, 2, 2}; + return new int[] {1, 0, 3, 2, 1, 4}; + case "MA": + return new int[] {3, 3, 1, 1, 2, 2}; case "MC": return new int[] {0, 2, 2, 0, 2, 2}; - case "JO": case "ME": - return new int[] {1, 0, 0, 1, 2, 2}; - case "MF": - return new int[] {1, 2, 1, 0, 2, 2}; - case "MG": - return new int[] {3, 4, 2, 2, 2, 2}; - case "MH": - return new int[] {3, 2, 2, 4, 2, 2}; - case "ML": - return new int[] {4, 3, 3, 1, 2, 2}; + return new int[] {2, 0, 0, 1, 2, 2}; + case "MK": + return new int[] {1, 0, 0, 1, 3, 2}; case "MM": - return new int[] {2, 4, 3, 3, 2, 2}; + return new int[] {2, 4, 2, 3, 2, 2}; case "MN": return new int[] {2, 0, 1, 2, 2, 2}; case "MO": + case "MP": return new int[] {0, 2, 4, 4, 2, 2}; - case "GF": case "GP": case "MQ": return new int[] {2, 1, 2, 3, 2, 2}; - case "MR": - return new int[] {4, 1, 3, 4, 2, 2}; - case "EE": - case "LT": - case "LV": - case "MT": - return new int[] {0, 0, 0, 0, 2, 2}; case "MU": return new int[] {3, 1, 1, 2, 2, 2}; case "MV": return new int[] {3, 4, 1, 4, 2, 2}; case "MW": - return new int[] {4, 2, 1, 0, 2, 2}; - case "CG": + return new int[] {4, 2, 3, 3, 2, 2}; case "MX": return new int[] {2, 4, 3, 4, 2, 2}; - case "BD": case "MY": - return new int[] {2, 1, 3, 3, 2, 2}; - case "NA": - return new int[] {4, 3, 2, 2, 2, 2}; - case "AZ": + return new int[] {1, 0, 3, 1, 3, 2}; + case "MZ": + return new int[] {3, 1, 2, 1, 2, 2}; case "NC": - return new int[] {3, 2, 4, 4, 2, 2}; + return new int[] {3, 3, 4, 4, 2, 2}; case "NG": - return new int[] {3, 4, 1, 1, 2, 2}; - case "NI": - return new int[] {2, 3, 4, 3, 2, 2}; + return new int[] {3, 4, 2, 1, 2, 2}; case "NL": - return new int[] {0, 0, 3, 2, 0, 4}; + return new int[] {0, 2, 2, 3, 0, 3}; + case "CZ": case "NO": - return new int[] {0, 0, 2, 0, 0, 2}; + return new int[] {0, 0, 2, 0, 1, 2}; case "NP": - return new int[] {2, 1, 4, 3, 2, 2}; + return new int[] {2, 2, 4, 3, 2, 2}; case "NR": - return new int[] {3, 2, 2, 0, 2, 2}; - case "NZ": - return new int[] {1, 0, 1, 2, 4, 2}; + case "NU": + return new int[] {4, 2, 2, 1, 2, 2}; case "OM": return new int[] {2, 3, 1, 3, 4, 2}; - case "PA": - return new int[] {1, 3, 3, 3, 2, 2}; + case "GU": case "PE": - return new int[] {2, 3, 4, 4, 4, 2}; + return new int[] {1, 2, 4, 4, 4, 2}; + case "CK": case "PF": - return new int[] {2, 3, 3, 1, 2, 2}; - case "CU": + return new int[] {2, 2, 2, 1, 2, 2}; + case "ML": case "PG": - return new int[] {4, 4, 3, 2, 2, 2}; + return new int[] {4, 3, 3, 2, 2, 2}; case "PH": - return new int[] {2, 2, 3, 3, 3, 2}; + return new int[] {2, 1, 3, 3, 3, 0}; + case "NZ": + case "PL": + return new int[] {1, 1, 2, 2, 4, 2}; case "PR": - return new int[] {2, 3, 2, 2, 3, 3}; + return new int[] {2, 0, 2, 1, 2, 1}; case "PS": return new int[] {3, 4, 1, 2, 2, 2}; - case "PT": - return new int[] {0, 1, 0, 0, 2, 2}; case "PW": return new int[] {2, 2, 4, 1, 2, 2}; - case "PY": - return new int[] {2, 2, 3, 2, 2, 2}; case "QA": - return new int[] {2, 4, 2, 4, 4, 2}; + return new int[] {2, 4, 4, 4, 4, 2}; + case "MF": case "RE": - return new int[] {1, 1, 1, 2, 2, 2}; + return new int[] {1, 2, 1, 2, 2, 2}; case "RO": - return new int[] {0, 0, 1, 1, 1, 2}; - case "GR": - case "HR": + return new int[] {0, 0, 1, 2, 1, 2}; case "MD": - case "MK": case "RS": return new int[] {1, 0, 0, 0, 2, 2}; case "RU": - return new int[] {0, 0, 0, 1, 2, 2}; + return new int[] {1, 0, 0, 0, 4, 3}; case "RW": - return new int[] {3, 4, 3, 0, 2, 2}; - case "KI": - case "KM": - case "LY": + return new int[] {3, 4, 2, 0, 2, 2}; + case "SA": + return new int[] {3, 1, 1, 1, 2, 2}; case "SB": return new int[] {4, 2, 4, 3, 2, 2}; - case "SC": - return new int[] {4, 3, 0, 2, 2, 2}; case "SG": - return new int[] {1, 1, 2, 3, 1, 4}; - case "BG": - case "CZ": + return new int[] {1, 1, 2, 2, 2, 1}; + case "AQ": + case "ER": + case "SH": + return new int[] {4, 2, 2, 2, 2, 2}; + case "GR": + case "HR": case "SI": - return new int[] {0, 0, 0, 0, 1, 2}; - case "AT": - case "CH": - case "IS": - case "SE": + return new int[] {1, 0, 0, 0, 1, 2}; + case "BG": + case "MT": case "SK": - return new int[] {0, 0, 0, 0, 0, 2}; - case "SL": - return new int[] {4, 3, 4, 1, 2, 2}; + return new int[] {0, 0, 0, 0, 1, 2}; case "AX": - case "GI": case "LI": - case "MP": + case "MS": case "PM": - case "SJ": case "SM": return new int[] {0, 2, 2, 2, 2, 2}; - case "HN": - case "PK": - case "SO": - return new int[] {3, 2, 3, 3, 2, 2}; - case "BR": + case "SN": + return new int[] {4, 4, 4, 3, 2, 2}; case "SR": - return new int[] {2, 3, 2, 2, 2, 2}; - case "FK": - case "KP": - case "MA": - case "MZ": + return new int[] {2, 4, 3, 0, 2, 2}; + case "SS": + return new int[] {4, 3, 2, 3, 2, 2}; case "ST": - return new int[] {3, 2, 2, 2, 2, 2}; + return new int[] {2, 2, 1, 2, 2, 2}; + case "NI": + case "PA": case "SV": - return new int[] {2, 2, 3, 3, 2, 2}; + return new int[] {2, 3, 3, 3, 2, 2}; case "SZ": - return new int[] {4, 3, 2, 4, 2, 2}; + return new int[] {3, 3, 3, 4, 2, 2}; case "SX": case "TC": - return new int[] {2, 2, 1, 0, 2, 2}; + return new int[] {1, 2, 1, 0, 2, 2}; + case "GA": case "TG": - return new int[] {3, 3, 2, 0, 2, 2}; + return new int[] {3, 4, 1, 0, 2, 2}; case "TH": - return new int[] {0, 3, 2, 3, 3, 0}; - case "TJ": - return new int[] {4, 2, 4, 4, 2, 2}; - case "BI": - case "DZ": + return new int[] {0, 2, 2, 3, 3, 4}; + case "TK": + return new int[] {2, 2, 2, 4, 2, 2}; + case "CU": + case "DJ": case "SY": + case "TJ": case "TL": return new int[] {4, 3, 4, 4, 2, 2}; + case "SC": case "TM": - return new int[] {4, 2, 4, 2, 2, 2}; + return new int[] {4, 2, 1, 1, 2, 2}; + case "AZ": + case "GF": + case "LY": + case "PK": + case "SO": case "TO": - return new int[] {4, 2, 3, 3, 2, 2}; + return new int[] {3, 2, 3, 3, 2, 2}; case "TR": - return new int[] {1, 1, 0, 1, 2, 2}; + return new int[] {1, 1, 0, 0, 2, 2}; case "TT": - return new int[] {1, 4, 1, 1, 2, 2}; - case "AQ": - case "ER": - case "IO": - case "NU": - case "SH": - case "SS": - case "TV": - return new int[] {4, 2, 2, 2, 2, 2}; + return new int[] {1, 4, 1, 3, 2, 2}; + case "EE": + case "IS": + case "LV": + case "PT": + case "SE": case "TW": - return new int[] {0, 0, 0, 0, 0, 0}; - case "GW": + return new int[] {0, 0, 0, 0, 0, 2}; case "TZ": - return new int[] {3, 4, 3, 3, 2, 2}; + return new int[] {3, 4, 3, 2, 2, 2}; + case "IM": case "UA": - return new int[] {0, 3, 1, 1, 2, 2}; - case "IQ": + return new int[] {0, 2, 1, 1, 2, 2}; + case "SL": case "UG": - return new int[] {3, 3, 3, 3, 2, 2}; - case "CL": - case "PL": + return new int[] {3, 3, 4, 3, 2, 2}; case "US": - return new int[] {1, 1, 2, 2, 3, 2}; - case "LA": + return new int[] {1, 0, 2, 2, 3, 1}; + case "AR": + case "KG": + case "TN": case "UY": - return new int[] {2, 2, 1, 2, 2, 2}; + return new int[] {2, 1, 1, 1, 2, 2}; case "UZ": return new int[] {2, 2, 3, 4, 2, 2}; - case "AI": case "BL": case "CX": - case "DM": + case "VA": + return new int[] {1, 2, 2, 2, 2, 2}; + case "AD": + case "BM": + case "BQ": case "GD": - case "MS": + case "GL": + case "KN": + case "KY": + case "LC": case "VC": - return new int[] {1, 2, 2, 2, 2, 2}; - case "SA": - case "TN": + return new int[] {1, 2, 0, 0, 2, 2}; case "VG": return new int[] {2, 2, 1, 1, 2, 2}; + case "GG": case "VI": - return new int[] {1, 2, 1, 3, 2, 2}; + return new int[] {0, 2, 0, 1, 2, 2}; case "VN": return new int[] {0, 3, 3, 4, 2, 2}; + case "GH": + case "NA": case "VU": - return new int[] {4, 2, 2, 1, 2, 2}; - case "GM": + return new int[] {3, 3, 3, 2, 2, 2}; + case "IO": + case "MH": + case "TV": case "WF": return new int[] {4, 2, 2, 4, 2, 2}; case "WS": - return new int[] {3, 1, 2, 1, 2, 2}; + return new int[] {3, 1, 3, 1, 2, 2}; + case "AL": case "XK": return new int[] {1, 1, 1, 1, 2, 2}; - case "AF": + case "BI": case "HT": + case "KM": + case "MG": case "NE": case "SD": - case "SN": case "TD": case "VE": case "YE": return new int[] {4, 4, 4, 4, 2, 2}; + case "JE": case "YT": - return new int[] {4, 1, 1, 1, 2, 2}; + return new int[] {4, 2, 2, 3, 2, 2}; case "ZA": - return new int[] {3, 3, 1, 1, 1, 2}; + return new int[] {3, 2, 2, 1, 1, 2}; case "ZM": return new int[] {3, 3, 4, 2, 2, 2}; + case "MR": case "ZW": - return new int[] {3, 2, 4, 3, 2, 2}; + return new int[] {4, 2, 4, 4, 2, 2}; default: return new int[] {2, 2, 2, 2, 2, 2}; } diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/upstream/DefaultBandwidthMeterTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/upstream/DefaultBandwidthMeterTest.java index d2ca3e7f03..bd3e3cbf1c 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/upstream/DefaultBandwidthMeterTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/upstream/DefaultBandwidthMeterTest.java @@ -38,6 +38,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import java.util.Random; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.Shadows; @@ -125,6 +126,7 @@ public void setUp() { /* subType= */ 0, /* isAvailable= */ true, CONNECTED); + setNetworkCountryIso("non-existent-country-to-force-default-values"); } @Test @@ -378,6 +380,7 @@ public void defaultInitialBitrateEstimate_forOffline_isReasonable() { assertThat(initialEstimateFast).isGreaterThan(initialEstimateSlow); } + @Ignore // 5G-SA isn't widespread enough yet to define a slow and fast country for testing. @Test @Config(minSdk = 29) // 5G-SA detection support was added in API 29. public void From 12e756273091f64152b0f053bee401684f9edbf6 Mon Sep 17 00:00:00 2001 From: christosts Date: Wed, 15 Jun 2022 17:05:54 +0000 Subject: [PATCH 22/73] Misc javadoc fix. PiperOrigin-RevId: 455157744 --- .../main/java/androidx/media3/exoplayer/text/TextOutput.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextOutput.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextOutput.java index 5485452d96..6e12cd57fb 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextOutput.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextOutput.java @@ -39,7 +39,7 @@ default void onCues(List cues) {} * Called when there is a change in the {@link CueGroup}. * *

    Both {@link #onCues(List)} and {@link #onCues(CueGroup)} are called when there is a change - * in the cues You should only implement one or the other. + * in the cues. You should only implement one or the other. */ void onCues(CueGroup cueGroup); } From 8f844b32fdf4d41d6a5690e57e55d0c383ee7e3e Mon Sep 17 00:00:00 2001 From: bachinger Date: Wed, 15 Jun 2022 18:40:32 +0000 Subject: [PATCH 23/73] Avoid out of bounds when setting less media items than in playlist Issue: androidx/media#86 #minor-release PiperOrigin-RevId: 455182232 --- RELEASENOTES.md | 3 + .../session/MediaControllerImplBase.java | 12 ++- .../media3/session/MediaControllerTest.java | 94 +++++++++++++++++++ 3 files changed, 106 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e050b7090d..6a1542c1f8 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -185,6 +185,9 @@ `MediaSession.Callback.onSetMediaUri`. The same functionality can be achieved by using `MediaController.setMediaItem` and `MediaSession.Callback.onAddMediaItems`. + * Fix `IndexOutOfBoundsException` when setting less media items than in + the current playlist + ([#86](https://github.com/androidx/media/issues/86)). * Data sources: * Rename `DummyDataSource` to `PlaceholderDataSource`. * Workaround OkHttp interrupt handling. diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java index c80e832a97..d9d804c1e6 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java @@ -828,7 +828,7 @@ public void setMediaItem(MediaItem mediaItem) { Collections.singletonList(mediaItem), /* startIndex= */ C.INDEX_UNSET, /* startPositionMs= */ C.TIME_UNSET, - /* resetToDefaultPosition= */ false); + /* resetToDefaultPosition= */ true); } @Override @@ -887,7 +887,7 @@ public void setMediaItems(List mediaItems) { mediaItems, /* startIndex= */ C.INDEX_UNSET, /* startPositionMs= */ C.TIME_UNSET, - /* resetToDefaultPosition= */ false); + /* resetToDefaultPosition= */ true); } @Override @@ -1832,12 +1832,18 @@ private void setMediaItemsInternal( throw new IllegalSeekPositionException(newTimeline, startIndex, startPositionMs); } + boolean correctedStartIndex = false; if (resetToDefaultPosition) { startIndex = newTimeline.getFirstWindowIndex(playerInfo.shuffleModeEnabled); startPositionMs = C.TIME_UNSET; } else if (startIndex == C.INDEX_UNSET) { startIndex = playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex; startPositionMs = playerInfo.sessionPositionInfo.positionInfo.positionMs; + if (startIndex >= newTimeline.getWindowCount()) { + correctedStartIndex = true; + startIndex = newTimeline.getFirstWindowIndex(playerInfo.shuffleModeEnabled); + startPositionMs = C.TIME_UNSET; + } } PositionInfo newPositionInfo; SessionPositionInfo newSessionPositionInfo; @@ -1905,7 +1911,7 @@ private void setMediaItemsInternal( // Mask the playback state. int maskingPlaybackState = newPlayerInfo.playbackState; if (startIndex != C.INDEX_UNSET && newPlayerInfo.playbackState != STATE_IDLE) { - if (newTimeline.isEmpty() || startIndex >= newTimeline.getWindowCount()) { + if (newTimeline.isEmpty() || correctedStartIndex) { // Setting an empty timeline or invalid seek transitions to ended. maskingPlaybackState = STATE_ENDED; } else { diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerTest.java index 80b893e9d3..63ea9ad1c9 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerTest.java @@ -36,6 +36,7 @@ import androidx.media3.common.AudioAttributes; import androidx.media3.common.C; import androidx.media3.common.HeartRating; +import androidx.media3.common.IllegalSeekPositionException; import androidx.media3.common.MediaItem; import androidx.media3.common.MediaLibraryInfo; import androidx.media3.common.MediaMetadata; @@ -56,6 +57,7 @@ import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; +import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -64,6 +66,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; @@ -1055,4 +1058,95 @@ public void getMediaMetadata() throws Exception { assertThat(mediaMetadata).isEqualTo(testMediaMetadata); } + + @Test + public void + setMediaItems_setLessMediaItemsThanCurrentMediaItemIndex_masksCurrentMediaItemIndexAndStateCorrectly() + throws Exception { + MediaController controller = controllerTestRule.createController(remoteSession.getToken()); + List threeItemsList = + ImmutableList.of( + MediaItem.fromUri("http://www.google.com/1"), + MediaItem.fromUri("http://www.google.com/2"), + MediaItem.fromUri("http://www.google.com/3")); + List twoItemsList = + ImmutableList.of( + MediaItem.fromUri("http://www.google.com/1"), + MediaItem.fromUri("http://www.google.com/2")); + + int[] currentMediaIndexAndState = + threadTestRule + .getHandler() + .postAndSync( + () -> { + controller.setMediaItems(threeItemsList); + controller.prepare(); + controller.seekTo(/* mediaItemIndex= */ 2, /* positionMs= */ C.TIME_UNSET); + controller.setMediaItems(twoItemsList); + return new int[] { + controller.getCurrentMediaItemIndex(), controller.getPlaybackState() + }; + }); + + assertThat(currentMediaIndexAndState[0]).isEqualTo(0); + assertThat(currentMediaIndexAndState[1]).isEqualTo(Player.STATE_BUFFERING); + } + + @Test + public void + setMediaItems_setLessMediaItemsThanCurrentMediaItemIndexResetPositionFalse_masksCurrentMediaItemIndexAndStateCorrectly() + throws Exception { + MediaController controller = controllerTestRule.createController(remoteSession.getToken()); + List threeItemsList = + ImmutableList.of( + MediaItem.fromUri("http://www.google.com/1"), + MediaItem.fromUri("http://www.google.com/2"), + MediaItem.fromUri("http://www.google.com/3")); + List twoItemsList = + ImmutableList.of( + MediaItem.fromUri("http://www.google.com/1"), + MediaItem.fromUri("http://www.google.com/2")); + + int[] currentMediaItemIndexAndState = + threadTestRule + .getHandler() + .postAndSync( + () -> { + controller.setMediaItems(threeItemsList); + controller.prepare(); + controller.seekTo(/* mediaItemIndex= */ 2, /* positionMs= */ C.TIME_UNSET); + controller.setMediaItems(twoItemsList, /* resetPosition= */ false); + return new int[] { + controller.getCurrentMediaItemIndex(), controller.getPlaybackState() + }; + }); + + assertThat(currentMediaItemIndexAndState[0]).isEqualTo(0); + assertThat(currentMediaItemIndexAndState[1]).isEqualTo(Player.STATE_ENDED); + } + + @Test + public void setMediaItems_startIndexTooLarge_throwIllegalSeekPositionException() + throws Exception { + MediaController controller = controllerTestRule.createController(remoteSession.getToken()); + List threeItemsList = + ImmutableList.of( + MediaItem.fromUri("http://www.google.com/1"), + MediaItem.fromUri("http://www.google.com/2"), + MediaItem.fromUri("http://www.google.com/3")); + + Assert.assertThrows( + IllegalSeekPositionException.class, + () -> + threadTestRule + .getHandler() + .postAndSync( + () -> { + controller.setMediaItems( + threeItemsList, + /* startIndex= */ 99, + /* startPositionMs= */ C.TIME_UNSET); + return controller.getCurrentMediaItemIndex(); + })); + } } From ee847d92c50c8d2929da287e1103110149d78170 Mon Sep 17 00:00:00 2001 From: hschlueter Date: Thu, 16 Jun 2022 10:41:23 +0000 Subject: [PATCH 24/73] Wrap processor chain executor service for better exception handling. The wrapper * catches exceptions for each task and notifies the listener (this will be used more in follow-ups when processFrame is split into lots of listeners and callbacks), * removes finished tasks from the queue and signals any exceptions that occurred to the listener each time a new task is executed. PiperOrigin-RevId: 455345184 --- .../transformer/FrameProcessingTask.java | 27 ++++ .../FrameProcessingTaskExecutor.java | 123 ++++++++++++++++++ .../transformer/FrameProcessorChain.java | 118 ++++++----------- 3 files changed, 191 insertions(+), 77 deletions(-) create mode 100644 libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessingTask.java create mode 100644 libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessingTaskExecutor.java diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessingTask.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessingTask.java new file mode 100644 index 0000000000..e5e12dc14c --- /dev/null +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessingTask.java @@ -0,0 +1,27 @@ +/* + * Copyright 2022 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 androidx.media3.transformer; + +import androidx.media3.common.util.GlUtil; + +/** + * Interface for tasks that may throw a {@link GlUtil.GlException} or {@link + * FrameProcessingException}. + */ +/* package */ interface FrameProcessingTask { + /** Runs the task. */ + void run() throws FrameProcessingException, GlUtil.GlException; +} diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessingTaskExecutor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessingTaskExecutor.java new file mode 100644 index 0000000000..d228494831 --- /dev/null +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessingTaskExecutor.java @@ -0,0 +1,123 @@ +/* + * Copyright 2022 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 androidx.media3.transformer; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import androidx.media3.common.util.GlUtil; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Wrapper around a single thread {@link ExecutorService} for executing {@link FrameProcessingTask} + * instances. + * + *

    The wrapper handles calling {@link + * FrameProcessorChain.Listener#onFrameProcessingError(FrameProcessingException)} for errors that + * occur during these tasks. + */ +/* package */ final class FrameProcessingTaskExecutor { + + private final ExecutorService singleThreadExecutorService; + private final FrameProcessorChain.Listener listener; + private final ConcurrentLinkedQueue> futures; + private final AtomicBoolean shouldCancelTasks; + + /** Creates a new instance. */ + public FrameProcessingTaskExecutor( + ExecutorService singleThreadExecutorService, FrameProcessorChain.Listener listener) { + this.singleThreadExecutorService = singleThreadExecutorService; + this.listener = listener; + + futures = new ConcurrentLinkedQueue<>(); + shouldCancelTasks = new AtomicBoolean(); + } + + /** + * Submits the given {@link FrameProcessingTask} to be executed after any pending tasks have + * completed. + */ + public void submit(FrameProcessingTask task) { + if (shouldCancelTasks.get()) { + return; + } + try { + futures.add(submitTask(task)); + } catch (RejectedExecutionException e) { + if (!shouldCancelTasks.getAndSet(true)) { + listener.onFrameProcessingError(new FrameProcessingException(e)); + } + } + } + + /** + * Cancels remaining tasks, runs the given release task, and shuts down the background thread. + * + * @param releaseTask A {@link FrameProcessingTask} to execute before shutting down the background + * thread. + * @param releaseWaitTimeMs How long to wait for the release task to terminate, in milliseconds. + * @throws InterruptedException If interrupted while releasing resources. + */ + public void release(FrameProcessingTask releaseTask, long releaseWaitTimeMs) + throws InterruptedException { + shouldCancelTasks.getAndSet(true); + while (!futures.isEmpty()) { + futures.remove().cancel(/* mayInterruptIfRunning= */ false); + } + Future releaseFuture = submitTask(releaseTask); + singleThreadExecutorService.shutdown(); + try { + if (!singleThreadExecutorService.awaitTermination(releaseWaitTimeMs, MILLISECONDS)) { + listener.onFrameProcessingError(new FrameProcessingException("Release timed out")); + } + releaseFuture.get(); + } catch (ExecutionException e) { + listener.onFrameProcessingError(new FrameProcessingException(e)); + } + } + + private Future submitTask(FrameProcessingTask glTask) { + return singleThreadExecutorService.submit( + () -> { + try { + glTask.run(); + removeFinishedFutures(); + } catch (FrameProcessingException | GlUtil.GlException | RuntimeException e) { + listener.onFrameProcessingError(FrameProcessingException.from(e)); + } + }); + } + + private void removeFinishedFutures() { + while (!futures.isEmpty()) { + if (!futures.element().isDone()) { + return; + } + try { + futures.remove().get(); + } catch (ExecutionException e) { + listener.onFrameProcessingError(new FrameProcessingException(e)); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + listener.onFrameProcessingError(new FrameProcessingException(e)); + } + } + } +} diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java index 2167da9744..510160e3f1 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java @@ -16,10 +16,8 @@ package androidx.media3.transformer; import static androidx.media3.common.util.Assertions.checkArgument; -import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkState; import static com.google.common.collect.Iterables.getLast; -import static java.util.concurrent.TimeUnit.MILLISECONDS; import android.content.Context; import android.graphics.SurfaceTexture; @@ -42,11 +40,9 @@ import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import java.util.List; -import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; -import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @@ -323,15 +319,12 @@ private static TextureInfo createTexture(int outputWidth, int outputHeight) private final boolean enableExperimentalHdrEditing; private final EGLDisplay eglDisplay; private final EGLContext eglContext; - /** Some OpenGL commands may block, so all OpenGL commands are run on a background thread. */ - private final ExecutorService singleThreadExecutorService; + private final FrameProcessingTaskExecutor frameProcessingTaskExecutor; /** * Offset compared to original media presentation time that has been added to incoming frame * timestamps, in microseconds. */ private final long streamOffsetUs; - /** Futures corresponding to the executor service's pending tasks. */ - private final ConcurrentLinkedQueue> futures; /** Number of frames {@linkplain #registerInputFrame() registered} but not fully processed. */ private final AtomicInteger pendingFrameCount; /** Wraps the {@link #inputSurfaceTexture}. */ @@ -399,7 +392,6 @@ private FrameProcessorChain( this.eglDisplay = eglDisplay; this.eglContext = eglContext; - this.singleThreadExecutorService = singleThreadExecutorService; this.inputExternalTexId = inputExternalTexId; this.streamOffsetUs = streamOffsetUs; this.intermediateTextures = intermediateTextures; @@ -411,7 +403,8 @@ private FrameProcessorChain( this.stopProcessing = new AtomicBoolean(); this.enableExperimentalHdrEditing = enableExperimentalHdrEditing; - futures = new ConcurrentLinkedQueue<>(); + frameProcessingTaskExecutor = + new FrameProcessingTaskExecutor(singleThreadExecutorService, listener); pendingFrameCount = new AtomicInteger(); inputSurfaceTexture = new SurfaceTexture(inputExternalTexId); inputSurface = new Surface(inputSurfaceTexture); @@ -425,20 +418,7 @@ private FrameProcessorChain( public Surface getInputSurface() { // TODO(b/227625423): Allow input surface to be recreated for input size change. inputSurfaceTexture.setOnFrameAvailableListener( - surfaceTexture -> { - if (stopProcessing.get()) { - // Frames can still become available after a transformation is cancelled but they can be - // ignored. - return; - } - try { - futures.add(singleThreadExecutorService.submit(this::processFrame)); - } catch (RejectedExecutionException e) { - if (!stopProcessing.get()) { - throw e; - } - } - }); + surfaceTexture -> frameProcessingTaskExecutor.submit(this::processFrame)); return inputSurface; } @@ -470,7 +450,7 @@ public int getPendingFrameCount() { public void signalEndOfInputStream() { checkState(!inputStreamEnded); inputStreamEnded = true; - futures.add(singleThreadExecutorService.submit(this::signalEndOfOutputStream)); + frameProcessingTaskExecutor.submit(this::signalEndOfOutputStream); } /** @@ -485,19 +465,13 @@ public void signalEndOfInputStream() { */ public void release() { stopProcessing.set(true); - while (!futures.isEmpty()) { - checkNotNull(futures.poll()).cancel(/* mayInterruptIfRunning= */ false); - } - futures.add( - singleThreadExecutorService.submit(this::releaseTextureProcessorsAndDestroyGlContext)); - singleThreadExecutorService.shutdown(); try { - if (!singleThreadExecutorService.awaitTermination(RELEASE_WAIT_TIME_MS, MILLISECONDS)) { - Log.d(TAG, "Failed to release FrameProcessorChain"); - } - } catch (InterruptedException e) { - Log.d(TAG, "FrameProcessorChain release was interrupted", e); + frameProcessingTaskExecutor.release( + /* releaseTask= */ this::releaseTextureProcessorsAndDestroyGlContext, + RELEASE_WAIT_TIME_MS); + } catch (InterruptedException unexpected) { Thread.currentThread().interrupt(); + throw new IllegalStateException(unexpected); } inputSurfaceTexture.release(); inputSurface.release(); @@ -509,24 +483,19 @@ public void release() { *

    This method must be called on the {@linkplain #THREAD_NAME background thread}. */ @WorkerThread - private void processFrame() { - if (stopProcessing.get()) { - return; - } - - long presentationTimeUs = C.TIME_UNSET; - try { - checkState(Thread.currentThread().getName().equals(THREAD_NAME)); + private void processFrame() throws FrameProcessingException { + checkState(Thread.currentThread().getName().equals(THREAD_NAME)); - inputSurfaceTexture.updateTexImage(); - long inputFrameTimeNs = inputSurfaceTexture.getTimestamp(); - // Correct for the stream offset so processors see original media presentation timestamps. - presentationTimeUs = inputFrameTimeNs / 1000 - streamOffsetUs; - inputSurfaceTexture.getTransformMatrix(textureTransformMatrix); - ((ExternalTextureProcessor) textureProcessors.get(0)) - .setTextureTransformMatrix(textureTransformMatrix); - int inputTexId = inputExternalTexId; + inputSurfaceTexture.updateTexImage(); + long inputFrameTimeNs = inputSurfaceTexture.getTimestamp(); + // Correct for the stream offset so processors see original media presentation timestamps. + long presentationTimeUs = inputFrameTimeNs / 1000 - streamOffsetUs; + inputSurfaceTexture.getTransformMatrix(textureTransformMatrix); + ((ExternalTextureProcessor) textureProcessors.get(0)) + .setTextureTransformMatrix(textureTransformMatrix); + int inputTexId = inputExternalTexId; + try { for (int i = 0; i < textureProcessors.size() - 1; i++) { if (stopProcessing.get()) { return; @@ -550,27 +519,25 @@ private void processFrame() { EGLExt.eglPresentationTimeANDROID(eglDisplay, outputEglSurface, inputFrameTimeNs); EGL14.eglSwapBuffers(eglDisplay, outputEglSurface); + } catch (GlUtil.GlException e) { + throw new FrameProcessingException(e, presentationTimeUs); + } + try { if (debugSurfaceViewWrapper != null) { long finalPresentationTimeUs = presentationTimeUs; int finalInputTexId = inputTexId; debugSurfaceViewWrapper.maybeRenderToSurfaceView( () -> { - try { - GlUtil.clearOutputFrame(); - getLast(textureProcessors).drawFrame(finalInputTexId, finalPresentationTimeUs); - } catch (GlUtil.GlException | FrameProcessingException e) { - Log.d(TAG, "Error rendering to debug preview", e); - } + GlUtil.clearOutputFrame(); + getLast(textureProcessors).drawFrame(finalInputTexId, finalPresentationTimeUs); }); } - - checkState(pendingFrameCount.getAndDecrement() > 0); - } catch (FrameProcessingException | GlUtil.GlException | RuntimeException e) { - if (!stopProcessing.getAndSet(true)) { - listener.onFrameProcessingError(FrameProcessingException.from(e, presentationTimeUs)); - } + } catch (FrameProcessingException | GlUtil.GlException e) { + Log.d(TAG, "Error rendering to debug preview", e); } + + checkState(pendingFrameCount.getAndDecrement() > 0); } /** Calls {@link Listener#onFrameProcessingEnded()} once no more frames are pending. */ @@ -579,7 +546,7 @@ private void signalEndOfOutputStream() { if (getPendingFrameCount() == 0) { listener.onFrameProcessingEnded(); } else { - futures.add(singleThreadExecutorService.submit(this::signalEndOfOutputStream)); + frameProcessingTaskExecutor.submit(this::signalEndOfOutputStream); } } @@ -590,15 +557,12 @@ private void signalEndOfOutputStream() { *

    This method must be called on the {@linkplain #THREAD_NAME background thread}. */ @WorkerThread - private void releaseTextureProcessorsAndDestroyGlContext() { - try { - for (int i = 0; i < textureProcessors.size(); i++) { - textureProcessors.get(i).release(); - } - GlUtil.destroyEglContext(eglDisplay, eglContext); - } catch (FrameProcessingException | GlUtil.GlException | RuntimeException e) { - listener.onFrameProcessingError(FrameProcessingException.from(e)); + private void releaseTextureProcessorsAndDestroyGlContext() + throws GlUtil.GlException, FrameProcessingException { + for (int i = 0; i < textureProcessors.size(); i++) { + textureProcessors.get(i).release(); } + GlUtil.destroyEglContext(eglDisplay, eglContext); } /** @@ -627,12 +591,12 @@ public SurfaceViewWrapper(SurfaceView surfaceView) { /** * Focuses the wrapped surface view's surface as an {@link EGLSurface}, renders using {@code - * renderRunnable} and swaps buffers, if the view's holder has a valid surface. Does nothing + * renderingTask} and swaps buffers, if the view's holder has a valid surface. Does nothing * otherwise. */ @WorkerThread - public synchronized void maybeRenderToSurfaceView(Runnable renderRunnable) - throws GlUtil.GlException { + public synchronized void maybeRenderToSurfaceView(FrameProcessingTask renderingTask) + throws GlUtil.GlException, FrameProcessingException { if (surface == null) { return; } @@ -646,7 +610,7 @@ public synchronized void maybeRenderToSurfaceView(Runnable renderRunnable) } EGLSurface eglSurface = this.eglSurface; GlUtil.focusEglSurface(eglDisplay, eglContext, eglSurface, width, height); - renderRunnable.run(); + renderingTask.run(); EGL14.eglSwapBuffers(eglDisplay, eglSurface); } From 1c0b4b32a400ab9f7fb316ed7729ea2b8a32957f Mon Sep 17 00:00:00 2001 From: bachinger Date: Thu, 16 Jun 2022 11:21:05 +0000 Subject: [PATCH 25/73] Version bump to exoplayer:2.18.0 and media3:1.0.0-beta01 #minor-release PiperOrigin-RevId: 455350486 --- .github/ISSUE_TEMPLATE/bug.yml | 1 + RELEASENOTES.md | 70 +++++++++++-------- constants.gradle | 4 +- .../media3/common/MediaLibraryInfo.java | 6 +- 4 files changed, 46 insertions(+), 35 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 41d4528ced..b29b2e92b0 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -17,6 +17,7 @@ body: label: Media3 Version description: What version of Media3 are you using? options: + - 1.0.0-beta01 - 1.0.0-alpha03 - 1.0.0-alpha02 - 1.0.0-alpha01 diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 2b383b0c84..48dc8c7288 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,7 +1,16 @@ -# Release notes + Release notes ### Unreleased changes +* Extractors: + * Add support for AVI + ([#2092](https://github.com/google/ExoPlayer/issues/2092)). +* RTSP: + * Add RTP reader for H263 + ([#63](https://github.com/androidx/media/pull/63)). + +### 1.0.0-beta01 (2022-06-16) + * Core library: * Enable support for Android platform diagnostics via `MediaMetricsManager`. ExoPlayer will forward playback events and @@ -40,7 +49,7 @@ `DefaultTrackSelector.Parameters.Builder` instead of the deprecated `DefaultTrackSelector.ParametersBuilder`. * Add - `DefaultTrackSelector.Parameters.constrainAudioChannelCountToDeviceCapabilities`. + `DefaultTrackSelector.Parameters.constrainAudioChannelCountToDeviceCapabilities` which is enabled by default. When enabled, the `DefaultTrackSelector` will prefer audio tracks whose channel count does not exceed the device output capabilities. On handheld devices, the `DefaultTrackSelector` @@ -77,9 +86,6 @@ * Ensure the DRM session is always correctly updated when seeking immediately after a format change ([10274](https://github.com/google/ExoPlayer/issues/10274)). -* Ad playback / IMA: - * Decrease ad polling rate from every 100ms to every 200ms, to line up - with Media Rating Council (MRC) recommendations. * Text: * Change `Player.getCurrentCues()` to return `CueGroup` instead of `List`. @@ -95,18 +101,16 @@ * MP4: Parse bitrates from `esds` boxes. * Ogg: Allow duplicate Opus ID and comment headers ([#10038](https://github.com/google/ExoPlayer/issues/10038)). - * Add support for AVI - ([#2092](https://github.com/google/ExoPlayer/issues/2092)). * UI: - * Fix delivery of events to `OnClickListener`s set on `PlayerView` and - `LegacyPlayerView`, in the case that `useController=false` + * Fix delivery of events to `OnClickListener`s set on `PlayerView`, in the + case that `useController=false` ([#9605](https://github.com/google/ExoPlayer/issues/9605)). Also fix delivery of events to `OnLongClickListener` for all view configurations. * Fix incorrectly treating a sequence of touch events that exit the bounds - of `PlayerView` and `LegacyPlayerView` before `ACTION_UP` as a click + of `PlayerView` before `ACTION_UP` as a click ([#9861](https://github.com/google/ExoPlayer/issues/9861)). - * Fix `PlayerView` accessibility issue where it was not possible to - tapping would toggle playback rather than hiding the controls + * Fix `PlayerView` accessibility issue where tapping might toggle playback + rather than hiding the controls ([#8627](https://github.com/google/ExoPlayer/issues/8627)). * Rewrite `TrackSelectionView` and `TrackSelectionDialogBuilder` to work with the `Player` interface rather than `ExoPlayer`. This allows the @@ -163,36 +167,42 @@ ([#47](https://github.com/androidx/media/pull/64)). * Add RTP reader for OPUS ([#53](https://github.com/androidx/media/pull/53)). - * Add RTP reader for H263 - ([#63](https://github.com/androidx/media/pull/63)). * Session: - * Fix NPE in MediaControllerImplLegacy - ([#59](https://github.com/androidx/media/pull/59)). - * Update session position info on timeline - change([#51](https://github.com/androidx/media/issues/51)). - * Fix NPE in MediaControllerImplBase after releasing controller - ([#74](https://github.com/androidx/media/issues/74)). - * Rename `MediaSession.MediaSessionCallback` to `MediaSession.Callback`, - `MediaLibrarySession.MediaLibrarySessionCallback` to - `MediaLibrarySession.Callback` and - `MediaSession.Builder.setSessionCallback` to `setCallback`. - * Replace `MediaSession.MediaItemFiler` with + * Replace `MediaSession.MediaItemFiller` with `MediaSession.Callback.onAddMediaItems` to allow asynchronous resolution of requests. - * Forward legacy `MediaController` calls to play media to - `MediaSession.Callback.onAddMediaItems` instead of `onSetMediaUri`. * Support `setMediaItems(s)` methods when `MediaController` connects to a legacy media session. * Remove `MediaController.setMediaUri` and `MediaSession.Callback.onSetMediaUri`. The same functionality can be achieved by using `MediaController.setMediaItem` and `MediaSession.Callback.onAddMediaItems`. + * Forward legacy `MediaController` calls to play media to + `MediaSession.Callback.onAddMediaItems` instead of `onSetMediaUri`. + * Add `MediaNotification.Provider` and `DefaultMediaNotificationProvider` + to provide customization of the notification. + * Add `BitmapLoader` and `SimpleBitmapLoader` for downloading artwork + images. + * Add `MediaSession.setCustomLayout()` to provide backwards compatibility + with the legacy session. + * Add `MediaSession.setSessionExtras()` to provide feature parity with + legacy session. + * Rename `MediaSession.MediaSessionCallback` to `MediaSession.Callback`, + `MediaLibrarySession.MediaLibrarySessionCallback` to + `MediaLibrarySession.Callback` and + `MediaSession.Builder.setSessionCallback` to `setCallback`. + * Fix NPE in `MediaControllerImplLegacy` + ([#59](https://github.com/androidx/media/pull/59)). + * Update session position info on timeline + change([#51](https://github.com/androidx/media/issues/51)). + * Fix NPE in `MediaControllerImplBase` after releasing controller + ([#74](https://github.com/androidx/media/issues/74)). * Fix `IndexOutOfBoundsException` when setting less media items than in the current playlist ([#86](https://github.com/androidx/media/issues/86)). -* Data sources: - * Rename `DummyDataSource` to `PlaceholderDataSource`. - * Workaround OkHttp interrupt handling. +* Ad playback / IMA: + * Decrease ad polling rate from every 100ms to every 200ms, to line up + with Media Rating Council (MRC) recommendations. * FFmpeg extension: * Update CMake version to `3.21.0+` to avoid a CMake bug causing AndroidStudio's gradle sync to fail diff --git a/constants.gradle b/constants.gradle index 3c379912f6..8752c6d8a9 100644 --- a/constants.gradle +++ b/constants.gradle @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. project.ext { - releaseVersion = '1.0.0-alpha03' - releaseVersionCode = 1_000_000_0_03 + releaseVersion = '1.0.0-beta01' + releaseVersionCode = 1_000_000_1_01 minSdkVersion = 16 appTargetSdkVersion = 29 // Upgrading this requires [Internal ref: b/193254928] to be fixed, or some diff --git a/libraries/common/src/main/java/androidx/media3/common/MediaLibraryInfo.java b/libraries/common/src/main/java/androidx/media3/common/MediaLibraryInfo.java index 0cf954df4f..4e87f65806 100644 --- a/libraries/common/src/main/java/androidx/media3/common/MediaLibraryInfo.java +++ b/libraries/common/src/main/java/androidx/media3/common/MediaLibraryInfo.java @@ -29,11 +29,11 @@ public final class MediaLibraryInfo { /** The version of the library expressed as a string, for example "1.2.3" or "1.2.3-beta01". */ // Intentionally hardcoded. Do not derive from other constants (e.g. VERSION_INT) or vice versa. - public static final String VERSION = "1.0.0-alpha03"; + public static final String VERSION = "1.0.0-beta01"; /** The version of the library expressed as {@code TAG + "/" + VERSION}. */ // Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa. - public static final String VERSION_SLASHY = "AndroidXMedia3/1.0.0-alpha03"; + public static final String VERSION_SLASHY = "AndroidXMedia3/1.0.0-beta01"; /** * The version of the library expressed as an integer, for example 1002003300. @@ -47,7 +47,7 @@ public final class MediaLibraryInfo { * (123-045-006-3-00). */ // Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa. - public static final int VERSION_INT = 1_000_000_0_03; + public static final int VERSION_INT = 1_000_000_1_01; /** Whether the library was compiled with {@link Assertions} checks enabled. */ public static final boolean ASSERTIONS_ENABLED = true; From 61ab75b8b88050a12492c412e8c79ebf75fc1d9c Mon Sep 17 00:00:00 2001 From: bachinger Date: Thu, 16 Jun 2022 11:50:36 +0000 Subject: [PATCH 26/73] Add lint base xml file for string.xml files Fixing lint errors in the string.xml files makes no sense because these are overridden with the next automated string import. Adding a lint-baseline.xml instead for the ui module. See https://issuetracker.google.com/208178382 #minor-release PiperOrigin-RevId: 455354304 --- libraries/ui/build.gradle | 6 ++++ libraries/ui/lint-baseline.xml | 62 ++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 libraries/ui/lint-baseline.xml diff --git a/libraries/ui/build.gradle b/libraries/ui/build.gradle index c911f434eb..35dba78fb3 100644 --- a/libraries/ui/build.gradle +++ b/libraries/ui/build.gradle @@ -15,6 +15,12 @@ apply from: "$gradle.ext.androidxMediaSettingsDir/common_library_config.gradle" android.buildTypes.debug.testCoverageEnabled true +android { + lint { + baseline = file("lint-baseline.xml") + } +} + dependencies { implementation project(modulePrefix + 'lib-common') implementation 'androidx.media:media:' + androidxMediaVersion diff --git a/libraries/ui/lint-baseline.xml b/libraries/ui/lint-baseline.xml new file mode 100644 index 0000000000..0b6a29a68c --- /dev/null +++ b/libraries/ui/lint-baseline.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + From 4b4e7cb919ca4b2d9c889c5b82994c9d08991381 Mon Sep 17 00:00:00 2001 From: bachinger Date: Thu, 16 Jun 2022 13:54:23 +0000 Subject: [PATCH 27/73] Fix release notes #minor-release PiperOrigin-RevId: 455372269 --- RELEASENOTES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 48dc8c7288..3fca7aed2f 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -11,6 +11,9 @@ ### 1.0.0-beta01 (2022-06-16) +This release corresponds to the +[ExoPlayer 2.18.0 release](https://github.com/google/ExoPlayer/releases/tag/r2.18.0). + * Core library: * Enable support for Android platform diagnostics via `MediaMetricsManager`. ExoPlayer will forward playback events and From c7f1b465d4dfcfb1657425e4557e47e627d127cf Mon Sep 17 00:00:00 2001 From: ibaker Date: Thu, 16 Jun 2022 13:56:10 +0000 Subject: [PATCH 28/73] Publish api.txt to media3 GitHub #minor-release PiperOrigin-RevId: 455372568 --- api.txt | 1800 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1800 insertions(+) create mode 100644 api.txt diff --git a/api.txt b/api.txt new file mode 100644 index 0000000000..c4e42f5772 --- /dev/null +++ b/api.txt @@ -0,0 +1,1800 @@ +// Signature format: 3.0 +package androidx.media3.common { + + public final class AdOverlayInfo { + field public static final int PURPOSE_CLOSE_AD = 2; // 0x2 + field public static final int PURPOSE_CONTROLS = 1; // 0x1 + field public static final int PURPOSE_NOT_VISIBLE = 4; // 0x4 + field public static final int PURPOSE_OTHER = 3; // 0x3 + field @androidx.media3.common.AdOverlayInfo.Purpose public final int purpose; + field @Nullable public final String reasonDetail; + field public final android.view.View view; + } + + public static final class AdOverlayInfo.Builder { + ctor public AdOverlayInfo.Builder(android.view.View, @androidx.media3.common.AdOverlayInfo.Purpose int); + method public androidx.media3.common.AdOverlayInfo build(); + method public androidx.media3.common.AdOverlayInfo.Builder setDetailedReason(@Nullable String); + } + + @IntDef({androidx.media3.common.AdOverlayInfo.PURPOSE_CONTROLS, androidx.media3.common.AdOverlayInfo.PURPOSE_CLOSE_AD, androidx.media3.common.AdOverlayInfo.PURPOSE_OTHER, androidx.media3.common.AdOverlayInfo.PURPOSE_NOT_VISIBLE}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface AdOverlayInfo.Purpose { + } + + public interface AdViewProvider { + method public default java.util.List getAdOverlayInfos(); + method @Nullable public android.view.ViewGroup getAdViewGroup(); + } + + public final class AudioAttributes { + method @RequiresApi(21) public androidx.media3.common.AudioAttributes.AudioAttributesV21 getAudioAttributesV21(); + field public static final androidx.media3.common.AudioAttributes DEFAULT; + field @androidx.media3.common.C.AudioAllowedCapturePolicy public final int allowedCapturePolicy; + field @androidx.media3.common.C.AudioContentType public final int contentType; + field @androidx.media3.common.C.AudioFlags public final int flags; + field @androidx.media3.common.C.SpatializationBehavior public final int spatializationBehavior; + field @androidx.media3.common.C.AudioUsage public final int usage; + } + + @RequiresApi(21) public static final class AudioAttributes.AudioAttributesV21 { + field public final android.media.AudioAttributes audioAttributes; + } + + public static final class AudioAttributes.Builder { + ctor public AudioAttributes.Builder(); + method public androidx.media3.common.AudioAttributes build(); + method public androidx.media3.common.AudioAttributes.Builder setAllowedCapturePolicy(@androidx.media3.common.C.AudioAllowedCapturePolicy int); + method public androidx.media3.common.AudioAttributes.Builder setContentType(@androidx.media3.common.C.AudioContentType int); + method public androidx.media3.common.AudioAttributes.Builder setFlags(@androidx.media3.common.C.AudioFlags int); + method public androidx.media3.common.AudioAttributes.Builder setSpatializationBehavior(@androidx.media3.common.C.SpatializationBehavior int); + method public androidx.media3.common.AudioAttributes.Builder setUsage(@androidx.media3.common.C.AudioUsage int); + } + + public final class C { + field public static final int ALLOW_CAPTURE_BY_ALL = 1; // 0x1 + field public static final int ALLOW_CAPTURE_BY_NONE = 3; // 0x3 + field public static final int ALLOW_CAPTURE_BY_SYSTEM = 2; // 0x2 + field public static final int AUDIO_CONTENT_TYPE_MOVIE = 3; // 0x3 + field public static final int AUDIO_CONTENT_TYPE_MUSIC = 2; // 0x2 + field public static final int AUDIO_CONTENT_TYPE_SONIFICATION = 4; // 0x4 + field public static final int AUDIO_CONTENT_TYPE_SPEECH = 1; // 0x1 + field public static final int AUDIO_CONTENT_TYPE_UNKNOWN = 0; // 0x0 + field public static final java.util.UUID CLEARKEY_UUID; + field public static final java.util.UUID COMMON_PSSH_UUID; + field public static final int CONTENT_TYPE_DASH = 0; // 0x0 + field public static final int CONTENT_TYPE_HLS = 2; // 0x2 + field public static final int CONTENT_TYPE_OTHER = 4; // 0x4 + field public static final int CONTENT_TYPE_RTSP = 3; // 0x3 + field public static final int CONTENT_TYPE_SS = 1; // 0x1 + field public static final int CRYPTO_TYPE_CUSTOM_BASE = 10000; // 0x2710 + field public static final int CRYPTO_TYPE_FRAMEWORK = 2; // 0x2 + field public static final int CRYPTO_TYPE_NONE = 0; // 0x0 + field public static final int CRYPTO_TYPE_UNSUPPORTED = 1; // 0x1 + field public static final long DEFAULT_MAX_SEEK_TO_PREVIOUS_POSITION_MS = 3000L; // 0xbb8L + field public static final long DEFAULT_SEEK_BACK_INCREMENT_MS = 5000L; // 0x1388L + field public static final long DEFAULT_SEEK_FORWARD_INCREMENT_MS = 15000L; // 0x3a98L + field public static final int FLAG_AUDIBILITY_ENFORCED = 1; // 0x1 + field public static final int INDEX_UNSET = -1; // 0xffffffff + field public static final String LANGUAGE_UNDETERMINED = "und"; + field public static final int LENGTH_UNSET = -1; // 0xffffffff + field public static final java.util.UUID PLAYREADY_UUID; + field public static final float RATE_UNSET = -3.4028235E38f; + field public static final int ROLE_FLAG_ALTERNATE = 2; // 0x2 + field public static final int ROLE_FLAG_CAPTION = 64; // 0x40 + field public static final int ROLE_FLAG_COMMENTARY = 8; // 0x8 + field public static final int ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND = 1024; // 0x400 + field public static final int ROLE_FLAG_DESCRIBES_VIDEO = 512; // 0x200 + field public static final int ROLE_FLAG_DUB = 16; // 0x10 + field public static final int ROLE_FLAG_EASY_TO_READ = 8192; // 0x2000 + field public static final int ROLE_FLAG_EMERGENCY = 32; // 0x20 + field public static final int ROLE_FLAG_ENHANCED_DIALOG_INTELLIGIBILITY = 2048; // 0x800 + field public static final int ROLE_FLAG_MAIN = 1; // 0x1 + field public static final int ROLE_FLAG_SIGN = 256; // 0x100 + field public static final int ROLE_FLAG_SUBTITLE = 128; // 0x80 + field public static final int ROLE_FLAG_SUPPLEMENTARY = 4; // 0x4 + field public static final int ROLE_FLAG_TRANSCRIBES_DIALOG = 4096; // 0x1000 + field public static final int ROLE_FLAG_TRICK_PLAY = 16384; // 0x4000 + field public static final int SELECTION_FLAG_AUTOSELECT = 4; // 0x4 + field public static final int SELECTION_FLAG_DEFAULT = 1; // 0x1 + field public static final int SELECTION_FLAG_FORCED = 2; // 0x2 + field public static final int SPATIALIZATION_BEHAVIOR_AUTO = 0; // 0x0 + field public static final int SPATIALIZATION_BEHAVIOR_NEVER = 1; // 0x1 + field public static final long TIME_END_OF_SOURCE = -9223372036854775808L; // 0x8000000000000000L + field public static final long TIME_UNSET = -9223372036854775807L; // 0x8000000000000001L + field public static final int TRACK_TYPE_AUDIO = 1; // 0x1 + field public static final int TRACK_TYPE_CAMERA_MOTION = 6; // 0x6 + field public static final int TRACK_TYPE_CUSTOM_BASE = 10000; // 0x2710 + field public static final int TRACK_TYPE_DEFAULT = 0; // 0x0 + field public static final int TRACK_TYPE_IMAGE = 4; // 0x4 + field public static final int TRACK_TYPE_METADATA = 5; // 0x5 + field public static final int TRACK_TYPE_NONE = -2; // 0xfffffffe + field public static final int TRACK_TYPE_TEXT = 3; // 0x3 + field public static final int TRACK_TYPE_UNKNOWN = -1; // 0xffffffff + field public static final int TRACK_TYPE_VIDEO = 2; // 0x2 + field public static final int USAGE_ALARM = 4; // 0x4 + field public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11; // 0xb + field public static final int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12; // 0xc + field public static final int USAGE_ASSISTANCE_SONIFICATION = 13; // 0xd + field public static final int USAGE_ASSISTANT = 16; // 0x10 + field public static final int USAGE_GAME = 14; // 0xe + field public static final int USAGE_MEDIA = 1; // 0x1 + field public static final int USAGE_NOTIFICATION = 5; // 0x5 + field public static final int USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9; // 0x9 + field public static final int USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8; // 0x8 + field public static final int USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7; // 0x7 + field public static final int USAGE_NOTIFICATION_EVENT = 10; // 0xa + field public static final int USAGE_NOTIFICATION_RINGTONE = 6; // 0x6 + field public static final int USAGE_UNKNOWN = 0; // 0x0 + field public static final int USAGE_VOICE_COMMUNICATION = 2; // 0x2 + field public static final int USAGE_VOICE_COMMUNICATION_SIGNALLING = 3; // 0x3 + field public static final java.util.UUID UUID_NIL; + field public static final int WAKE_MODE_LOCAL = 1; // 0x1 + field public static final int WAKE_MODE_NETWORK = 2; // 0x2 + field public static final int WAKE_MODE_NONE = 0; // 0x0 + field public static final java.util.UUID WIDEVINE_UUID; + } + + @IntDef({androidx.media3.common.C.ALLOW_CAPTURE_BY_ALL, androidx.media3.common.C.ALLOW_CAPTURE_BY_NONE, androidx.media3.common.C.ALLOW_CAPTURE_BY_SYSTEM}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface C.AudioAllowedCapturePolicy { + } + + @IntDef({androidx.media3.common.C.AUDIO_CONTENT_TYPE_MOVIE, androidx.media3.common.C.AUDIO_CONTENT_TYPE_MUSIC, androidx.media3.common.C.AUDIO_CONTENT_TYPE_SONIFICATION, androidx.media3.common.C.AUDIO_CONTENT_TYPE_SPEECH, androidx.media3.common.C.AUDIO_CONTENT_TYPE_UNKNOWN}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface C.AudioContentType { + } + + @IntDef(flag=true, value={androidx.media3.common.C.FLAG_AUDIBILITY_ENFORCED}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface C.AudioFlags { + } + + @IntDef({androidx.media3.common.C.USAGE_ALARM, androidx.media3.common.C.USAGE_ASSISTANCE_ACCESSIBILITY, androidx.media3.common.C.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, androidx.media3.common.C.USAGE_ASSISTANCE_SONIFICATION, androidx.media3.common.C.USAGE_ASSISTANT, androidx.media3.common.C.USAGE_GAME, androidx.media3.common.C.USAGE_MEDIA, androidx.media3.common.C.USAGE_NOTIFICATION, androidx.media3.common.C.USAGE_NOTIFICATION_COMMUNICATION_DELAYED, androidx.media3.common.C.USAGE_NOTIFICATION_COMMUNICATION_INSTANT, androidx.media3.common.C.USAGE_NOTIFICATION_COMMUNICATION_REQUEST, androidx.media3.common.C.USAGE_NOTIFICATION_EVENT, androidx.media3.common.C.USAGE_NOTIFICATION_RINGTONE, androidx.media3.common.C.USAGE_UNKNOWN, androidx.media3.common.C.USAGE_VOICE_COMMUNICATION, androidx.media3.common.C.USAGE_VOICE_COMMUNICATION_SIGNALLING}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface C.AudioUsage { + } + + @IntDef({androidx.media3.common.C.CONTENT_TYPE_DASH, androidx.media3.common.C.CONTENT_TYPE_SS, androidx.media3.common.C.CONTENT_TYPE_HLS, androidx.media3.common.C.CONTENT_TYPE_RTSP, androidx.media3.common.C.CONTENT_TYPE_OTHER}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface C.ContentType { + } + + @IntDef(open=true, value={androidx.media3.common.C.CRYPTO_TYPE_UNSUPPORTED, androidx.media3.common.C.CRYPTO_TYPE_NONE, androidx.media3.common.C.CRYPTO_TYPE_FRAMEWORK}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) public static @interface C.CryptoType { + } + + @IntDef(flag=true, value={androidx.media3.common.C.ROLE_FLAG_MAIN, androidx.media3.common.C.ROLE_FLAG_ALTERNATE, androidx.media3.common.C.ROLE_FLAG_SUPPLEMENTARY, androidx.media3.common.C.ROLE_FLAG_COMMENTARY, androidx.media3.common.C.ROLE_FLAG_DUB, androidx.media3.common.C.ROLE_FLAG_EMERGENCY, androidx.media3.common.C.ROLE_FLAG_CAPTION, androidx.media3.common.C.ROLE_FLAG_SUBTITLE, androidx.media3.common.C.ROLE_FLAG_SIGN, androidx.media3.common.C.ROLE_FLAG_DESCRIBES_VIDEO, androidx.media3.common.C.ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND, androidx.media3.common.C.ROLE_FLAG_ENHANCED_DIALOG_INTELLIGIBILITY, androidx.media3.common.C.ROLE_FLAG_TRANSCRIBES_DIALOG, androidx.media3.common.C.ROLE_FLAG_EASY_TO_READ, androidx.media3.common.C.ROLE_FLAG_TRICK_PLAY}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface C.RoleFlags { + } + + @IntDef(flag=true, value={androidx.media3.common.C.SELECTION_FLAG_DEFAULT, androidx.media3.common.C.SELECTION_FLAG_FORCED, androidx.media3.common.C.SELECTION_FLAG_AUTOSELECT}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface C.SelectionFlags { + } + + @IntDef({androidx.media3.common.C.SPATIALIZATION_BEHAVIOR_AUTO, androidx.media3.common.C.SPATIALIZATION_BEHAVIOR_NEVER}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) public static @interface C.SpatializationBehavior { + } + + @IntDef(open=true, value={androidx.media3.common.C.TRACK_TYPE_UNKNOWN, androidx.media3.common.C.TRACK_TYPE_DEFAULT, androidx.media3.common.C.TRACK_TYPE_AUDIO, androidx.media3.common.C.TRACK_TYPE_VIDEO, androidx.media3.common.C.TRACK_TYPE_TEXT, androidx.media3.common.C.TRACK_TYPE_IMAGE, androidx.media3.common.C.TRACK_TYPE_METADATA, androidx.media3.common.C.TRACK_TYPE_CAMERA_MOTION, androidx.media3.common.C.TRACK_TYPE_NONE}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) public static @interface C.TrackType { + } + + @IntDef({androidx.media3.common.C.WAKE_MODE_NONE, androidx.media3.common.C.WAKE_MODE_LOCAL, androidx.media3.common.C.WAKE_MODE_NETWORK}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface C.WakeMode { + } + + public final class DeviceInfo { + field public static final int PLAYBACK_TYPE_LOCAL = 0; // 0x0 + field public static final int PLAYBACK_TYPE_REMOTE = 1; // 0x1 + field public static final androidx.media3.common.DeviceInfo UNKNOWN; + field public final int maxVolume; + field public final int minVolume; + field @androidx.media3.common.DeviceInfo.PlaybackType public final int playbackType; + } + + @IntDef({androidx.media3.common.DeviceInfo.PLAYBACK_TYPE_LOCAL, androidx.media3.common.DeviceInfo.PLAYBACK_TYPE_REMOTE}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) public static @interface DeviceInfo.PlaybackType { + } + + public interface ErrorMessageProvider { + method public android.util.Pair getErrorMessage(T); + } + + public final class Format { + field public static final int NO_VALUE = -1; // 0xffffffff + field public final int channelCount; + field @Nullable public final String codecs; + field @Nullable public final String containerMimeType; + field public final float frameRate; + field public final int height; + field @Nullable public final String id; + field @Nullable public final String label; + field @Nullable public final String language; + field public final float pixelWidthHeightRatio; + field @androidx.media3.common.C.RoleFlags public final int roleFlags; + field @Nullable public final String sampleMimeType; + field public final int sampleRate; + field @androidx.media3.common.C.SelectionFlags public final int selectionFlags; + field public final int width; + } + + public final class HeartRating extends androidx.media3.common.Rating { + ctor public HeartRating(); + ctor public HeartRating(boolean); + method public boolean isHeart(); + method public boolean isRated(); + } + + public final class MediaItem { + method public androidx.media3.common.MediaItem.Builder buildUpon(); + method public static androidx.media3.common.MediaItem fromUri(String); + method public static androidx.media3.common.MediaItem fromUri(android.net.Uri); + field public static final String DEFAULT_MEDIA_ID = ""; + field public static final androidx.media3.common.MediaItem EMPTY; + field public final androidx.media3.common.MediaItem.ClippingConfiguration clippingConfiguration; + field public final androidx.media3.common.MediaItem.LiveConfiguration liveConfiguration; + field @Nullable public final androidx.media3.common.MediaItem.LocalConfiguration localConfiguration; + field public final String mediaId; + field public final androidx.media3.common.MediaMetadata mediaMetadata; + field public final androidx.media3.common.MediaItem.RequestMetadata requestMetadata; + } + + public static final class MediaItem.AdsConfiguration { + method public androidx.media3.common.MediaItem.AdsConfiguration.Builder buildUpon(); + field public final android.net.Uri adTagUri; + field @Nullable public final Object adsId; + } + + public static final class MediaItem.AdsConfiguration.Builder { + ctor public MediaItem.AdsConfiguration.Builder(android.net.Uri); + method public androidx.media3.common.MediaItem.AdsConfiguration build(); + method public androidx.media3.common.MediaItem.AdsConfiguration.Builder setAdTagUri(android.net.Uri); + method public androidx.media3.common.MediaItem.AdsConfiguration.Builder setAdsId(@Nullable Object); + } + + public static final class MediaItem.Builder { + ctor public MediaItem.Builder(); + method public androidx.media3.common.MediaItem build(); + method public androidx.media3.common.MediaItem.Builder setAdsConfiguration(@Nullable androidx.media3.common.MediaItem.AdsConfiguration); + method public androidx.media3.common.MediaItem.Builder setClippingConfiguration(androidx.media3.common.MediaItem.ClippingConfiguration); + method public androidx.media3.common.MediaItem.Builder setDrmConfiguration(@Nullable androidx.media3.common.MediaItem.DrmConfiguration); + method public androidx.media3.common.MediaItem.Builder setLiveConfiguration(androidx.media3.common.MediaItem.LiveConfiguration); + method public androidx.media3.common.MediaItem.Builder setMediaId(String); + method public androidx.media3.common.MediaItem.Builder setMediaMetadata(androidx.media3.common.MediaMetadata); + method public androidx.media3.common.MediaItem.Builder setMimeType(@Nullable String); + method public androidx.media3.common.MediaItem.Builder setRequestMetadata(androidx.media3.common.MediaItem.RequestMetadata); + method public androidx.media3.common.MediaItem.Builder setSubtitleConfigurations(java.util.List); + method public androidx.media3.common.MediaItem.Builder setTag(@Nullable Object); + method public androidx.media3.common.MediaItem.Builder setUri(@Nullable String); + method public androidx.media3.common.MediaItem.Builder setUri(@Nullable android.net.Uri); + } + + public static class MediaItem.ClippingConfiguration { + method public androidx.media3.common.MediaItem.ClippingConfiguration.Builder buildUpon(); + field public static final androidx.media3.common.MediaItem.ClippingConfiguration UNSET; + field public final long endPositionMs; + field public final boolean relativeToDefaultPosition; + field public final boolean relativeToLiveWindow; + field @IntRange(from=0) public final long startPositionMs; + field public final boolean startsAtKeyFrame; + } + + public static final class MediaItem.ClippingConfiguration.Builder { + ctor public MediaItem.ClippingConfiguration.Builder(); + method public androidx.media3.common.MediaItem.ClippingConfiguration build(); + method public androidx.media3.common.MediaItem.ClippingConfiguration.Builder setEndPositionMs(long); + method public androidx.media3.common.MediaItem.ClippingConfiguration.Builder setRelativeToDefaultPosition(boolean); + method public androidx.media3.common.MediaItem.ClippingConfiguration.Builder setRelativeToLiveWindow(boolean); + method public androidx.media3.common.MediaItem.ClippingConfiguration.Builder setStartPositionMs(@IntRange(from=0) long); + method public androidx.media3.common.MediaItem.ClippingConfiguration.Builder setStartsAtKeyFrame(boolean); + } + + public static final class MediaItem.DrmConfiguration { + method public androidx.media3.common.MediaItem.DrmConfiguration.Builder buildUpon(); + method @Nullable public byte[] getKeySetId(); + field public final boolean forceDefaultLicenseUri; + field public final com.google.common.collect.ImmutableList forcedSessionTrackTypes; + field public final com.google.common.collect.ImmutableMap licenseRequestHeaders; + field @Nullable public final android.net.Uri licenseUri; + field public final boolean multiSession; + field public final boolean playClearContentWithoutKey; + field public final java.util.UUID scheme; + } + + public static final class MediaItem.DrmConfiguration.Builder { + ctor public MediaItem.DrmConfiguration.Builder(java.util.UUID); + method public androidx.media3.common.MediaItem.DrmConfiguration build(); + method public androidx.media3.common.MediaItem.DrmConfiguration.Builder setForceDefaultLicenseUri(boolean); + method public androidx.media3.common.MediaItem.DrmConfiguration.Builder setForceSessionsForAudioAndVideoTracks(boolean); + method public androidx.media3.common.MediaItem.DrmConfiguration.Builder setForcedSessionTrackTypes(java.util.List); + method public androidx.media3.common.MediaItem.DrmConfiguration.Builder setKeySetId(@Nullable byte[]); + method public androidx.media3.common.MediaItem.DrmConfiguration.Builder setLicenseRequestHeaders(java.util.Map); + method public androidx.media3.common.MediaItem.DrmConfiguration.Builder setLicenseUri(@Nullable android.net.Uri); + method public androidx.media3.common.MediaItem.DrmConfiguration.Builder setLicenseUri(@Nullable String); + method public androidx.media3.common.MediaItem.DrmConfiguration.Builder setMultiSession(boolean); + method public androidx.media3.common.MediaItem.DrmConfiguration.Builder setPlayClearContentWithoutKey(boolean); + method public androidx.media3.common.MediaItem.DrmConfiguration.Builder setScheme(java.util.UUID); + } + + public static final class MediaItem.LiveConfiguration { + method public androidx.media3.common.MediaItem.LiveConfiguration.Builder buildUpon(); + field public static final androidx.media3.common.MediaItem.LiveConfiguration UNSET; + field public final long maxOffsetMs; + field public final float maxPlaybackSpeed; + field public final long minOffsetMs; + field public final float minPlaybackSpeed; + field public final long targetOffsetMs; + } + + public static final class MediaItem.LiveConfiguration.Builder { + ctor public MediaItem.LiveConfiguration.Builder(); + method public androidx.media3.common.MediaItem.LiveConfiguration build(); + method public androidx.media3.common.MediaItem.LiveConfiguration.Builder setMaxOffsetMs(long); + method public androidx.media3.common.MediaItem.LiveConfiguration.Builder setMaxPlaybackSpeed(float); + method public androidx.media3.common.MediaItem.LiveConfiguration.Builder setMinOffsetMs(long); + method public androidx.media3.common.MediaItem.LiveConfiguration.Builder setMinPlaybackSpeed(float); + method public androidx.media3.common.MediaItem.LiveConfiguration.Builder setTargetOffsetMs(long); + } + + public static class MediaItem.LocalConfiguration { + field @Nullable public final androidx.media3.common.MediaItem.AdsConfiguration adsConfiguration; + field @Nullable public final androidx.media3.common.MediaItem.DrmConfiguration drmConfiguration; + field @Nullable public final String mimeType; + field public final com.google.common.collect.ImmutableList subtitleConfigurations; + field @Nullable public final Object tag; + field public final android.net.Uri uri; + } + + public static final class MediaItem.RequestMetadata { + method public androidx.media3.common.MediaItem.RequestMetadata.Builder buildUpon(); + field public static final androidx.media3.common.MediaItem.RequestMetadata EMPTY; + field @Nullable public final android.os.Bundle extras; + field @Nullable public final android.net.Uri mediaUri; + field @Nullable public final String searchQuery; + } + + public static final class MediaItem.RequestMetadata.Builder { + ctor public MediaItem.RequestMetadata.Builder(); + method public androidx.media3.common.MediaItem.RequestMetadata build(); + method public androidx.media3.common.MediaItem.RequestMetadata.Builder setExtras(@Nullable android.os.Bundle); + method public androidx.media3.common.MediaItem.RequestMetadata.Builder setMediaUri(@Nullable android.net.Uri); + method public androidx.media3.common.MediaItem.RequestMetadata.Builder setSearchQuery(@Nullable String); + } + + public static class MediaItem.SubtitleConfiguration { + method public androidx.media3.common.MediaItem.SubtitleConfiguration.Builder buildUpon(); + field @Nullable public final String id; + field @Nullable public final String label; + field @Nullable public final String language; + field @Nullable public final String mimeType; + field @androidx.media3.common.C.RoleFlags public final int roleFlags; + field @androidx.media3.common.C.SelectionFlags public final int selectionFlags; + field public final android.net.Uri uri; + } + + public static final class MediaItem.SubtitleConfiguration.Builder { + ctor public MediaItem.SubtitleConfiguration.Builder(android.net.Uri); + method public androidx.media3.common.MediaItem.SubtitleConfiguration build(); + method public androidx.media3.common.MediaItem.SubtitleConfiguration.Builder setId(@Nullable String); + method public androidx.media3.common.MediaItem.SubtitleConfiguration.Builder setLabel(@Nullable String); + method public androidx.media3.common.MediaItem.SubtitleConfiguration.Builder setLanguage(@Nullable String); + method public androidx.media3.common.MediaItem.SubtitleConfiguration.Builder setMimeType(@Nullable String); + method public androidx.media3.common.MediaItem.SubtitleConfiguration.Builder setRoleFlags(@androidx.media3.common.C.RoleFlags int); + method public androidx.media3.common.MediaItem.SubtitleConfiguration.Builder setSelectionFlags(@androidx.media3.common.C.SelectionFlags int); + method public androidx.media3.common.MediaItem.SubtitleConfiguration.Builder setUri(android.net.Uri); + } + + public final class MediaMetadata { + method public androidx.media3.common.MediaMetadata.Builder buildUpon(); + field public static final androidx.media3.common.MediaMetadata EMPTY; + field public static final int FOLDER_TYPE_ALBUMS = 2; // 0x2 + field public static final int FOLDER_TYPE_ARTISTS = 3; // 0x3 + field public static final int FOLDER_TYPE_GENRES = 4; // 0x4 + field public static final int FOLDER_TYPE_MIXED = 0; // 0x0 + field public static final int FOLDER_TYPE_NONE = -1; // 0xffffffff + field public static final int FOLDER_TYPE_PLAYLISTS = 5; // 0x5 + field public static final int FOLDER_TYPE_TITLES = 1; // 0x1 + field public static final int FOLDER_TYPE_YEARS = 6; // 0x6 + field public static final int PICTURE_TYPE_ARTIST_PERFORMER = 8; // 0x8 + field public static final int PICTURE_TYPE_A_BRIGHT_COLORED_FISH = 17; // 0x11 + field public static final int PICTURE_TYPE_BACK_COVER = 4; // 0x4 + field public static final int PICTURE_TYPE_BAND_ARTIST_LOGO = 19; // 0x13 + field public static final int PICTURE_TYPE_BAND_ORCHESTRA = 10; // 0xa + field public static final int PICTURE_TYPE_COMPOSER = 11; // 0xb + field public static final int PICTURE_TYPE_CONDUCTOR = 9; // 0x9 + field public static final int PICTURE_TYPE_DURING_PERFORMANCE = 15; // 0xf + field public static final int PICTURE_TYPE_DURING_RECORDING = 14; // 0xe + field public static final int PICTURE_TYPE_FILE_ICON = 1; // 0x1 + field public static final int PICTURE_TYPE_FILE_ICON_OTHER = 2; // 0x2 + field public static final int PICTURE_TYPE_FRONT_COVER = 3; // 0x3 + field public static final int PICTURE_TYPE_ILLUSTRATION = 18; // 0x12 + field public static final int PICTURE_TYPE_LEAD_ARTIST_PERFORMER = 7; // 0x7 + field public static final int PICTURE_TYPE_LEAFLET_PAGE = 5; // 0x5 + field public static final int PICTURE_TYPE_LYRICIST = 12; // 0xc + field public static final int PICTURE_TYPE_MEDIA = 6; // 0x6 + field public static final int PICTURE_TYPE_MOVIE_VIDEO_SCREEN_CAPTURE = 16; // 0x10 + field public static final int PICTURE_TYPE_OTHER = 0; // 0x0 + field public static final int PICTURE_TYPE_PUBLISHER_STUDIO_LOGO = 20; // 0x14 + field public static final int PICTURE_TYPE_RECORDING_LOCATION = 13; // 0xd + field @Nullable public final CharSequence albumArtist; + field @Nullable public final CharSequence albumTitle; + field @Nullable public final CharSequence artist; + field @Nullable public final byte[] artworkData; + field @Nullable @androidx.media3.common.MediaMetadata.PictureType public final Integer artworkDataType; + field @Nullable public final android.net.Uri artworkUri; + field @Nullable public final CharSequence compilation; + field @Nullable public final CharSequence composer; + field @Nullable public final CharSequence conductor; + field @Nullable public final CharSequence description; + field @Nullable public final Integer discNumber; + field @Nullable public final CharSequence displayTitle; + field @Nullable public final android.os.Bundle extras; + field @Nullable @androidx.media3.common.MediaMetadata.FolderType public final Integer folderType; + field @Nullable public final CharSequence genre; + field @Nullable public final Boolean isPlayable; + field @Nullable public final androidx.media3.common.Rating overallRating; + field @Nullable public final Integer recordingDay; + field @Nullable public final Integer recordingMonth; + field @Nullable public final Integer recordingYear; + field @Nullable public final Integer releaseDay; + field @Nullable public final Integer releaseMonth; + field @Nullable public final Integer releaseYear; + field @Nullable public final CharSequence station; + field @Nullable public final CharSequence subtitle; + field @Nullable public final CharSequence title; + field @Nullable public final Integer totalDiscCount; + field @Nullable public final Integer totalTrackCount; + field @Nullable public final Integer trackNumber; + field @Nullable public final androidx.media3.common.Rating userRating; + field @Nullable public final CharSequence writer; + } + + public static final class MediaMetadata.Builder { + ctor public MediaMetadata.Builder(); + method public androidx.media3.common.MediaMetadata build(); + method public androidx.media3.common.MediaMetadata.Builder maybeSetArtworkData(byte[], @androidx.media3.common.MediaMetadata.PictureType int); + method public androidx.media3.common.MediaMetadata.Builder setAlbumArtist(@Nullable CharSequence); + method public androidx.media3.common.MediaMetadata.Builder setAlbumTitle(@Nullable CharSequence); + method public androidx.media3.common.MediaMetadata.Builder setArtist(@Nullable CharSequence); + method public androidx.media3.common.MediaMetadata.Builder setArtworkData(@Nullable byte[], @Nullable @androidx.media3.common.MediaMetadata.PictureType Integer); + method public androidx.media3.common.MediaMetadata.Builder setArtworkUri(@Nullable android.net.Uri); + method public androidx.media3.common.MediaMetadata.Builder setCompilation(@Nullable CharSequence); + method public androidx.media3.common.MediaMetadata.Builder setComposer(@Nullable CharSequence); + method public androidx.media3.common.MediaMetadata.Builder setConductor(@Nullable CharSequence); + method public androidx.media3.common.MediaMetadata.Builder setDescription(@Nullable CharSequence); + method public androidx.media3.common.MediaMetadata.Builder setDiscNumber(@Nullable Integer); + method public androidx.media3.common.MediaMetadata.Builder setDisplayTitle(@Nullable CharSequence); + method public androidx.media3.common.MediaMetadata.Builder setExtras(@Nullable android.os.Bundle); + method public androidx.media3.common.MediaMetadata.Builder setFolderType(@Nullable @androidx.media3.common.MediaMetadata.FolderType Integer); + method public androidx.media3.common.MediaMetadata.Builder setGenre(@Nullable CharSequence); + method public androidx.media3.common.MediaMetadata.Builder setIsPlayable(@Nullable Boolean); + method public androidx.media3.common.MediaMetadata.Builder setOverallRating(@Nullable androidx.media3.common.Rating); + method public androidx.media3.common.MediaMetadata.Builder setRecordingDay(@IntRange(from=1, to=31) @Nullable Integer); + method public androidx.media3.common.MediaMetadata.Builder setRecordingMonth(@IntRange(from=1, to=12) @Nullable Integer); + method public androidx.media3.common.MediaMetadata.Builder setRecordingYear(@Nullable Integer); + method public androidx.media3.common.MediaMetadata.Builder setReleaseDay(@IntRange(from=1, to=31) @Nullable Integer); + method public androidx.media3.common.MediaMetadata.Builder setReleaseMonth(@IntRange(from=1, to=12) @Nullable Integer); + method public androidx.media3.common.MediaMetadata.Builder setReleaseYear(@Nullable Integer); + method public androidx.media3.common.MediaMetadata.Builder setStation(@Nullable CharSequence); + method public androidx.media3.common.MediaMetadata.Builder setSubtitle(@Nullable CharSequence); + method public androidx.media3.common.MediaMetadata.Builder setTitle(@Nullable CharSequence); + method public androidx.media3.common.MediaMetadata.Builder setTotalDiscCount(@Nullable Integer); + method public androidx.media3.common.MediaMetadata.Builder setTotalTrackCount(@Nullable Integer); + method public androidx.media3.common.MediaMetadata.Builder setTrackNumber(@Nullable Integer); + method public androidx.media3.common.MediaMetadata.Builder setUserRating(@Nullable androidx.media3.common.Rating); + method public androidx.media3.common.MediaMetadata.Builder setWriter(@Nullable CharSequence); + } + + @IntDef({androidx.media3.common.MediaMetadata.FOLDER_TYPE_NONE, androidx.media3.common.MediaMetadata.FOLDER_TYPE_MIXED, androidx.media3.common.MediaMetadata.FOLDER_TYPE_TITLES, androidx.media3.common.MediaMetadata.FOLDER_TYPE_ALBUMS, androidx.media3.common.MediaMetadata.FOLDER_TYPE_ARTISTS, androidx.media3.common.MediaMetadata.FOLDER_TYPE_GENRES, androidx.media3.common.MediaMetadata.FOLDER_TYPE_PLAYLISTS, androidx.media3.common.MediaMetadata.FOLDER_TYPE_YEARS}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface MediaMetadata.FolderType { + } + + @IntDef({androidx.media3.common.MediaMetadata.PICTURE_TYPE_OTHER, androidx.media3.common.MediaMetadata.PICTURE_TYPE_FILE_ICON, androidx.media3.common.MediaMetadata.PICTURE_TYPE_FILE_ICON_OTHER, androidx.media3.common.MediaMetadata.PICTURE_TYPE_FRONT_COVER, androidx.media3.common.MediaMetadata.PICTURE_TYPE_BACK_COVER, androidx.media3.common.MediaMetadata.PICTURE_TYPE_LEAFLET_PAGE, androidx.media3.common.MediaMetadata.PICTURE_TYPE_MEDIA, androidx.media3.common.MediaMetadata.PICTURE_TYPE_LEAD_ARTIST_PERFORMER, androidx.media3.common.MediaMetadata.PICTURE_TYPE_ARTIST_PERFORMER, androidx.media3.common.MediaMetadata.PICTURE_TYPE_CONDUCTOR, androidx.media3.common.MediaMetadata.PICTURE_TYPE_BAND_ORCHESTRA, androidx.media3.common.MediaMetadata.PICTURE_TYPE_COMPOSER, androidx.media3.common.MediaMetadata.PICTURE_TYPE_LYRICIST, androidx.media3.common.MediaMetadata.PICTURE_TYPE_RECORDING_LOCATION, androidx.media3.common.MediaMetadata.PICTURE_TYPE_DURING_RECORDING, androidx.media3.common.MediaMetadata.PICTURE_TYPE_DURING_PERFORMANCE, androidx.media3.common.MediaMetadata.PICTURE_TYPE_MOVIE_VIDEO_SCREEN_CAPTURE, androidx.media3.common.MediaMetadata.PICTURE_TYPE_A_BRIGHT_COLORED_FISH, androidx.media3.common.MediaMetadata.PICTURE_TYPE_ILLUSTRATION, androidx.media3.common.MediaMetadata.PICTURE_TYPE_BAND_ARTIST_LOGO, androidx.media3.common.MediaMetadata.PICTURE_TYPE_PUBLISHER_STUDIO_LOGO}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface MediaMetadata.PictureType { + } + + public final class MimeTypes { + field public static final String APPLICATION_AIT = "application/vnd.dvb.ait"; + field public static final String APPLICATION_CEA608 = "application/cea-608"; + field public static final String APPLICATION_CEA708 = "application/cea-708"; + field public static final String APPLICATION_DVBSUBS = "application/dvbsubs"; + field public static final String APPLICATION_ID3 = "application/id3"; + field public static final String APPLICATION_M3U8 = "application/x-mpegURL"; + field public static final String APPLICATION_MATROSKA = "application/x-matroska"; + field public static final String APPLICATION_MP4 = "application/mp4"; + field public static final String APPLICATION_MP4CEA608 = "application/x-mp4-cea-608"; + field public static final String APPLICATION_MP4VTT = "application/x-mp4-vtt"; + field public static final String APPLICATION_MPD = "application/dash+xml"; + field public static final String APPLICATION_PGS = "application/pgs"; + field public static final String APPLICATION_RAWCC = "application/x-rawcc"; + field public static final String APPLICATION_RTSP = "application/x-rtsp"; + field public static final String APPLICATION_SS = "application/vnd.ms-sstr+xml"; + field public static final String APPLICATION_SUBRIP = "application/x-subrip"; + field public static final String APPLICATION_TTML = "application/ttml+xml"; + field public static final String APPLICATION_TX3G = "application/x-quicktime-tx3g"; + field public static final String APPLICATION_VOBSUB = "application/vobsub"; + field public static final String APPLICATION_WEBM = "application/webm"; + field public static final String AUDIO_AAC = "audio/mp4a-latm"; + field public static final String AUDIO_AC3 = "audio/ac3"; + field public static final String AUDIO_AC4 = "audio/ac4"; + field public static final String AUDIO_ALAC = "audio/alac"; + field public static final String AUDIO_ALAW = "audio/g711-alaw"; + field public static final String AUDIO_AMR = "audio/amr"; + field public static final String AUDIO_AMR_NB = "audio/3gpp"; + field public static final String AUDIO_AMR_WB = "audio/amr-wb"; + field public static final String AUDIO_DTS = "audio/vnd.dts"; + field public static final String AUDIO_DTS_EXPRESS = "audio/vnd.dts.hd;profile=lbr"; + field public static final String AUDIO_DTS_HD = "audio/vnd.dts.hd"; + field public static final String AUDIO_E_AC3 = "audio/eac3"; + field public static final String AUDIO_E_AC3_JOC = "audio/eac3-joc"; + field public static final String AUDIO_FLAC = "audio/flac"; + field public static final String AUDIO_MIDI = "audio/midi"; + field public static final String AUDIO_MLAW = "audio/g711-mlaw"; + field public static final String AUDIO_MP4 = "audio/mp4"; + field public static final String AUDIO_MPEG = "audio/mpeg"; + field public static final String AUDIO_MPEGH_MHA1 = "audio/mha1"; + field public static final String AUDIO_MPEGH_MHM1 = "audio/mhm1"; + field public static final String AUDIO_MPEG_L1 = "audio/mpeg-L1"; + field public static final String AUDIO_MPEG_L2 = "audio/mpeg-L2"; + field public static final String AUDIO_MSGSM = "audio/gsm"; + field public static final String AUDIO_OGG = "audio/ogg"; + field public static final String AUDIO_OPUS = "audio/opus"; + field public static final String AUDIO_RAW = "audio/raw"; + field public static final String AUDIO_TRUEHD = "audio/true-hd"; + field public static final String AUDIO_VORBIS = "audio/vorbis"; + field public static final String AUDIO_WAV = "audio/wav"; + field public static final String AUDIO_WEBM = "audio/webm"; + field public static final String IMAGE_JPEG = "image/jpeg"; + field public static final String TEXT_SSA = "text/x-ssa"; + field public static final String TEXT_VTT = "text/vtt"; + field public static final String VIDEO_AV1 = "video/av01"; + field public static final String VIDEO_AVI = "video/x-msvideo"; + field public static final String VIDEO_DIVX = "video/divx"; + field public static final String VIDEO_DOLBY_VISION = "video/dolby-vision"; + field public static final String VIDEO_H263 = "video/3gpp"; + field public static final String VIDEO_H264 = "video/avc"; + field public static final String VIDEO_H265 = "video/hevc"; + field public static final String VIDEO_MJPEG = "video/mjpeg"; + field public static final String VIDEO_MP2T = "video/mp2t"; + field public static final String VIDEO_MP4 = "video/mp4"; + field public static final String VIDEO_MP42 = "video/mp42"; + field public static final String VIDEO_MP43 = "video/mp43"; + field public static final String VIDEO_MP4V = "video/mp4v-es"; + field public static final String VIDEO_MPEG = "video/mpeg"; + field public static final String VIDEO_MPEG2 = "video/mpeg2"; + field public static final String VIDEO_OGG = "video/ogg"; + field public static final String VIDEO_PS = "video/mp2p"; + field public static final String VIDEO_VC1 = "video/wvc1"; + field public static final String VIDEO_WEBM = "video/webm"; + } + + public final class PercentageRating extends androidx.media3.common.Rating { + ctor public PercentageRating(); + ctor public PercentageRating(@FloatRange(from=0, to=100) float); + method public float getPercent(); + method public boolean isRated(); + } + + public class PlaybackException extends java.lang.Exception { + method @CallSuper public boolean errorInfoEquals(@Nullable androidx.media3.common.PlaybackException); + method public static String getErrorCodeName(@androidx.media3.common.PlaybackException.ErrorCode int); + method public final String getErrorCodeName(); + field public static final int CUSTOM_ERROR_CODE_BASE = 1000000; // 0xf4240 + field public static final int ERROR_CODE_AUDIO_TRACK_INIT_FAILED = 5001; // 0x1389 + field public static final int ERROR_CODE_AUDIO_TRACK_WRITE_FAILED = 5002; // 0x138a + field public static final int ERROR_CODE_BEHIND_LIVE_WINDOW = 1002; // 0x3ea + field public static final int ERROR_CODE_DECODER_INIT_FAILED = 4001; // 0xfa1 + field public static final int ERROR_CODE_DECODER_QUERY_FAILED = 4002; // 0xfa2 + field public static final int ERROR_CODE_DECODING_FAILED = 4003; // 0xfa3 + field public static final int ERROR_CODE_DECODING_FORMAT_EXCEEDS_CAPABILITIES = 4004; // 0xfa4 + field public static final int ERROR_CODE_DECODING_FORMAT_UNSUPPORTED = 4005; // 0xfa5 + field public static final int ERROR_CODE_DRM_CONTENT_ERROR = 6003; // 0x1773 + field public static final int ERROR_CODE_DRM_DEVICE_REVOKED = 6007; // 0x1777 + field public static final int ERROR_CODE_DRM_DISALLOWED_OPERATION = 6005; // 0x1775 + field public static final int ERROR_CODE_DRM_LICENSE_ACQUISITION_FAILED = 6004; // 0x1774 + field public static final int ERROR_CODE_DRM_LICENSE_EXPIRED = 6008; // 0x1778 + field public static final int ERROR_CODE_DRM_PROVISIONING_FAILED = 6002; // 0x1772 + field public static final int ERROR_CODE_DRM_SCHEME_UNSUPPORTED = 6001; // 0x1771 + field public static final int ERROR_CODE_DRM_SYSTEM_ERROR = 6006; // 0x1776 + field public static final int ERROR_CODE_DRM_UNSPECIFIED = 6000; // 0x1770 + field public static final int ERROR_CODE_FAILED_RUNTIME_CHECK = 1004; // 0x3ec + field public static final int ERROR_CODE_IO_BAD_HTTP_STATUS = 2004; // 0x7d4 + field public static final int ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED = 2007; // 0x7d7 + field public static final int ERROR_CODE_IO_FILE_NOT_FOUND = 2005; // 0x7d5 + field public static final int ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE = 2003; // 0x7d3 + field public static final int ERROR_CODE_IO_NETWORK_CONNECTION_FAILED = 2001; // 0x7d1 + field public static final int ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT = 2002; // 0x7d2 + field public static final int ERROR_CODE_IO_NO_PERMISSION = 2006; // 0x7d6 + field public static final int ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE = 2008; // 0x7d8 + field public static final int ERROR_CODE_IO_UNSPECIFIED = 2000; // 0x7d0 + field public static final int ERROR_CODE_PARSING_CONTAINER_MALFORMED = 3001; // 0xbb9 + field public static final int ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED = 3003; // 0xbbb + field public static final int ERROR_CODE_PARSING_MANIFEST_MALFORMED = 3002; // 0xbba + field public static final int ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED = 3004; // 0xbbc + field public static final int ERROR_CODE_REMOTE_ERROR = 1001; // 0x3e9 + field public static final int ERROR_CODE_TIMEOUT = 1003; // 0x3eb + field public static final int ERROR_CODE_UNSPECIFIED = 1000; // 0x3e8 + field @androidx.media3.common.PlaybackException.ErrorCode public final int errorCode; + field public final long timestampMs; + } + + @IntDef(open=true, value={androidx.media3.common.PlaybackException.ERROR_CODE_UNSPECIFIED, androidx.media3.common.PlaybackException.ERROR_CODE_REMOTE_ERROR, androidx.media3.common.PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW, androidx.media3.common.PlaybackException.ERROR_CODE_TIMEOUT, androidx.media3.common.PlaybackException.ERROR_CODE_FAILED_RUNTIME_CHECK, androidx.media3.common.PlaybackException.ERROR_CODE_IO_UNSPECIFIED, androidx.media3.common.PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED, androidx.media3.common.PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT, androidx.media3.common.PlaybackException.ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE, androidx.media3.common.PlaybackException.ERROR_CODE_IO_BAD_HTTP_STATUS, androidx.media3.common.PlaybackException.ERROR_CODE_IO_FILE_NOT_FOUND, androidx.media3.common.PlaybackException.ERROR_CODE_IO_NO_PERMISSION, androidx.media3.common.PlaybackException.ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED, androidx.media3.common.PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE, androidx.media3.common.PlaybackException.ERROR_CODE_PARSING_CONTAINER_MALFORMED, androidx.media3.common.PlaybackException.ERROR_CODE_PARSING_MANIFEST_MALFORMED, androidx.media3.common.PlaybackException.ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED, androidx.media3.common.PlaybackException.ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED, androidx.media3.common.PlaybackException.ERROR_CODE_DECODER_INIT_FAILED, androidx.media3.common.PlaybackException.ERROR_CODE_DECODER_QUERY_FAILED, androidx.media3.common.PlaybackException.ERROR_CODE_DECODING_FAILED, androidx.media3.common.PlaybackException.ERROR_CODE_DECODING_FORMAT_EXCEEDS_CAPABILITIES, androidx.media3.common.PlaybackException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED, androidx.media3.common.PlaybackException.ERROR_CODE_AUDIO_TRACK_INIT_FAILED, androidx.media3.common.PlaybackException.ERROR_CODE_AUDIO_TRACK_WRITE_FAILED, androidx.media3.common.PlaybackException.ERROR_CODE_DRM_UNSPECIFIED, androidx.media3.common.PlaybackException.ERROR_CODE_DRM_SCHEME_UNSUPPORTED, androidx.media3.common.PlaybackException.ERROR_CODE_DRM_PROVISIONING_FAILED, androidx.media3.common.PlaybackException.ERROR_CODE_DRM_CONTENT_ERROR, androidx.media3.common.PlaybackException.ERROR_CODE_DRM_LICENSE_ACQUISITION_FAILED, androidx.media3.common.PlaybackException.ERROR_CODE_DRM_DISALLOWED_OPERATION, androidx.media3.common.PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR, androidx.media3.common.PlaybackException.ERROR_CODE_DRM_DEVICE_REVOKED, androidx.media3.common.PlaybackException.ERROR_CODE_DRM_LICENSE_EXPIRED}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface PlaybackException.ErrorCode { + } + + public final class PlaybackParameters { + ctor public PlaybackParameters(float); + ctor public PlaybackParameters(@FloatRange(from=0, fromInclusive=false) float, @FloatRange(from=0, fromInclusive=false) float); + method @CheckResult public androidx.media3.common.PlaybackParameters withSpeed(@FloatRange(from=0, fromInclusive=false) float); + field public static final androidx.media3.common.PlaybackParameters DEFAULT; + field public final float pitch; + field public final float speed; + } + + public interface Player { + method public void addListener(androidx.media3.common.Player.Listener); + method public void addMediaItem(androidx.media3.common.MediaItem); + method public void addMediaItem(int, androidx.media3.common.MediaItem); + method public void addMediaItems(java.util.List); + method public void addMediaItems(int, java.util.List); + method public boolean canAdvertiseSession(); + method public void clearMediaItems(); + method public void clearVideoSurface(); + method public void clearVideoSurface(@Nullable android.view.Surface); + method public void clearVideoSurfaceHolder(@Nullable android.view.SurfaceHolder); + method public void clearVideoSurfaceView(@Nullable android.view.SurfaceView); + method public void clearVideoTextureView(@Nullable android.view.TextureView); + method public void decreaseDeviceVolume(); + method public android.os.Looper getApplicationLooper(); + method public androidx.media3.common.AudioAttributes getAudioAttributes(); + method public androidx.media3.common.Player.Commands getAvailableCommands(); + method @IntRange(from=0, to=100) public int getBufferedPercentage(); + method public long getBufferedPosition(); + method public long getContentBufferedPosition(); + method public long getContentDuration(); + method public long getContentPosition(); + method public int getCurrentAdGroupIndex(); + method public int getCurrentAdIndexInAdGroup(); + method public androidx.media3.common.text.CueGroup getCurrentCues(); + method public long getCurrentLiveOffset(); + method @Nullable public androidx.media3.common.MediaItem getCurrentMediaItem(); + method public int getCurrentMediaItemIndex(); + method public int getCurrentPeriodIndex(); + method public long getCurrentPosition(); + method public androidx.media3.common.Timeline getCurrentTimeline(); + method public androidx.media3.common.Tracks getCurrentTracks(); + method public androidx.media3.common.DeviceInfo getDeviceInfo(); + method @IntRange(from=0) public int getDeviceVolume(); + method public long getDuration(); + method public long getMaxSeekToPreviousPosition(); + method public androidx.media3.common.MediaItem getMediaItemAt(int); + method public int getMediaItemCount(); + method public androidx.media3.common.MediaMetadata getMediaMetadata(); + method public int getNextMediaItemIndex(); + method public boolean getPlayWhenReady(); + method public androidx.media3.common.PlaybackParameters getPlaybackParameters(); + method @androidx.media3.common.Player.State public int getPlaybackState(); + method @androidx.media3.common.Player.PlaybackSuppressionReason public int getPlaybackSuppressionReason(); + method @Nullable public androidx.media3.common.PlaybackException getPlayerError(); + method public androidx.media3.common.MediaMetadata getPlaylistMetadata(); + method public int getPreviousMediaItemIndex(); + method @androidx.media3.common.Player.RepeatMode public int getRepeatMode(); + method public long getSeekBackIncrement(); + method public long getSeekForwardIncrement(); + method public boolean getShuffleModeEnabled(); + method public long getTotalBufferedDuration(); + method public androidx.media3.common.TrackSelectionParameters getTrackSelectionParameters(); + method public androidx.media3.common.VideoSize getVideoSize(); + method @FloatRange(from=0, to=1.0) public float getVolume(); + method public boolean hasNextMediaItem(); + method public boolean hasPreviousMediaItem(); + method public void increaseDeviceVolume(); + method public boolean isCommandAvailable(@androidx.media3.common.Player.Command int); + method public boolean isCurrentMediaItemDynamic(); + method public boolean isCurrentMediaItemLive(); + method public boolean isCurrentMediaItemSeekable(); + method public boolean isDeviceMuted(); + method public boolean isLoading(); + method public boolean isPlaying(); + method public boolean isPlayingAd(); + method public void moveMediaItem(int, int); + method public void moveMediaItems(int, int, int); + method public void pause(); + method public void play(); + method public void prepare(); + method public void release(); + method public void removeListener(androidx.media3.common.Player.Listener); + method public void removeMediaItem(int); + method public void removeMediaItems(int, int); + method public void seekBack(); + method public void seekForward(); + method public void seekTo(long); + method public void seekTo(int, long); + method public void seekToDefaultPosition(); + method public void seekToDefaultPosition(int); + method public void seekToNext(); + method public void seekToNextMediaItem(); + method public void seekToPrevious(); + method public void seekToPreviousMediaItem(); + method public void setDeviceMuted(boolean); + method public void setDeviceVolume(@IntRange(from=0) int); + method public void setMediaItem(androidx.media3.common.MediaItem); + method public void setMediaItem(androidx.media3.common.MediaItem, long); + method public void setMediaItem(androidx.media3.common.MediaItem, boolean); + method public void setMediaItems(java.util.List); + method public void setMediaItems(java.util.List, boolean); + method public void setMediaItems(java.util.List, int, long); + method public void setPlayWhenReady(boolean); + method public void setPlaybackParameters(androidx.media3.common.PlaybackParameters); + method public void setPlaybackSpeed(@FloatRange(from=0, fromInclusive=false) float); + method public void setPlaylistMetadata(androidx.media3.common.MediaMetadata); + method public void setRepeatMode(@androidx.media3.common.Player.RepeatMode int); + method public void setShuffleModeEnabled(boolean); + method public void setTrackSelectionParameters(androidx.media3.common.TrackSelectionParameters); + method public void setVideoSurface(@Nullable android.view.Surface); + method public void setVideoSurfaceHolder(@Nullable android.view.SurfaceHolder); + method public void setVideoSurfaceView(@Nullable android.view.SurfaceView); + method public void setVideoTextureView(@Nullable android.view.TextureView); + method public void setVolume(@FloatRange(from=0, to=1.0) float); + method public void stop(); + field public static final int COMMAND_ADJUST_DEVICE_VOLUME = 26; // 0x1a + field public static final int COMMAND_CHANGE_MEDIA_ITEMS = 20; // 0x14 + field public static final int COMMAND_GET_AUDIO_ATTRIBUTES = 21; // 0x15 + field public static final int COMMAND_GET_CURRENT_MEDIA_ITEM = 16; // 0x10 + field public static final int COMMAND_GET_DEVICE_VOLUME = 23; // 0x17 + field public static final int COMMAND_GET_MEDIA_ITEMS_METADATA = 18; // 0x12 + field public static final int COMMAND_GET_TEXT = 28; // 0x1c + field public static final int COMMAND_GET_TIMELINE = 17; // 0x11 + field public static final int COMMAND_GET_TRACKS = 30; // 0x1e + field public static final int COMMAND_GET_VOLUME = 22; // 0x16 + field public static final int COMMAND_INVALID = -1; // 0xffffffff + field public static final int COMMAND_PLAY_PAUSE = 1; // 0x1 + field public static final int COMMAND_PREPARE = 2; // 0x2 + field public static final int COMMAND_SEEK_BACK = 11; // 0xb + field public static final int COMMAND_SEEK_FORWARD = 12; // 0xc + field public static final int COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM = 5; // 0x5 + field public static final int COMMAND_SEEK_TO_DEFAULT_POSITION = 4; // 0x4 + field public static final int COMMAND_SEEK_TO_MEDIA_ITEM = 10; // 0xa + field public static final int COMMAND_SEEK_TO_NEXT = 9; // 0x9 + field public static final int COMMAND_SEEK_TO_NEXT_MEDIA_ITEM = 8; // 0x8 + field public static final int COMMAND_SEEK_TO_PREVIOUS = 7; // 0x7 + field public static final int COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM = 6; // 0x6 + field public static final int COMMAND_SET_DEVICE_VOLUME = 25; // 0x19 + field public static final int COMMAND_SET_MEDIA_ITEM = 31; // 0x1f + field public static final int COMMAND_SET_MEDIA_ITEMS_METADATA = 19; // 0x13 + field public static final int COMMAND_SET_REPEAT_MODE = 15; // 0xf + field public static final int COMMAND_SET_SHUFFLE_MODE = 14; // 0xe + field public static final int COMMAND_SET_SPEED_AND_PITCH = 13; // 0xd + field public static final int COMMAND_SET_TRACK_SELECTION_PARAMETERS = 29; // 0x1d + field public static final int COMMAND_SET_VIDEO_SURFACE = 27; // 0x1b + field public static final int COMMAND_SET_VOLUME = 24; // 0x18 + field public static final int COMMAND_STOP = 3; // 0x3 + field public static final int DISCONTINUITY_REASON_AUTO_TRANSITION = 0; // 0x0 + field public static final int DISCONTINUITY_REASON_INTERNAL = 5; // 0x5 + field public static final int DISCONTINUITY_REASON_REMOVE = 4; // 0x4 + field public static final int DISCONTINUITY_REASON_SEEK = 1; // 0x1 + field public static final int DISCONTINUITY_REASON_SEEK_ADJUSTMENT = 2; // 0x2 + field public static final int DISCONTINUITY_REASON_SKIP = 3; // 0x3 + field public static final int EVENT_AUDIO_ATTRIBUTES_CHANGED = 20; // 0x14 + field public static final int EVENT_AUDIO_SESSION_ID = 21; // 0x15 + field public static final int EVENT_AVAILABLE_COMMANDS_CHANGED = 13; // 0xd + field public static final int EVENT_CUES = 27; // 0x1b + field public static final int EVENT_DEVICE_INFO_CHANGED = 29; // 0x1d + field public static final int EVENT_DEVICE_VOLUME_CHANGED = 30; // 0x1e + field public static final int EVENT_IS_LOADING_CHANGED = 3; // 0x3 + field public static final int EVENT_IS_PLAYING_CHANGED = 7; // 0x7 + field public static final int EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED = 18; // 0x12 + field public static final int EVENT_MEDIA_ITEM_TRANSITION = 1; // 0x1 + field public static final int EVENT_MEDIA_METADATA_CHANGED = 14; // 0xe + field public static final int EVENT_METADATA = 28; // 0x1c + field public static final int EVENT_PLAYBACK_PARAMETERS_CHANGED = 12; // 0xc + field public static final int EVENT_PLAYBACK_STATE_CHANGED = 4; // 0x4 + field public static final int EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED = 6; // 0x6 + field public static final int EVENT_PLAYER_ERROR = 10; // 0xa + field public static final int EVENT_PLAYLIST_METADATA_CHANGED = 15; // 0xf + field public static final int EVENT_PLAY_WHEN_READY_CHANGED = 5; // 0x5 + field public static final int EVENT_POSITION_DISCONTINUITY = 11; // 0xb + field public static final int EVENT_RENDERED_FIRST_FRAME = 26; // 0x1a + field public static final int EVENT_REPEAT_MODE_CHANGED = 8; // 0x8 + field public static final int EVENT_SEEK_BACK_INCREMENT_CHANGED = 16; // 0x10 + field public static final int EVENT_SEEK_FORWARD_INCREMENT_CHANGED = 17; // 0x11 + field public static final int EVENT_SHUFFLE_MODE_ENABLED_CHANGED = 9; // 0x9 + field public static final int EVENT_SKIP_SILENCE_ENABLED_CHANGED = 23; // 0x17 + field public static final int EVENT_SURFACE_SIZE_CHANGED = 24; // 0x18 + field public static final int EVENT_TIMELINE_CHANGED = 0; // 0x0 + field public static final int EVENT_TRACKS_CHANGED = 2; // 0x2 + field public static final int EVENT_TRACK_SELECTION_PARAMETERS_CHANGED = 19; // 0x13 + field public static final int EVENT_VIDEO_SIZE_CHANGED = 25; // 0x19 + field public static final int EVENT_VOLUME_CHANGED = 22; // 0x16 + field public static final int MEDIA_ITEM_TRANSITION_REASON_AUTO = 1; // 0x1 + field public static final int MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED = 3; // 0x3 + field public static final int MEDIA_ITEM_TRANSITION_REASON_REPEAT = 0; // 0x0 + field public static final int MEDIA_ITEM_TRANSITION_REASON_SEEK = 2; // 0x2 + field public static final int PLAYBACK_SUPPRESSION_REASON_NONE = 0; // 0x0 + field public static final int PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS = 1; // 0x1 + field public static final int PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY = 3; // 0x3 + field public static final int PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS = 2; // 0x2 + field public static final int PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM = 5; // 0x5 + field public static final int PLAY_WHEN_READY_CHANGE_REASON_REMOTE = 4; // 0x4 + field public static final int PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST = 1; // 0x1 + field public static final int REPEAT_MODE_ALL = 2; // 0x2 + field public static final int REPEAT_MODE_OFF = 0; // 0x0 + field public static final int REPEAT_MODE_ONE = 1; // 0x1 + field public static final int STATE_BUFFERING = 2; // 0x2 + field public static final int STATE_ENDED = 4; // 0x4 + field public static final int STATE_IDLE = 1; // 0x1 + field public static final int STATE_READY = 3; // 0x3 + field public static final int TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED = 0; // 0x0 + field public static final int TIMELINE_CHANGE_REASON_SOURCE_UPDATE = 1; // 0x1 + } + + @IntDef({androidx.media3.common.Player.COMMAND_INVALID, androidx.media3.common.Player.COMMAND_PLAY_PAUSE, androidx.media3.common.Player.COMMAND_PREPARE, androidx.media3.common.Player.COMMAND_STOP, androidx.media3.common.Player.COMMAND_SEEK_TO_DEFAULT_POSITION, androidx.media3.common.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS, androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT, androidx.media3.common.Player.COMMAND_SEEK_TO_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_BACK, androidx.media3.common.Player.COMMAND_SEEK_FORWARD, androidx.media3.common.Player.COMMAND_SET_SPEED_AND_PITCH, androidx.media3.common.Player.COMMAND_SET_SHUFFLE_MODE, androidx.media3.common.Player.COMMAND_SET_REPEAT_MODE, androidx.media3.common.Player.COMMAND_GET_CURRENT_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_GET_TIMELINE, androidx.media3.common.Player.COMMAND_GET_MEDIA_ITEMS_METADATA, androidx.media3.common.Player.COMMAND_SET_MEDIA_ITEMS_METADATA, androidx.media3.common.Player.COMMAND_CHANGE_MEDIA_ITEMS, androidx.media3.common.Player.COMMAND_GET_AUDIO_ATTRIBUTES, androidx.media3.common.Player.COMMAND_GET_VOLUME, androidx.media3.common.Player.COMMAND_GET_DEVICE_VOLUME, androidx.media3.common.Player.COMMAND_SET_VOLUME, androidx.media3.common.Player.COMMAND_SET_DEVICE_VOLUME, androidx.media3.common.Player.COMMAND_ADJUST_DEVICE_VOLUME, androidx.media3.common.Player.COMMAND_SET_VIDEO_SURFACE, androidx.media3.common.Player.COMMAND_GET_TEXT, androidx.media3.common.Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS, androidx.media3.common.Player.COMMAND_GET_TRACKS, androidx.media3.common.Player.COMMAND_SET_MEDIA_ITEM}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.Command { + } + + public static final class Player.Commands { + method public boolean contains(@androidx.media3.common.Player.Command int); + method public boolean containsAny(@androidx.media3.common.Player.Command int...); + method @androidx.media3.common.Player.Command public int get(int); + method public int size(); + field public static final androidx.media3.common.Player.Commands EMPTY; + } + + @IntDef({androidx.media3.common.Player.DISCONTINUITY_REASON_AUTO_TRANSITION, androidx.media3.common.Player.DISCONTINUITY_REASON_SEEK, androidx.media3.common.Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT, androidx.media3.common.Player.DISCONTINUITY_REASON_SKIP, androidx.media3.common.Player.DISCONTINUITY_REASON_REMOVE, androidx.media3.common.Player.DISCONTINUITY_REASON_INTERNAL}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.DiscontinuityReason { + } + + @IntDef({androidx.media3.common.Player.EVENT_TIMELINE_CHANGED, androidx.media3.common.Player.EVENT_MEDIA_ITEM_TRANSITION, androidx.media3.common.Player.EVENT_TRACKS_CHANGED, androidx.media3.common.Player.EVENT_IS_LOADING_CHANGED, androidx.media3.common.Player.EVENT_PLAYBACK_STATE_CHANGED, androidx.media3.common.Player.EVENT_PLAY_WHEN_READY_CHANGED, androidx.media3.common.Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED, androidx.media3.common.Player.EVENT_IS_PLAYING_CHANGED, androidx.media3.common.Player.EVENT_REPEAT_MODE_CHANGED, androidx.media3.common.Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED, androidx.media3.common.Player.EVENT_PLAYER_ERROR, androidx.media3.common.Player.EVENT_POSITION_DISCONTINUITY, androidx.media3.common.Player.EVENT_PLAYBACK_PARAMETERS_CHANGED, androidx.media3.common.Player.EVENT_AVAILABLE_COMMANDS_CHANGED, androidx.media3.common.Player.EVENT_MEDIA_METADATA_CHANGED, androidx.media3.common.Player.EVENT_PLAYLIST_METADATA_CHANGED, androidx.media3.common.Player.EVENT_SEEK_BACK_INCREMENT_CHANGED, androidx.media3.common.Player.EVENT_SEEK_FORWARD_INCREMENT_CHANGED, androidx.media3.common.Player.EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED, androidx.media3.common.Player.EVENT_TRACK_SELECTION_PARAMETERS_CHANGED, androidx.media3.common.Player.EVENT_AUDIO_ATTRIBUTES_CHANGED, androidx.media3.common.Player.EVENT_AUDIO_SESSION_ID, androidx.media3.common.Player.EVENT_VOLUME_CHANGED, androidx.media3.common.Player.EVENT_SKIP_SILENCE_ENABLED_CHANGED, androidx.media3.common.Player.EVENT_SURFACE_SIZE_CHANGED, androidx.media3.common.Player.EVENT_VIDEO_SIZE_CHANGED, androidx.media3.common.Player.EVENT_RENDERED_FIRST_FRAME, androidx.media3.common.Player.EVENT_CUES, androidx.media3.common.Player.EVENT_METADATA, androidx.media3.common.Player.EVENT_DEVICE_INFO_CHANGED, androidx.media3.common.Player.EVENT_DEVICE_VOLUME_CHANGED}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.Event { + } + + public static final class Player.Events { + method public boolean contains(@androidx.media3.common.Player.Event int); + method public boolean containsAny(@androidx.media3.common.Player.Event int...); + method @androidx.media3.common.Player.Event public int get(int); + method public int size(); + } + + public static interface Player.Listener { + method public default void onAudioAttributesChanged(androidx.media3.common.AudioAttributes); + method public default void onAvailableCommandsChanged(androidx.media3.common.Player.Commands); + method public default void onCues(androidx.media3.common.text.CueGroup); + method public default void onDeviceInfoChanged(androidx.media3.common.DeviceInfo); + method public default void onDeviceVolumeChanged(int, boolean); + method public default void onEvents(androidx.media3.common.Player, androidx.media3.common.Player.Events); + method public default void onIsLoadingChanged(boolean); + method public default void onIsPlayingChanged(boolean); + method public default void onMaxSeekToPreviousPositionChanged(long); + method public default void onMediaItemTransition(@Nullable androidx.media3.common.MediaItem, @androidx.media3.common.Player.MediaItemTransitionReason int); + method public default void onMediaMetadataChanged(androidx.media3.common.MediaMetadata); + method public default void onPlayWhenReadyChanged(boolean, @androidx.media3.common.Player.PlayWhenReadyChangeReason int); + method public default void onPlaybackParametersChanged(androidx.media3.common.PlaybackParameters); + method public default void onPlaybackStateChanged(@androidx.media3.common.Player.State int); + method public default void onPlaybackSuppressionReasonChanged(@androidx.media3.common.Player.PlaybackSuppressionReason int); + method public default void onPlayerError(androidx.media3.common.PlaybackException); + method public default void onPlayerErrorChanged(@Nullable androidx.media3.common.PlaybackException); + method public default void onPlaylistMetadataChanged(androidx.media3.common.MediaMetadata); + method public default void onPositionDiscontinuity(androidx.media3.common.Player.PositionInfo, androidx.media3.common.Player.PositionInfo, @androidx.media3.common.Player.DiscontinuityReason int); + method public default void onRenderedFirstFrame(); + method public default void onRepeatModeChanged(@androidx.media3.common.Player.RepeatMode int); + method public default void onSeekBackIncrementChanged(long); + method public default void onSeekForwardIncrementChanged(long); + method public default void onShuffleModeEnabledChanged(boolean); + method public default void onSkipSilenceEnabledChanged(boolean); + method public default void onSurfaceSizeChanged(int, int); + method public default void onTimelineChanged(androidx.media3.common.Timeline, @androidx.media3.common.Player.TimelineChangeReason int); + method public default void onTrackSelectionParametersChanged(androidx.media3.common.TrackSelectionParameters); + method public default void onTracksChanged(androidx.media3.common.Tracks); + method public default void onVideoSizeChanged(androidx.media3.common.VideoSize); + method public default void onVolumeChanged(float); + } + + @IntDef({androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT, androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_AUTO, androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_SEEK, androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.MediaItemTransitionReason { + } + + @IntDef({androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_REMOTE, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.PlayWhenReadyChangeReason { + } + + @IntDef({androidx.media3.common.Player.PLAYBACK_SUPPRESSION_REASON_NONE, androidx.media3.common.Player.PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.PlaybackSuppressionReason { + } + + public static final class Player.PositionInfo { + field public final int adGroupIndex; + field public final int adIndexInAdGroup; + field public final long contentPositionMs; + field public final int mediaItemIndex; + field public final int periodIndex; + field @Nullable public final Object periodUid; + field public final long positionMs; + field @Nullable public final Object windowUid; + } + + @IntDef({androidx.media3.common.Player.REPEAT_MODE_OFF, androidx.media3.common.Player.REPEAT_MODE_ONE, androidx.media3.common.Player.REPEAT_MODE_ALL}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.RepeatMode { + } + + @IntDef({androidx.media3.common.Player.STATE_IDLE, androidx.media3.common.Player.STATE_BUFFERING, androidx.media3.common.Player.STATE_READY, androidx.media3.common.Player.STATE_ENDED}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.State { + } + + @IntDef({androidx.media3.common.Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED, androidx.media3.common.Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.TimelineChangeReason { + } + + public abstract class Rating { + method public abstract boolean isRated(); + } + + public final class StarRating extends androidx.media3.common.Rating { + ctor public StarRating(@IntRange(from=1) int); + ctor public StarRating(@IntRange(from=1) int, @FloatRange(from=0.0) float); + method @IntRange(from=1) public int getMaxStars(); + method public float getStarRating(); + method public boolean isRated(); + } + + public final class ThumbRating extends androidx.media3.common.Rating { + ctor public ThumbRating(); + ctor public ThumbRating(boolean); + method public boolean isRated(); + method public boolean isThumbsUp(); + } + + public abstract class Timeline { + method public int getFirstWindowIndex(boolean); + method public abstract int getIndexOfPeriod(Object); + method public int getLastWindowIndex(boolean); + method public final int getNextPeriodIndex(int, androidx.media3.common.Timeline.Period, androidx.media3.common.Timeline.Window, @androidx.media3.common.Player.RepeatMode int, boolean); + method public int getNextWindowIndex(int, @androidx.media3.common.Player.RepeatMode int, boolean); + method public final androidx.media3.common.Timeline.Period getPeriod(int, androidx.media3.common.Timeline.Period); + method public abstract androidx.media3.common.Timeline.Period getPeriod(int, androidx.media3.common.Timeline.Period, boolean); + method public androidx.media3.common.Timeline.Period getPeriodByUid(Object, androidx.media3.common.Timeline.Period); + method public abstract int getPeriodCount(); + method public final android.util.Pair getPeriodPositionUs(androidx.media3.common.Timeline.Window, androidx.media3.common.Timeline.Period, int, long); + method @Nullable public final android.util.Pair getPeriodPositionUs(androidx.media3.common.Timeline.Window, androidx.media3.common.Timeline.Period, int, long, long); + method public int getPreviousWindowIndex(int, @androidx.media3.common.Player.RepeatMode int, boolean); + method public abstract Object getUidOfPeriod(int); + method public final androidx.media3.common.Timeline.Window getWindow(int, androidx.media3.common.Timeline.Window); + method public abstract androidx.media3.common.Timeline.Window getWindow(int, androidx.media3.common.Timeline.Window, long); + method public abstract int getWindowCount(); + method public final boolean isEmpty(); + method public final boolean isLastPeriod(int, androidx.media3.common.Timeline.Period, androidx.media3.common.Timeline.Window, @androidx.media3.common.Player.RepeatMode int, boolean); + field public static final androidx.media3.common.Timeline EMPTY; + } + + public static final class Timeline.Period { + ctor public Timeline.Period(); + method public int getAdCountInAdGroup(int); + method public long getAdDurationUs(int, int); + method public int getAdGroupCount(); + method public int getAdGroupIndexAfterPositionUs(long); + method public int getAdGroupIndexForPositionUs(long); + method public long getAdGroupTimeUs(int); + method public long getAdResumePositionUs(); + method @Nullable public Object getAdsId(); + method public long getDurationMs(); + method public long getDurationUs(); + method public int getFirstAdIndexToPlay(int); + method public int getNextAdIndexToPlay(int, int); + method public long getPositionInWindowMs(); + method public long getPositionInWindowUs(); + method public int getRemovedAdGroupCount(); + method public boolean hasPlayedAdGroup(int); + field @Nullable public Object id; + field public boolean isPlaceholder; + field @Nullable public Object uid; + field public int windowIndex; + } + + public static final class Timeline.Window { + ctor public Timeline.Window(); + method public long getCurrentUnixTimeMs(); + method public long getDefaultPositionMs(); + method public long getDefaultPositionUs(); + method public long getDurationMs(); + method public long getDurationUs(); + method public long getPositionInFirstPeriodMs(); + method public long getPositionInFirstPeriodUs(); + method public boolean isLive(); + field public static final Object SINGLE_WINDOW_UID; + field public long elapsedRealtimeEpochOffsetMs; + field public int firstPeriodIndex; + field public boolean isDynamic; + field public boolean isPlaceholder; + field public boolean isSeekable; + field public int lastPeriodIndex; + field @Nullable public androidx.media3.common.MediaItem.LiveConfiguration liveConfiguration; + field @Nullable public Object manifest; + field public androidx.media3.common.MediaItem mediaItem; + field public long presentationStartTimeMs; + field public Object uid; + field public long windowStartTimeMs; + } + + public final class TrackGroup { + } + + public final class TrackSelectionOverride { + ctor public TrackSelectionOverride(androidx.media3.common.TrackGroup, int); + ctor public TrackSelectionOverride(androidx.media3.common.TrackGroup, java.util.List); + method @androidx.media3.common.C.TrackType public int getType(); + field public final androidx.media3.common.TrackGroup mediaTrackGroup; + field public final com.google.common.collect.ImmutableList trackIndices; + } + + public class TrackSelectionParameters { + method public androidx.media3.common.TrackSelectionParameters.Builder buildUpon(); + method public static androidx.media3.common.TrackSelectionParameters fromBundle(android.os.Bundle); + method public static androidx.media3.common.TrackSelectionParameters getDefaults(android.content.Context); + method public android.os.Bundle toBundle(); + field public final com.google.common.collect.ImmutableSet disabledTrackTypes; + field public final boolean forceHighestSupportedBitrate; + field public final boolean forceLowestBitrate; + field @androidx.media3.common.C.SelectionFlags public final int ignoredTextSelectionFlags; + field public final int maxAudioBitrate; + field public final int maxAudioChannelCount; + field public final int maxVideoBitrate; + field public final int maxVideoFrameRate; + field public final int maxVideoHeight; + field public final int maxVideoWidth; + field public final int minVideoBitrate; + field public final int minVideoFrameRate; + field public final int minVideoHeight; + field public final int minVideoWidth; + field public final com.google.common.collect.ImmutableMap overrides; + field public final com.google.common.collect.ImmutableList preferredAudioLanguages; + field public final com.google.common.collect.ImmutableList preferredAudioMimeTypes; + field @androidx.media3.common.C.RoleFlags public final int preferredAudioRoleFlags; + field public final com.google.common.collect.ImmutableList preferredTextLanguages; + field @androidx.media3.common.C.RoleFlags public final int preferredTextRoleFlags; + field public final com.google.common.collect.ImmutableList preferredVideoMimeTypes; + field @androidx.media3.common.C.RoleFlags public final int preferredVideoRoleFlags; + field public final boolean selectUndeterminedTextLanguage; + field public final int viewportHeight; + field public final boolean viewportOrientationMayChange; + field public final int viewportWidth; + } + + public static class TrackSelectionParameters.Builder { + ctor public TrackSelectionParameters.Builder(android.content.Context); + method public androidx.media3.common.TrackSelectionParameters.Builder addOverride(androidx.media3.common.TrackSelectionOverride); + method public androidx.media3.common.TrackSelectionParameters build(); + method public androidx.media3.common.TrackSelectionParameters.Builder clearOverride(androidx.media3.common.TrackGroup); + method public androidx.media3.common.TrackSelectionParameters.Builder clearOverrides(); + method public androidx.media3.common.TrackSelectionParameters.Builder clearOverridesOfType(@androidx.media3.common.C.TrackType int); + method public androidx.media3.common.TrackSelectionParameters.Builder clearVideoSizeConstraints(); + method public androidx.media3.common.TrackSelectionParameters.Builder clearViewportSizeConstraints(); + method public androidx.media3.common.TrackSelectionParameters.Builder setForceHighestSupportedBitrate(boolean); + method public androidx.media3.common.TrackSelectionParameters.Builder setForceLowestBitrate(boolean); + method public androidx.media3.common.TrackSelectionParameters.Builder setIgnoredTextSelectionFlags(@androidx.media3.common.C.SelectionFlags int); + method public androidx.media3.common.TrackSelectionParameters.Builder setMaxAudioBitrate(int); + method public androidx.media3.common.TrackSelectionParameters.Builder setMaxAudioChannelCount(int); + method public androidx.media3.common.TrackSelectionParameters.Builder setMaxVideoBitrate(int); + method public androidx.media3.common.TrackSelectionParameters.Builder setMaxVideoFrameRate(int); + method public androidx.media3.common.TrackSelectionParameters.Builder setMaxVideoSize(int, int); + method public androidx.media3.common.TrackSelectionParameters.Builder setMaxVideoSizeSd(); + method public androidx.media3.common.TrackSelectionParameters.Builder setMinVideoBitrate(int); + method public androidx.media3.common.TrackSelectionParameters.Builder setMinVideoFrameRate(int); + method public androidx.media3.common.TrackSelectionParameters.Builder setMinVideoSize(int, int); + method public androidx.media3.common.TrackSelectionParameters.Builder setOverrideForType(androidx.media3.common.TrackSelectionOverride); + method public androidx.media3.common.TrackSelectionParameters.Builder setPreferredAudioLanguage(@Nullable String); + method public androidx.media3.common.TrackSelectionParameters.Builder setPreferredAudioLanguages(java.lang.String...); + method public androidx.media3.common.TrackSelectionParameters.Builder setPreferredAudioMimeType(@Nullable String); + method public androidx.media3.common.TrackSelectionParameters.Builder setPreferredAudioMimeTypes(java.lang.String...); + method public androidx.media3.common.TrackSelectionParameters.Builder setPreferredAudioRoleFlags(@androidx.media3.common.C.RoleFlags int); + method public androidx.media3.common.TrackSelectionParameters.Builder setPreferredTextLanguage(@Nullable String); + method public androidx.media3.common.TrackSelectionParameters.Builder setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(android.content.Context); + method public androidx.media3.common.TrackSelectionParameters.Builder setPreferredTextLanguages(java.lang.String...); + method public androidx.media3.common.TrackSelectionParameters.Builder setPreferredTextRoleFlags(@androidx.media3.common.C.RoleFlags int); + method public androidx.media3.common.TrackSelectionParameters.Builder setPreferredVideoMimeType(@Nullable String); + method public androidx.media3.common.TrackSelectionParameters.Builder setPreferredVideoMimeTypes(java.lang.String...); + method public androidx.media3.common.TrackSelectionParameters.Builder setPreferredVideoRoleFlags(@androidx.media3.common.C.RoleFlags int); + method public androidx.media3.common.TrackSelectionParameters.Builder setSelectUndeterminedTextLanguage(boolean); + method public androidx.media3.common.TrackSelectionParameters.Builder setTrackTypeDisabled(@androidx.media3.common.C.TrackType int, boolean); + method public androidx.media3.common.TrackSelectionParameters.Builder setViewportSize(int, int, boolean); + method public androidx.media3.common.TrackSelectionParameters.Builder setViewportSizeToPhysicalDisplaySize(android.content.Context, boolean); + } + + public final class Tracks { + method public boolean containsType(@androidx.media3.common.C.TrackType int); + method public com.google.common.collect.ImmutableList getGroups(); + method public boolean isEmpty(); + method public boolean isTypeSelected(@androidx.media3.common.C.TrackType int); + method public boolean isTypeSupported(@androidx.media3.common.C.TrackType int); + method public boolean isTypeSupported(@androidx.media3.common.C.TrackType int, boolean); + field public static final androidx.media3.common.Tracks EMPTY; + } + + public static final class Tracks.Group { + method public androidx.media3.common.TrackGroup getMediaTrackGroup(); + method public androidx.media3.common.Format getTrackFormat(int); + method @androidx.media3.common.C.TrackType public int getType(); + method public boolean isAdaptiveSupported(); + method public boolean isSelected(); + method public boolean isSupported(); + method public boolean isSupported(boolean); + method public boolean isTrackSelected(int); + method public boolean isTrackSupported(int); + method public boolean isTrackSupported(int, boolean); + method public android.os.Bundle toBundle(); + field public final int length; + } + + public final class VideoSize { + field public static final androidx.media3.common.VideoSize UNKNOWN; + field @IntRange(from=0) public final int height; + field @FloatRange(from=0, fromInclusive=false) public final float pixelWidthHeightRatio; + field @IntRange(from=0, to=359) public final int unappliedRotationDegrees; + field @IntRange(from=0) public final int width; + } + +} + +package androidx.media3.common.text { + + public final class Cue { + field public static final int ANCHOR_TYPE_END = 2; // 0x2 + field public static final int ANCHOR_TYPE_MIDDLE = 1; // 0x1 + field public static final int ANCHOR_TYPE_START = 0; // 0x0 + field public static final float DIMEN_UNSET = -3.4028235E38f; + field public static final androidx.media3.common.text.Cue EMPTY; + field public static final int LINE_TYPE_FRACTION = 0; // 0x0 + field public static final int LINE_TYPE_NUMBER = 1; // 0x1 + field public static final int TEXT_SIZE_TYPE_ABSOLUTE = 2; // 0x2 + field public static final int TEXT_SIZE_TYPE_FRACTIONAL = 0; // 0x0 + field public static final int TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING = 1; // 0x1 + field public static final int TYPE_UNSET = -2147483648; // 0x80000000 + field public static final int VERTICAL_TYPE_LR = 2; // 0x2 + field public static final int VERTICAL_TYPE_RL = 1; // 0x1 + field @Nullable public final android.graphics.Bitmap bitmap; + field public final float bitmapHeight; + field public final float line; + field @androidx.media3.common.text.Cue.AnchorType public final int lineAnchor; + field @androidx.media3.common.text.Cue.LineType public final int lineType; + field @Nullable public final android.text.Layout.Alignment multiRowAlignment; + field public final float position; + field @androidx.media3.common.text.Cue.AnchorType public final int positionAnchor; + field public final float shearDegrees; + field public final float size; + field @Nullable public final CharSequence text; + field @Nullable public final android.text.Layout.Alignment textAlignment; + field public final float textSize; + field @androidx.media3.common.text.Cue.TextSizeType public final int textSizeType; + field @androidx.media3.common.text.Cue.VerticalType public final int verticalType; + field public final int windowColor; + field public final boolean windowColorSet; + } + + @IntDef({androidx.media3.common.text.Cue.TYPE_UNSET, androidx.media3.common.text.Cue.ANCHOR_TYPE_START, androidx.media3.common.text.Cue.ANCHOR_TYPE_MIDDLE, androidx.media3.common.text.Cue.ANCHOR_TYPE_END}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Cue.AnchorType { + } + + @IntDef({androidx.media3.common.text.Cue.TYPE_UNSET, androidx.media3.common.text.Cue.LINE_TYPE_FRACTION, androidx.media3.common.text.Cue.LINE_TYPE_NUMBER}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Cue.LineType { + } + + @IntDef({androidx.media3.common.text.Cue.TYPE_UNSET, androidx.media3.common.text.Cue.TEXT_SIZE_TYPE_FRACTIONAL, androidx.media3.common.text.Cue.TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING, androidx.media3.common.text.Cue.TEXT_SIZE_TYPE_ABSOLUTE}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Cue.TextSizeType { + } + + @IntDef({androidx.media3.common.text.Cue.TYPE_UNSET, androidx.media3.common.text.Cue.VERTICAL_TYPE_RL, androidx.media3.common.text.Cue.VERTICAL_TYPE_LR}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Cue.VerticalType { + } + + public final class CueGroup { + field public final com.google.common.collect.ImmutableList cues; + } + +} + +package androidx.media3.common.util { + + public final class Util { + method public static boolean checkCleartextTrafficPermitted(androidx.media3.common.MediaItem...); + method @Nullable public static String getAdaptiveMimeTypeForContentType(@androidx.media3.common.C.ContentType int); + method @Nullable public static java.util.UUID getDrmUuid(String); + method @androidx.media3.common.C.ContentType public static int inferContentType(android.net.Uri); + method @androidx.media3.common.C.ContentType public static int inferContentTypeForExtension(String); + method @androidx.media3.common.C.ContentType public static int inferContentTypeForUriAndMimeType(android.net.Uri, @Nullable String); + method public static boolean maybeRequestReadExternalStoragePermission(android.app.Activity, android.net.Uri...); + method public static boolean maybeRequestReadExternalStoragePermission(android.app.Activity, androidx.media3.common.MediaItem...); + } + +} + +package androidx.media3.datasource { + + public interface DataSource { + } + + public static interface DataSource.Factory { + } + + public class DataSourceException extends java.io.IOException { + field @androidx.media3.common.PlaybackException.ErrorCode public final int reason; + } + + public final class DefaultDataSource implements androidx.media3.datasource.DataSource { + } + + public static final class DefaultDataSource.Factory implements androidx.media3.datasource.DataSource.Factory { + ctor public DefaultDataSource.Factory(android.content.Context); + ctor public DefaultDataSource.Factory(android.content.Context, androidx.media3.datasource.DataSource.Factory); + } + + public class DefaultHttpDataSource implements androidx.media3.datasource.DataSource androidx.media3.datasource.HttpDataSource { + } + + public static final class DefaultHttpDataSource.Factory implements androidx.media3.datasource.HttpDataSource.Factory { + ctor public DefaultHttpDataSource.Factory(); + } + + public interface HttpDataSource extends androidx.media3.datasource.DataSource { + } + + public static final class HttpDataSource.CleartextNotPermittedException extends androidx.media3.datasource.HttpDataSource.HttpDataSourceException { + } + + public static interface HttpDataSource.Factory extends androidx.media3.datasource.DataSource.Factory { + } + + public static class HttpDataSource.HttpDataSourceException extends androidx.media3.datasource.DataSourceException { + field public static final int TYPE_CLOSE = 3; // 0x3 + field public static final int TYPE_OPEN = 1; // 0x1 + field public static final int TYPE_READ = 2; // 0x2 + field @androidx.media3.datasource.HttpDataSource.HttpDataSourceException.Type public final int type; + } + + @IntDef({androidx.media3.datasource.HttpDataSource.HttpDataSourceException.TYPE_OPEN, androidx.media3.datasource.HttpDataSource.HttpDataSourceException.TYPE_READ, androidx.media3.datasource.HttpDataSource.HttpDataSourceException.TYPE_CLOSE}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) public static @interface HttpDataSource.HttpDataSourceException.Type { + } + + public static final class HttpDataSource.InvalidContentTypeException extends androidx.media3.datasource.HttpDataSource.HttpDataSourceException { + field public final String contentType; + } + + public static final class HttpDataSource.InvalidResponseCodeException extends androidx.media3.datasource.HttpDataSource.HttpDataSourceException { + field public final byte[] responseBody; + field public final int responseCode; + field @Nullable public final String responseMessage; + } + +} + +package androidx.media3.datasource.cronet { + + public class CronetDataSource implements androidx.media3.datasource.DataSource androidx.media3.datasource.HttpDataSource { + } + + public static final class CronetDataSource.Factory implements androidx.media3.datasource.HttpDataSource.Factory { + ctor public CronetDataSource.Factory(org.chromium.net.CronetEngine, java.util.concurrent.Executor); + } + + public final class CronetUtil { + method @Nullable public static org.chromium.net.CronetEngine buildCronetEngine(android.content.Context); + } + +} + +package androidx.media3.datasource.okhttp { + + public class OkHttpDataSource implements androidx.media3.datasource.DataSource androidx.media3.datasource.HttpDataSource { + } + + public static final class OkHttpDataSource.Factory implements androidx.media3.datasource.HttpDataSource.Factory { + ctor public OkHttpDataSource.Factory(okhttp3.Call.Factory); + } + +} + +package androidx.media3.exoplayer { + + public final class ExoPlaybackException extends androidx.media3.common.PlaybackException { + } + + public interface ExoPlayer extends androidx.media3.common.Player { + method public void addAnalyticsListener(androidx.media3.exoplayer.analytics.AnalyticsListener); + method @Nullable public androidx.media3.exoplayer.ExoPlaybackException getPlayerError(); + method public void removeAnalyticsListener(androidx.media3.exoplayer.analytics.AnalyticsListener); + method public void setAudioAttributes(androidx.media3.common.AudioAttributes, boolean); + method public void setHandleAudioBecomingNoisy(boolean); + method public void setWakeMode(@androidx.media3.common.C.WakeMode int); + } + + public static final class ExoPlayer.Builder { + ctor public ExoPlayer.Builder(android.content.Context); + method public androidx.media3.exoplayer.ExoPlayer build(); + method public androidx.media3.exoplayer.ExoPlayer.Builder setAudioAttributes(androidx.media3.common.AudioAttributes, boolean); + method public androidx.media3.exoplayer.ExoPlayer.Builder setHandleAudioBecomingNoisy(boolean); + method public androidx.media3.exoplayer.ExoPlayer.Builder setMediaSourceFactory(androidx.media3.exoplayer.source.MediaSource.Factory); + method public androidx.media3.exoplayer.ExoPlayer.Builder setWakeMode(@androidx.media3.common.C.WakeMode int); + } + +} + +package androidx.media3.exoplayer.analytics { + + public interface AnalyticsListener { + } + +} + +package androidx.media3.exoplayer.drm { + + @RequiresApi(18) public final class FrameworkMediaDrm { + method public static boolean isCryptoSchemeSupported(java.util.UUID); + } + +} + +package androidx.media3.exoplayer.ima { + + public final class ImaAdsLoader implements androidx.media3.exoplayer.source.ads.AdsLoader { + method public void release(); + method public void setPlayer(@Nullable androidx.media3.common.Player); + } + + public static final class ImaAdsLoader.Builder { + ctor public ImaAdsLoader.Builder(android.content.Context); + method public androidx.media3.exoplayer.ima.ImaAdsLoader build(); + } + +} + +package androidx.media3.exoplayer.source { + + public final class DefaultMediaSourceFactory implements androidx.media3.exoplayer.source.MediaSource.Factory { + ctor public DefaultMediaSourceFactory(android.content.Context); + method public androidx.media3.exoplayer.source.DefaultMediaSourceFactory clearLocalAdInsertionComponents(); + method public androidx.media3.exoplayer.source.DefaultMediaSourceFactory setDataSourceFactory(androidx.media3.datasource.DataSource.Factory); + method public androidx.media3.exoplayer.source.DefaultMediaSourceFactory setLocalAdInsertionComponents(androidx.media3.exoplayer.source.ads.AdsLoader.Provider, androidx.media3.common.AdViewProvider); + } + + public interface MediaSource { + } + + public static interface MediaSource.Factory { + } + +} + +package androidx.media3.exoplayer.source.ads { + + public interface AdsLoader { + method public void release(); + method public void setPlayer(@Nullable androidx.media3.common.Player); + } + + public static interface AdsLoader.Provider { + method @Nullable public androidx.media3.exoplayer.source.ads.AdsLoader getAdsLoader(androidx.media3.common.MediaItem.AdsConfiguration); + } + +} + +package androidx.media3.exoplayer.util { + + public class DebugTextViewHelper { + ctor public DebugTextViewHelper(androidx.media3.exoplayer.ExoPlayer, android.widget.TextView); + method public final void start(); + method public final void stop(); + } + + public class EventLogger implements androidx.media3.exoplayer.analytics.AnalyticsListener { + ctor public EventLogger(); + ctor public EventLogger(String); + } + +} + +package androidx.media3.session { + + public final class CommandButton { + field public final CharSequence displayName; + field @DrawableRes public final int iconResId; + field public final boolean isEnabled; + field @androidx.media3.common.Player.Command public final int playerCommand; + field @Nullable public final androidx.media3.session.SessionCommand sessionCommand; + } + + public static final class CommandButton.Builder { + ctor public CommandButton.Builder(); + method public androidx.media3.session.CommandButton build(); + method public androidx.media3.session.CommandButton.Builder setDisplayName(CharSequence); + method public androidx.media3.session.CommandButton.Builder setEnabled(boolean); + method public androidx.media3.session.CommandButton.Builder setExtras(android.os.Bundle); + method public androidx.media3.session.CommandButton.Builder setIconResId(@DrawableRes int); + method public androidx.media3.session.CommandButton.Builder setPlayerCommand(@androidx.media3.common.Player.Command int); + method public androidx.media3.session.CommandButton.Builder setSessionCommand(androidx.media3.session.SessionCommand); + } + + public final class LibraryResult { + method public static androidx.media3.session.LibraryResult ofError(@androidx.media3.session.LibraryResult.Code int); + method public static androidx.media3.session.LibraryResult ofError(@androidx.media3.session.LibraryResult.Code int, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + method public static androidx.media3.session.LibraryResult ofItem(androidx.media3.common.MediaItem, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + method public static androidx.media3.session.LibraryResult> ofItemList(java.util.List, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + method public static androidx.media3.session.LibraryResult ofVoid(); + method public static androidx.media3.session.LibraryResult ofVoid(@Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + field public static final int RESULT_ERROR_BAD_VALUE = -3; // 0xfffffffd + field public static final int RESULT_ERROR_INVALID_STATE = -2; // 0xfffffffe + field public static final int RESULT_ERROR_IO = -5; // 0xfffffffb + field public static final int RESULT_ERROR_NOT_SUPPORTED = -6; // 0xfffffffa + field public static final int RESULT_ERROR_PERMISSION_DENIED = -4; // 0xfffffffc + field public static final int RESULT_ERROR_SESSION_AUTHENTICATION_EXPIRED = -102; // 0xffffff9a + field public static final int RESULT_ERROR_SESSION_CONCURRENT_STREAM_LIMIT = -104; // 0xffffff98 + field public static final int RESULT_ERROR_SESSION_DISCONNECTED = -100; // 0xffffff9c + field public static final int RESULT_ERROR_SESSION_NOT_AVAILABLE_IN_REGION = -106; // 0xffffff96 + field public static final int RESULT_ERROR_SESSION_PARENTAL_CONTROL_RESTRICTED = -105; // 0xffffff97 + field public static final int RESULT_ERROR_SESSION_PREMIUM_ACCOUNT_REQUIRED = -103; // 0xffffff99 + field public static final int RESULT_ERROR_SESSION_SETUP_REQUIRED = -108; // 0xffffff94 + field public static final int RESULT_ERROR_SESSION_SKIP_LIMIT_REACHED = -107; // 0xffffff95 + field public static final int RESULT_ERROR_UNKNOWN = -1; // 0xffffffff + field public static final int RESULT_INFO_SKIPPED = 1; // 0x1 + field public static final int RESULT_SUCCESS = 0; // 0x0 + field public final long completionTimeMs; + field @Nullable public final androidx.media3.session.MediaLibraryService.LibraryParams params; + field @androidx.media3.session.LibraryResult.Code public final int resultCode; + field @Nullable public final V value; + } + + @IntDef({androidx.media3.session.LibraryResult.RESULT_SUCCESS, androidx.media3.session.LibraryResult.RESULT_ERROR_UNKNOWN, androidx.media3.session.LibraryResult.RESULT_ERROR_INVALID_STATE, androidx.media3.session.LibraryResult.RESULT_ERROR_BAD_VALUE, androidx.media3.session.LibraryResult.RESULT_ERROR_PERMISSION_DENIED, androidx.media3.session.LibraryResult.RESULT_ERROR_IO, androidx.media3.session.LibraryResult.RESULT_INFO_SKIPPED, androidx.media3.session.LibraryResult.RESULT_ERROR_SESSION_DISCONNECTED, androidx.media3.session.LibraryResult.RESULT_ERROR_NOT_SUPPORTED, androidx.media3.session.LibraryResult.RESULT_ERROR_SESSION_AUTHENTICATION_EXPIRED, androidx.media3.session.LibraryResult.RESULT_ERROR_SESSION_PREMIUM_ACCOUNT_REQUIRED, androidx.media3.session.LibraryResult.RESULT_ERROR_SESSION_CONCURRENT_STREAM_LIMIT, androidx.media3.session.LibraryResult.RESULT_ERROR_SESSION_PARENTAL_CONTROL_RESTRICTED, androidx.media3.session.LibraryResult.RESULT_ERROR_SESSION_NOT_AVAILABLE_IN_REGION, androidx.media3.session.LibraryResult.RESULT_ERROR_SESSION_SKIP_LIMIT_REACHED, androidx.media3.session.LibraryResult.RESULT_ERROR_SESSION_SETUP_REQUIRED}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) public static @interface LibraryResult.Code { + } + + public final class MediaBrowser extends androidx.media3.session.MediaController { + method public com.google.common.util.concurrent.ListenableFuture>> getChildren(String, @IntRange(from=0) int, @IntRange(from=1) int, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + method public com.google.common.util.concurrent.ListenableFuture> getItem(String); + method public com.google.common.util.concurrent.ListenableFuture> getLibraryRoot(@Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + method public com.google.common.util.concurrent.ListenableFuture>> getSearchResult(String, @IntRange(from=0) int, @IntRange(from=1) int, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + method public com.google.common.util.concurrent.ListenableFuture> search(String, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + method public com.google.common.util.concurrent.ListenableFuture> subscribe(String, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + method public com.google.common.util.concurrent.ListenableFuture> unsubscribe(String); + } + + public static final class MediaBrowser.Builder { + ctor public MediaBrowser.Builder(android.content.Context, androidx.media3.session.SessionToken); + method public com.google.common.util.concurrent.ListenableFuture buildAsync(); + method public androidx.media3.session.MediaBrowser.Builder setApplicationLooper(android.os.Looper); + method public androidx.media3.session.MediaBrowser.Builder setConnectionHints(android.os.Bundle); + method public androidx.media3.session.MediaBrowser.Builder setListener(androidx.media3.session.MediaBrowser.Listener); + } + + public static interface MediaBrowser.Listener extends androidx.media3.session.MediaController.Listener { + method public default void onChildrenChanged(androidx.media3.session.MediaBrowser, String, @IntRange(from=0) int, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + method public default void onSearchResultChanged(androidx.media3.session.MediaBrowser, String, @IntRange(from=0) int, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + } + + public final class MediaConstants { + field public static final int ERROR_CODE_AUTHENTICATION_EXPIRED_COMPAT = 3; // 0x3 + field public static final String EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT_COMPAT = "android.media.extras.ERROR_RESOLUTION_ACTION_INTENT"; + field public static final String EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL_COMPAT = "android.media.extras.ERROR_RESOLUTION_ACTION_LABEL"; + field public static final String EXTRAS_KEY_SLOT_RESERVATION_SEEK_TO_NEXT = "android.media.playback.ALWAYS_RESERVE_SPACE_FOR.ACTION_SKIP_TO_NEXT"; + field public static final String EXTRAS_KEY_SLOT_RESERVATION_SEEK_TO_PREV = "android.media.playback.ALWAYS_RESERVE_SPACE_FOR.ACTION_SKIP_TO_PREVIOUS"; + } + + public class MediaController implements androidx.media3.common.Player { + method public void addListener(androidx.media3.common.Player.Listener); + method public void addMediaItem(androidx.media3.common.MediaItem); + method public void addMediaItem(int, androidx.media3.common.MediaItem); + method public void addMediaItems(java.util.List); + method public void addMediaItems(int, java.util.List); + method public boolean canAdvertiseSession(); + method public void clearMediaItems(); + method public void clearVideoSurface(); + method public void clearVideoSurface(@Nullable android.view.Surface); + method public void clearVideoSurfaceHolder(@Nullable android.view.SurfaceHolder); + method public void clearVideoSurfaceView(@Nullable android.view.SurfaceView); + method public void clearVideoTextureView(@Nullable android.view.TextureView); + method public void decreaseDeviceVolume(); + method public android.os.Looper getApplicationLooper(); + method public androidx.media3.common.AudioAttributes getAudioAttributes(); + method public androidx.media3.common.Player.Commands getAvailableCommands(); + method public androidx.media3.session.SessionCommands getAvailableSessionCommands(); + method @IntRange(from=0, to=100) public int getBufferedPercentage(); + method public long getBufferedPosition(); + method @Nullable public androidx.media3.session.SessionToken getConnectedToken(); + method public long getContentBufferedPosition(); + method public long getContentDuration(); + method public long getContentPosition(); + method public int getCurrentAdGroupIndex(); + method public int getCurrentAdIndexInAdGroup(); + method public androidx.media3.common.text.CueGroup getCurrentCues(); + method public long getCurrentLiveOffset(); + method @Nullable public androidx.media3.common.MediaItem getCurrentMediaItem(); + method public int getCurrentMediaItemIndex(); + method public int getCurrentPeriodIndex(); + method public long getCurrentPosition(); + method public androidx.media3.common.Timeline getCurrentTimeline(); + method public androidx.media3.common.Tracks getCurrentTracks(); + method public androidx.media3.common.DeviceInfo getDeviceInfo(); + method @IntRange(from=0) public int getDeviceVolume(); + method public long getDuration(); + method public long getMaxSeekToPreviousPosition(); + method public androidx.media3.common.MediaItem getMediaItemAt(int); + method public int getMediaItemCount(); + method public androidx.media3.common.MediaMetadata getMediaMetadata(); + method public int getNextMediaItemIndex(); + method public boolean getPlayWhenReady(); + method public androidx.media3.common.PlaybackParameters getPlaybackParameters(); + method @androidx.media3.common.Player.State public int getPlaybackState(); + method @androidx.media3.common.Player.PlaybackSuppressionReason public int getPlaybackSuppressionReason(); + method @Nullable public androidx.media3.common.PlaybackException getPlayerError(); + method public androidx.media3.common.MediaMetadata getPlaylistMetadata(); + method public int getPreviousMediaItemIndex(); + method @androidx.media3.common.Player.RepeatMode public int getRepeatMode(); + method public long getSeekBackIncrement(); + method public long getSeekForwardIncrement(); + method @Nullable public android.app.PendingIntent getSessionActivity(); + method public boolean getShuffleModeEnabled(); + method public long getTotalBufferedDuration(); + method public androidx.media3.common.TrackSelectionParameters getTrackSelectionParameters(); + method public androidx.media3.common.VideoSize getVideoSize(); + method @FloatRange(from=0, to=1) public float getVolume(); + method public boolean hasNextMediaItem(); + method public boolean hasPreviousMediaItem(); + method public void increaseDeviceVolume(); + method public boolean isCommandAvailable(@androidx.media3.common.Player.Command int); + method public boolean isConnected(); + method public boolean isCurrentMediaItemDynamic(); + method public boolean isCurrentMediaItemLive(); + method public boolean isCurrentMediaItemSeekable(); + method public boolean isDeviceMuted(); + method public boolean isLoading(); + method public boolean isPlaying(); + method public boolean isPlayingAd(); + method public boolean isSessionCommandAvailable(@androidx.media3.session.SessionCommand.CommandCode int); + method public boolean isSessionCommandAvailable(androidx.media3.session.SessionCommand); + method public void moveMediaItem(int, int); + method public void moveMediaItems(int, int, int); + method public void pause(); + method public void play(); + method public void prepare(); + method public void release(); + method public static void releaseFuture(java.util.concurrent.Future); + method public void removeListener(androidx.media3.common.Player.Listener); + method public void removeMediaItem(int); + method public void removeMediaItems(int, int); + method public void seekBack(); + method public void seekForward(); + method public void seekTo(long); + method public void seekTo(int, long); + method public void seekToDefaultPosition(); + method public void seekToDefaultPosition(int); + method public void seekToNext(); + method public void seekToNextMediaItem(); + method public void seekToPrevious(); + method public void seekToPreviousMediaItem(); + method public com.google.common.util.concurrent.ListenableFuture sendCustomCommand(androidx.media3.session.SessionCommand, android.os.Bundle); + method public void setDeviceMuted(boolean); + method public void setDeviceVolume(@IntRange(from=0) int); + method public void setMediaItem(androidx.media3.common.MediaItem); + method public void setMediaItem(androidx.media3.common.MediaItem, long); + method public void setMediaItem(androidx.media3.common.MediaItem, boolean); + method public void setMediaItems(java.util.List); + method public void setMediaItems(java.util.List, boolean); + method public void setMediaItems(java.util.List, int, long); + method public void setPlayWhenReady(boolean); + method public void setPlaybackParameters(androidx.media3.common.PlaybackParameters); + method public void setPlaybackSpeed(float); + method public void setPlaylistMetadata(androidx.media3.common.MediaMetadata); + method public com.google.common.util.concurrent.ListenableFuture setRating(String, androidx.media3.common.Rating); + method public com.google.common.util.concurrent.ListenableFuture setRating(androidx.media3.common.Rating); + method public void setRepeatMode(@androidx.media3.common.Player.RepeatMode int); + method public void setShuffleModeEnabled(boolean); + method public void setTrackSelectionParameters(androidx.media3.common.TrackSelectionParameters); + method public void setVideoSurface(@Nullable android.view.Surface); + method public void setVideoSurfaceHolder(@Nullable android.view.SurfaceHolder); + method public void setVideoSurfaceView(@Nullable android.view.SurfaceView); + method public void setVideoTextureView(@Nullable android.view.TextureView); + method public void setVolume(@FloatRange(from=0, to=1) float); + method public void stop(); + } + + public static final class MediaController.Builder { + ctor public MediaController.Builder(android.content.Context, androidx.media3.session.SessionToken); + method public com.google.common.util.concurrent.ListenableFuture buildAsync(); + method public androidx.media3.session.MediaController.Builder setApplicationLooper(android.os.Looper); + method public androidx.media3.session.MediaController.Builder setConnectionHints(android.os.Bundle); + method public androidx.media3.session.MediaController.Builder setListener(androidx.media3.session.MediaController.Listener); + } + + public static interface MediaController.Listener { + method public default void onAvailableSessionCommandsChanged(androidx.media3.session.MediaController, androidx.media3.session.SessionCommands); + method public default com.google.common.util.concurrent.ListenableFuture onCustomCommand(androidx.media3.session.MediaController, androidx.media3.session.SessionCommand, android.os.Bundle); + method public default void onDisconnected(androidx.media3.session.MediaController); + method public default void onExtrasChanged(androidx.media3.session.MediaController, android.os.Bundle); + method public default com.google.common.util.concurrent.ListenableFuture onSetCustomLayout(androidx.media3.session.MediaController, java.util.List); + } + + public abstract class MediaLibraryService extends androidx.media3.session.MediaSessionService { + ctor public MediaLibraryService(); + method @Nullable public abstract androidx.media3.session.MediaLibraryService.MediaLibrarySession onGetSession(androidx.media3.session.MediaSession.ControllerInfo); + field public static final String SERVICE_INTERFACE = "androidx.media3.session.MediaLibraryService"; + } + + public static final class MediaLibraryService.LibraryParams { + field public final boolean isOffline; + field public final boolean isRecent; + field public final boolean isSuggested; + } + + public static final class MediaLibraryService.LibraryParams.Builder { + ctor public MediaLibraryService.LibraryParams.Builder(); + method public androidx.media3.session.MediaLibraryService.LibraryParams build(); + method public androidx.media3.session.MediaLibraryService.LibraryParams.Builder setOffline(boolean); + method public androidx.media3.session.MediaLibraryService.LibraryParams.Builder setRecent(boolean); + method public androidx.media3.session.MediaLibraryService.LibraryParams.Builder setSuggested(boolean); + } + + public static final class MediaLibraryService.MediaLibrarySession extends androidx.media3.session.MediaSession { + method public void notifyChildrenChanged(androidx.media3.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + method public void notifyChildrenChanged(String, @IntRange(from=0) int, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + method public void notifySearchResultChanged(androidx.media3.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + } + + public static final class MediaLibraryService.MediaLibrarySession.Builder { + ctor public MediaLibraryService.MediaLibrarySession.Builder(androidx.media3.session.MediaLibraryService, androidx.media3.common.Player, androidx.media3.session.MediaLibraryService.MediaLibrarySession.Callback); + method public androidx.media3.session.MediaLibraryService.MediaLibrarySession build(); + method public androidx.media3.session.MediaLibraryService.MediaLibrarySession.Builder setExtras(android.os.Bundle); + method public androidx.media3.session.MediaLibraryService.MediaLibrarySession.Builder setId(String); + method public androidx.media3.session.MediaLibraryService.MediaLibrarySession.Builder setSessionActivity(android.app.PendingIntent); + } + + public static interface MediaLibraryService.MediaLibrarySession.Callback extends androidx.media3.session.MediaSession.Callback { + method public default com.google.common.util.concurrent.ListenableFuture>> onGetChildren(androidx.media3.session.MediaLibraryService.MediaLibrarySession, androidx.media3.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @IntRange(from=1) int, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + method public default com.google.common.util.concurrent.ListenableFuture> onGetItem(androidx.media3.session.MediaLibraryService.MediaLibrarySession, androidx.media3.session.MediaSession.ControllerInfo, String); + method public default com.google.common.util.concurrent.ListenableFuture> onGetLibraryRoot(androidx.media3.session.MediaLibraryService.MediaLibrarySession, androidx.media3.session.MediaSession.ControllerInfo, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + method public default com.google.common.util.concurrent.ListenableFuture>> onGetSearchResult(androidx.media3.session.MediaLibraryService.MediaLibrarySession, androidx.media3.session.MediaSession.ControllerInfo, String, @IntRange(from=0) int, @IntRange(from=1) int, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + method public default com.google.common.util.concurrent.ListenableFuture> onSearch(androidx.media3.session.MediaLibraryService.MediaLibrarySession, androidx.media3.session.MediaSession.ControllerInfo, String, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + method public default com.google.common.util.concurrent.ListenableFuture> onSubscribe(androidx.media3.session.MediaLibraryService.MediaLibrarySession, androidx.media3.session.MediaSession.ControllerInfo, String, @Nullable androidx.media3.session.MediaLibraryService.LibraryParams); + method public default com.google.common.util.concurrent.ListenableFuture> onUnsubscribe(androidx.media3.session.MediaLibraryService.MediaLibrarySession, androidx.media3.session.MediaSession.ControllerInfo, String); + } + + public final class MediaNotification { + ctor public MediaNotification(@IntRange(from=1) int, android.app.Notification); + field public final android.app.Notification notification; + field @IntRange(from=1) public final int notificationId; + } + + public class MediaSession { + method public void broadcastCustomCommand(androidx.media3.session.SessionCommand, android.os.Bundle); + method public java.util.List getConnectedControllers(); + method public String getId(); + method public androidx.media3.common.Player getPlayer(); + method @Nullable public android.app.PendingIntent getSessionActivity(); + method public androidx.media3.session.SessionToken getToken(); + method public void release(); + method public com.google.common.util.concurrent.ListenableFuture sendCustomCommand(androidx.media3.session.MediaSession.ControllerInfo, androidx.media3.session.SessionCommand, android.os.Bundle); + method public void setAvailableCommands(androidx.media3.session.MediaSession.ControllerInfo, androidx.media3.session.SessionCommands, androidx.media3.common.Player.Commands); + method public com.google.common.util.concurrent.ListenableFuture setCustomLayout(androidx.media3.session.MediaSession.ControllerInfo, java.util.List); + method public void setCustomLayout(java.util.List); + method public void setPlayer(androidx.media3.common.Player); + method public void setSessionExtras(android.os.Bundle); + method public void setSessionExtras(androidx.media3.session.MediaSession.ControllerInfo, android.os.Bundle); + } + + public static final class MediaSession.Builder { + ctor public MediaSession.Builder(android.content.Context, androidx.media3.common.Player); + method public androidx.media3.session.MediaSession build(); + method public androidx.media3.session.MediaSession.Builder setCallback(androidx.media3.session.MediaSession.Callback); + method public androidx.media3.session.MediaSession.Builder setExtras(android.os.Bundle); + method public androidx.media3.session.MediaSession.Builder setId(String); + method public androidx.media3.session.MediaSession.Builder setSessionActivity(android.app.PendingIntent); + } + + public static interface MediaSession.Callback { + method public default com.google.common.util.concurrent.ListenableFuture> onAddMediaItems(androidx.media3.session.MediaSession, androidx.media3.session.MediaSession.ControllerInfo, java.util.List); + method public default androidx.media3.session.MediaSession.ConnectionResult onConnect(androidx.media3.session.MediaSession, androidx.media3.session.MediaSession.ControllerInfo); + method public default com.google.common.util.concurrent.ListenableFuture onCustomCommand(androidx.media3.session.MediaSession, androidx.media3.session.MediaSession.ControllerInfo, androidx.media3.session.SessionCommand, android.os.Bundle); + method public default void onDisconnected(androidx.media3.session.MediaSession, androidx.media3.session.MediaSession.ControllerInfo); + method @androidx.media3.session.SessionResult.Code public default int onPlayerCommandRequest(androidx.media3.session.MediaSession, androidx.media3.session.MediaSession.ControllerInfo, @androidx.media3.common.Player.Command int); + method public default void onPostConnect(androidx.media3.session.MediaSession, androidx.media3.session.MediaSession.ControllerInfo); + method public default com.google.common.util.concurrent.ListenableFuture onSetRating(androidx.media3.session.MediaSession, androidx.media3.session.MediaSession.ControllerInfo, String, androidx.media3.common.Rating); + method public default com.google.common.util.concurrent.ListenableFuture onSetRating(androidx.media3.session.MediaSession, androidx.media3.session.MediaSession.ControllerInfo, androidx.media3.common.Rating); + } + + public static final class MediaSession.ConnectionResult { + method public static androidx.media3.session.MediaSession.ConnectionResult accept(androidx.media3.session.SessionCommands, androidx.media3.common.Player.Commands); + method public static androidx.media3.session.MediaSession.ConnectionResult reject(); + field public final androidx.media3.common.Player.Commands availablePlayerCommands; + field public final androidx.media3.session.SessionCommands availableSessionCommands; + field public final boolean isAccepted; + } + + public static final class MediaSession.ControllerInfo { + method public android.os.Bundle getConnectionHints(); + method public int getControllerVersion(); + method public String getPackageName(); + method public int getUid(); + field public static final int LEGACY_CONTROLLER_VERSION = 0; // 0x0 + } + + public abstract class MediaSessionService extends android.app.Service { + ctor public MediaSessionService(); + method public final void addSession(androidx.media3.session.MediaSession); + method public final java.util.List getSessions(); + method public final boolean isSessionAdded(androidx.media3.session.MediaSession); + method @CallSuper @Nullable public android.os.IBinder onBind(@Nullable android.content.Intent); + method @Nullable public abstract androidx.media3.session.MediaSession onGetSession(androidx.media3.session.MediaSession.ControllerInfo); + method public void onUpdateNotification(androidx.media3.session.MediaSession); + method public final void removeSession(androidx.media3.session.MediaSession); + field public static final String SERVICE_INTERFACE = "androidx.media3.session.MediaSessionService"; + } + + public final class SessionCommand { + ctor public SessionCommand(@androidx.media3.session.SessionCommand.CommandCode int); + ctor public SessionCommand(String, android.os.Bundle); + field public static final int COMMAND_CODE_CUSTOM = 0; // 0x0 + field public static final int COMMAND_CODE_LIBRARY_GET_CHILDREN = 50003; // 0xc353 + field public static final int COMMAND_CODE_LIBRARY_GET_ITEM = 50004; // 0xc354 + field public static final int COMMAND_CODE_LIBRARY_GET_LIBRARY_ROOT = 50000; // 0xc350 + field public static final int COMMAND_CODE_LIBRARY_GET_SEARCH_RESULT = 50006; // 0xc356 + field public static final int COMMAND_CODE_LIBRARY_SEARCH = 50005; // 0xc355 + field public static final int COMMAND_CODE_LIBRARY_SUBSCRIBE = 50001; // 0xc351 + field public static final int COMMAND_CODE_LIBRARY_UNSUBSCRIBE = 50002; // 0xc352 + field public static final int COMMAND_CODE_SESSION_SET_RATING = 40010; // 0x9c4a + field @androidx.media3.session.SessionCommand.CommandCode public final int commandCode; + field public final String customAction; + field public final android.os.Bundle customExtras; + } + + @IntDef({androidx.media3.session.SessionCommand.COMMAND_CODE_CUSTOM, androidx.media3.session.SessionCommand.COMMAND_CODE_SESSION_SET_RATING, androidx.media3.session.SessionCommand.COMMAND_CODE_LIBRARY_GET_LIBRARY_ROOT, androidx.media3.session.SessionCommand.COMMAND_CODE_LIBRARY_SUBSCRIBE, androidx.media3.session.SessionCommand.COMMAND_CODE_LIBRARY_UNSUBSCRIBE, androidx.media3.session.SessionCommand.COMMAND_CODE_LIBRARY_GET_CHILDREN, androidx.media3.session.SessionCommand.COMMAND_CODE_LIBRARY_GET_ITEM, androidx.media3.session.SessionCommand.COMMAND_CODE_LIBRARY_SEARCH, androidx.media3.session.SessionCommand.COMMAND_CODE_LIBRARY_GET_SEARCH_RESULT}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) public static @interface SessionCommand.CommandCode { + } + + public final class SessionCommands { + method public androidx.media3.session.SessionCommands.Builder buildUpon(); + method public boolean contains(androidx.media3.session.SessionCommand); + method public boolean contains(@androidx.media3.session.SessionCommand.CommandCode int); + field public static final androidx.media3.session.SessionCommands EMPTY; + field public final com.google.common.collect.ImmutableSet commands; + } + + public static final class SessionCommands.Builder { + ctor public SessionCommands.Builder(); + method public androidx.media3.session.SessionCommands.Builder add(androidx.media3.session.SessionCommand); + method public androidx.media3.session.SessionCommands.Builder add(@androidx.media3.session.SessionCommand.CommandCode int); + method public androidx.media3.session.SessionCommands build(); + method public androidx.media3.session.SessionCommands.Builder remove(androidx.media3.session.SessionCommand); + method public androidx.media3.session.SessionCommands.Builder remove(@androidx.media3.session.SessionCommand.CommandCode int); + } + + public final class SessionResult { + ctor public SessionResult(@androidx.media3.session.SessionResult.Code int); + ctor public SessionResult(@androidx.media3.session.SessionResult.Code int, android.os.Bundle); + field public static final int RESULT_ERROR_BAD_VALUE = -3; // 0xfffffffd + field public static final int RESULT_ERROR_INVALID_STATE = -2; // 0xfffffffe + field public static final int RESULT_ERROR_IO = -5; // 0xfffffffb + field public static final int RESULT_ERROR_NOT_SUPPORTED = -6; // 0xfffffffa + field public static final int RESULT_ERROR_PERMISSION_DENIED = -4; // 0xfffffffc + field public static final int RESULT_ERROR_SESSION_AUTHENTICATION_EXPIRED = -102; // 0xffffff9a + field public static final int RESULT_ERROR_SESSION_CONCURRENT_STREAM_LIMIT = -104; // 0xffffff98 + field public static final int RESULT_ERROR_SESSION_DISCONNECTED = -100; // 0xffffff9c + field public static final int RESULT_ERROR_SESSION_NOT_AVAILABLE_IN_REGION = -106; // 0xffffff96 + field public static final int RESULT_ERROR_SESSION_PARENTAL_CONTROL_RESTRICTED = -105; // 0xffffff97 + field public static final int RESULT_ERROR_SESSION_PREMIUM_ACCOUNT_REQUIRED = -103; // 0xffffff99 + field public static final int RESULT_ERROR_SESSION_SETUP_REQUIRED = -108; // 0xffffff94 + field public static final int RESULT_ERROR_SESSION_SKIP_LIMIT_REACHED = -107; // 0xffffff95 + field public static final int RESULT_ERROR_UNKNOWN = -1; // 0xffffffff + field public static final int RESULT_INFO_SKIPPED = 1; // 0x1 + field public static final int RESULT_SUCCESS = 0; // 0x0 + field public final long completionTimeMs; + field public final android.os.Bundle extras; + field @androidx.media3.session.SessionResult.Code public final int resultCode; + } + + @IntDef({androidx.media3.session.SessionResult.RESULT_SUCCESS, androidx.media3.session.SessionResult.RESULT_ERROR_UNKNOWN, androidx.media3.session.SessionResult.RESULT_ERROR_INVALID_STATE, androidx.media3.session.SessionResult.RESULT_ERROR_BAD_VALUE, androidx.media3.session.SessionResult.RESULT_ERROR_PERMISSION_DENIED, androidx.media3.session.SessionResult.RESULT_ERROR_IO, androidx.media3.session.SessionResult.RESULT_INFO_SKIPPED, androidx.media3.session.SessionResult.RESULT_ERROR_SESSION_DISCONNECTED, androidx.media3.session.SessionResult.RESULT_ERROR_NOT_SUPPORTED, androidx.media3.session.SessionResult.RESULT_ERROR_SESSION_AUTHENTICATION_EXPIRED, androidx.media3.session.SessionResult.RESULT_ERROR_SESSION_PREMIUM_ACCOUNT_REQUIRED, androidx.media3.session.SessionResult.RESULT_ERROR_SESSION_CONCURRENT_STREAM_LIMIT, androidx.media3.session.SessionResult.RESULT_ERROR_SESSION_PARENTAL_CONTROL_RESTRICTED, androidx.media3.session.SessionResult.RESULT_ERROR_SESSION_NOT_AVAILABLE_IN_REGION, androidx.media3.session.SessionResult.RESULT_ERROR_SESSION_SKIP_LIMIT_REACHED, androidx.media3.session.SessionResult.RESULT_ERROR_SESSION_SETUP_REQUIRED}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) public static @interface SessionResult.Code { + } + + public final class SessionToken { + ctor public SessionToken(android.content.Context, android.content.ComponentName); + method public static com.google.common.collect.ImmutableSet getAllServiceTokens(android.content.Context); + method public android.os.Bundle getExtras(); + method public String getPackageName(); + method public String getServiceName(); + method public int getSessionVersion(); + method @androidx.media3.session.SessionToken.TokenType public int getType(); + method public int getUid(); + field public static final int TYPE_LIBRARY_SERVICE = 2; // 0x2 + field public static final int TYPE_SESSION = 0; // 0x0 + field public static final int TYPE_SESSION_SERVICE = 1; // 0x1 + } + + @IntDef({androidx.media3.session.SessionToken.TYPE_SESSION, androidx.media3.session.SessionToken.TYPE_SESSION_SERVICE, androidx.media3.session.SessionToken.TYPE_LIBRARY_SERVICE}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) public static @interface SessionToken.TokenType { + } + +} + +package androidx.media3.ui { + + public class PlayerView extends android.widget.FrameLayout implements androidx.media3.common.AdViewProvider { + ctor public PlayerView(android.content.Context); + ctor public PlayerView(android.content.Context, @Nullable android.util.AttributeSet); + ctor public PlayerView(android.content.Context, @Nullable android.util.AttributeSet, int); + method public android.view.ViewGroup getAdViewGroup(); + method @Nullable public androidx.media3.common.Player getPlayer(); + method public boolean getUseController(); + method public void onPause(); + method public void onResume(); + method public void setControllerVisibilityListener(@Nullable androidx.media3.ui.PlayerView.ControllerVisibilityListener); + method public void setErrorMessageProvider(@Nullable androidx.media3.common.ErrorMessageProvider); + method public void setFullscreenButtonClickListener(@Nullable androidx.media3.ui.PlayerView.FullscreenButtonClickListener); + method public void setPlayer(@Nullable androidx.media3.common.Player); + method public void setUseController(boolean); + } + + public static interface PlayerView.ControllerVisibilityListener { + method public void onVisibilityChanged(int); + } + + public static interface PlayerView.FullscreenButtonClickListener { + method public void onFullscreenButtonClick(boolean); + } + +} + From 7563bd2792d85c61223c12dd0c4c5a77d1b75b13 Mon Sep 17 00:00:00 2001 From: christosts Date: Thu, 16 Jun 2022 14:39:46 +0000 Subject: [PATCH 29/73] Misc improvement in Util #minor-release PiperOrigin-RevId: 455380010 --- .../src/main/java/androidx/media3/common/util/Util.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/common/src/main/java/androidx/media3/common/util/Util.java b/libraries/common/src/main/java/androidx/media3/common/util/Util.java index 02fab9ce93..ce6bec8d3a 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/Util.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/Util.java @@ -311,9 +311,9 @@ public static boolean maybeRequestReadExternalStoragePermission( } private static boolean maybeRequestReadExternalStoragePermission(Activity activity, Uri uri) { - return SDK_INT >= 23 && (isLocalFileUri(uri) || isMediaStoreExternalContentUri(uri)) - ? requestExternalStoragePermission(activity) - : false; + return SDK_INT >= 23 + && (isLocalFileUri(uri) || isMediaStoreExternalContentUri(uri)) + && requestExternalStoragePermission(activity); } private static boolean isMediaStoreExternalContentUri(Uri uri) { From 981baae7095ef34c548df600bfbea1f7765dbb9e Mon Sep 17 00:00:00 2001 From: hschlueter Date: Fri, 17 Jun 2022 16:57:46 +0100 Subject: [PATCH 30/73] Implement chaining GlTextureProcessor.Listener. In follow-ups the FrameProcessorChain will set an instance of this listener for each GlTextureProcessor to chain it with its previous and next GlTextureProcesssor. PiperOrigin-RevId: 455628942 --- .../ChainingGlTextureProcessorListener.java | 106 ++++++++++++ .../transformer/FrameProcessorChain.java | 5 +- ...hainingGlTextureProcessorListenerTest.java | 163 ++++++++++++++++++ 3 files changed, 272 insertions(+), 2 deletions(-) create mode 100644 libraries/transformer/src/main/java/androidx/media3/transformer/ChainingGlTextureProcessorListener.java create mode 100644 libraries/transformer/src/test/java/androidx/media3/transformer/ChainingGlTextureProcessorListenerTest.java diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/ChainingGlTextureProcessorListener.java b/libraries/transformer/src/main/java/androidx/media3/transformer/ChainingGlTextureProcessorListener.java new file mode 100644 index 0000000000..3017107b2f --- /dev/null +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/ChainingGlTextureProcessorListener.java @@ -0,0 +1,106 @@ +/* + * Copyright 2022 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 androidx.media3.transformer; + +import android.util.Pair; +import androidx.annotation.Nullable; +import java.util.ArrayDeque; +import java.util.Queue; + +/** + * A {@link GlTextureProcessor.Listener} that connects the {@link GlTextureProcessor} it is + * {@linkplain GlTextureProcessor#setListener(GlTextureProcessor.Listener) set} on to a previous and + * next {@link GlTextureProcessor}. + */ +/* package */ final class ChainingGlTextureProcessorListener + implements GlTextureProcessor.Listener { + + @Nullable private final GlTextureProcessor previousGlTextureProcessor; + @Nullable private final GlTextureProcessor nextGlTextureProcessor; + private final FrameProcessingTaskExecutor frameProcessingTaskExecutor; + private final FrameProcessorChain.Listener frameProcessorChainListener; + private final Queue> pendingFrames; + + /** + * Creates a new instance. + * + * @param previousGlTextureProcessor The {@link GlTextureProcessor} that comes before the {@link + * GlTextureProcessor} this listener is set on or {@code null} if not applicable. + * @param nextGlTextureProcessor The {@link GlTextureProcessor} that comes after the {@link + * GlTextureProcessor} this listener is set on or {@code null} if not applicable. + * @param frameProcessingTaskExecutor The {@link FrameProcessingTaskExecutor} that is used for + * OpenGL calls. All calls to the previous/next {@link GlTextureProcessor} will be executed by + * the {@link FrameProcessingTaskExecutor}. The caller is responsible for releasing the {@link + * FrameProcessingTaskExecutor}. + * @param frameProcessorChainListener The {@link FrameProcessorChain.Listener} to forward + * exceptions to. + */ + public ChainingGlTextureProcessorListener( + @Nullable GlTextureProcessor previousGlTextureProcessor, + @Nullable GlTextureProcessor nextGlTextureProcessor, + FrameProcessingTaskExecutor frameProcessingTaskExecutor, + FrameProcessorChain.Listener frameProcessorChainListener) { + this.previousGlTextureProcessor = previousGlTextureProcessor; + this.nextGlTextureProcessor = nextGlTextureProcessor; + this.frameProcessingTaskExecutor = frameProcessingTaskExecutor; + this.frameProcessorChainListener = frameProcessorChainListener; + pendingFrames = new ArrayDeque<>(); + } + + @Override + public void onInputFrameProcessed(TextureInfo inputTexture) { + if (previousGlTextureProcessor != null) { + GlTextureProcessor nonNullPreviousGlTextureProcessor = previousGlTextureProcessor; + frameProcessingTaskExecutor.submit( + () -> nonNullPreviousGlTextureProcessor.releaseOutputFrame(inputTexture)); + } + } + + @Override + public void onOutputFrameAvailable(TextureInfo outputTexture, long presentationTimeUs) { + if (nextGlTextureProcessor != null) { + GlTextureProcessor nonNullNextGlTextureProcessor = nextGlTextureProcessor; + frameProcessingTaskExecutor.submit( + () -> { + pendingFrames.add(new Pair<>(outputTexture, presentationTimeUs)); + processFrameNowOrLater(nonNullNextGlTextureProcessor); + }); + } + } + + private void processFrameNowOrLater(GlTextureProcessor nextGlTextureProcessor) { + Pair pendingFrame = pendingFrames.element(); + TextureInfo outputTexture = pendingFrame.first; + long presentationTimeUs = pendingFrame.second; + if (nextGlTextureProcessor.maybeQueueInputFrame(outputTexture, presentationTimeUs)) { + pendingFrames.remove(); + } else { + frameProcessingTaskExecutor.submit(() -> processFrameNowOrLater(nextGlTextureProcessor)); + } + } + + @Override + public void onOutputStreamEnded() { + if (nextGlTextureProcessor != null) { + frameProcessingTaskExecutor.submit(nextGlTextureProcessor::signalEndOfInputStream); + } + } + + @Override + public void onFrameProcessingError(FrameProcessingException e) { + frameProcessorChainListener.onFrameProcessingError(e); + } +} diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java index 510160e3f1..f86eda288c 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java @@ -146,11 +146,12 @@ public static FrameProcessorChain create( } /** - * Creates the OpenGL textures and framebuffers, initializes the {@link + * Creates the OpenGL context, surfaces, textures, and framebuffers, initializes the {@link * SingleFrameGlTextureProcessor SingleFrameGlTextureProcessors} corresponding to the {@link * GlEffect GlEffects}, and returns a new {@code FrameProcessorChain}. * - *

    This method must be executed using the {@code singleThreadExecutorService}. + *

    This method must be executed using the {@code singleThreadExecutorService}, as all later + * OpenGL commands will be called on that thread. */ @WorkerThread @Nullable diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/ChainingGlTextureProcessorListenerTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/ChainingGlTextureProcessorListenerTest.java new file mode 100644 index 0000000000..9c74cb9306 --- /dev/null +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/ChainingGlTextureProcessorListenerTest.java @@ -0,0 +1,163 @@ +/* + * Copyright 2022 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 androidx.media3.transformer; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import androidx.media3.common.util.Util; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Tests for {@link ChainingGlTextureProcessorListener}. */ +@RunWith(AndroidJUnit4.class) +public final class ChainingGlTextureProcessorListenerTest { + private static final long EXECUTOR_WAIT_TIME_MS = 100; + + private final FrameProcessorChain.Listener mockFrameProcessorChainListener = + mock(FrameProcessorChain.Listener.class); + private final FrameProcessingTaskExecutor frameProcessingTaskExecutor = + new FrameProcessingTaskExecutor( + Util.newSingleThreadExecutor("Test"), mockFrameProcessorChainListener); + private final GlTextureProcessor mockPreviousGlTextureProcessor = mock(GlTextureProcessor.class); + private final FakeGlTextureProcessor fakeNextGlTextureProcessor = + spy(new FakeGlTextureProcessor()); + private final ChainingGlTextureProcessorListener chainingGlTextureProcessorListener = + new ChainingGlTextureProcessorListener( + mockPreviousGlTextureProcessor, + fakeNextGlTextureProcessor, + frameProcessingTaskExecutor, + mockFrameProcessorChainListener); + + @After + public void release() throws InterruptedException { + frameProcessingTaskExecutor.release(/* releaseTask= */ () -> {}, EXECUTOR_WAIT_TIME_MS); + } + + @Test + public void onFrameProcessingError_callsListener() { + FrameProcessingException exception = new FrameProcessingException("message"); + + chainingGlTextureProcessorListener.onFrameProcessingError(exception); + + verify(mockFrameProcessorChainListener, times(1)).onFrameProcessingError(exception); + } + + @Test + public void onInputFrameProcessed_surrendersFrameToPreviousGlTextureProcessor() + throws InterruptedException { + TextureInfo texture = + new TextureInfo(/* texId= */ 1, /* fboId= */ 1, /* width= */ 100, /* height= */ 100); + + chainingGlTextureProcessorListener.onInputFrameProcessed(texture); + Thread.sleep(EXECUTOR_WAIT_TIME_MS); + + verify(mockPreviousGlTextureProcessor, times(1)).releaseOutputFrame(texture); + } + + @Test + public void onOutputFrameAvailable_passesFrameToNextGlTextureProcessor() + throws InterruptedException { + TextureInfo texture = + new TextureInfo(/* texId= */ 1, /* fboId= */ 1, /* width= */ 100, /* height= */ 100); + long presentationTimeUs = 123; + + chainingGlTextureProcessorListener.onOutputFrameAvailable(texture, presentationTimeUs); + Thread.sleep(EXECUTOR_WAIT_TIME_MS); + + verify(fakeNextGlTextureProcessor, times(1)).maybeQueueInputFrame(texture, presentationTimeUs); + } + + @Test + public void onOutputFrameAvailable_nextGlTextureProcessorRejectsFrame_triesAgain() + throws InterruptedException { + TextureInfo texture = + new TextureInfo(/* texId= */ 1, /* fboId= */ 1, /* width= */ 100, /* height= */ 100); + long presentationTimeUs = 123; + fakeNextGlTextureProcessor.rejectNextFrame(); + + chainingGlTextureProcessorListener.onOutputFrameAvailable(texture, presentationTimeUs); + Thread.sleep(EXECUTOR_WAIT_TIME_MS); + + verify(fakeNextGlTextureProcessor, times(2)).maybeQueueInputFrame(texture, presentationTimeUs); + } + + @Test + public void onOutputFrameAvailable_twoFramesWithFirstRejected_retriesFirstBeforeSecond() + throws InterruptedException { + TextureInfo firstTexture = + new TextureInfo(/* texId= */ 1, /* fboId= */ 1, /* width= */ 100, /* height= */ 100); + long firstPresentationTimeUs = 123; + TextureInfo secondTexture = + new TextureInfo(/* texId= */ 2, /* fboId= */ 2, /* width= */ 100, /* height= */ 100); + long secondPresentationTimeUs = 567; + fakeNextGlTextureProcessor.rejectNextFrame(); + + chainingGlTextureProcessorListener.onOutputFrameAvailable( + firstTexture, firstPresentationTimeUs); + chainingGlTextureProcessorListener.onOutputFrameAvailable( + secondTexture, secondPresentationTimeUs); + Thread.sleep(EXECUTOR_WAIT_TIME_MS); + + verify(fakeNextGlTextureProcessor, times(2)) + .maybeQueueInputFrame(firstTexture, firstPresentationTimeUs); + verify(fakeNextGlTextureProcessor, times(1)) + .maybeQueueInputFrame(secondTexture, secondPresentationTimeUs); + } + + @Test + public void onOutputStreamEnded_signalsInputStreamEndedToNextGlTextureProcessor() + throws InterruptedException { + chainingGlTextureProcessorListener.onOutputStreamEnded(); + Thread.sleep(EXECUTOR_WAIT_TIME_MS); + + verify(fakeNextGlTextureProcessor, times(1)).signalEndOfInputStream(); + } + + private static class FakeGlTextureProcessor implements GlTextureProcessor { + + private volatile boolean rejectNextFrame; + + public void rejectNextFrame() { + rejectNextFrame = true; + } + + @Override + public void setListener(Listener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean maybeQueueInputFrame(TextureInfo inputTexture, long presentationTimeUs) { + boolean acceptFrame = !rejectNextFrame; + rejectNextFrame = false; + return acceptFrame; + } + + @Override + public void releaseOutputFrame(TextureInfo outputTexture) {} + + @Override + public void signalEndOfInputStream() {} + + @Override + public void release() {} + } +} From 931562c24380ff8bd1f8fad6b2c0bb3581dc65e5 Mon Sep 17 00:00:00 2001 From: hschlueter Date: Mon, 20 Jun 2022 13:50:16 +0100 Subject: [PATCH 31/73] Add option to disable debug preview. This is useful for testing Transformer in the same way as it is used in tests and to see only the real transformation time. PiperOrigin-RevId: 456058466 --- .../media3/demo/transformer/ConfigurationActivity.java | 9 +++++++++ .../media3/demo/transformer/TransformerActivity.java | 5 ++++- .../src/main/res/layout/configuration_activity.xml | 10 ++++++++++ demos/transformer/src/main/res/values/strings.xml | 1 + 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/demos/transformer/src/main/java/androidx/media3/demo/transformer/ConfigurationActivity.java b/demos/transformer/src/main/java/androidx/media3/demo/transformer/ConfigurationActivity.java index 026f396091..227c517cc1 100644 --- a/demos/transformer/src/main/java/androidx/media3/demo/transformer/ConfigurationActivity.java +++ b/demos/transformer/src/main/java/androidx/media3/demo/transformer/ConfigurationActivity.java @@ -59,6 +59,7 @@ public final class ConfigurationActivity extends AppCompatActivity { public static final String TRIM_START_MS = "trim_start_ms"; public static final String TRIM_END_MS = "trim_end_ms"; public static final String ENABLE_FALLBACK = "enable_fallback"; + public static final String ENABLE_DEBUG_PREVIEW = "enable_debug_preview"; public static final String ENABLE_REQUEST_SDR_TONE_MAPPING = "enable_request_sdr_tone_mapping"; public static final String ENABLE_HDR_EDITING = "enable_hdr_editing"; public static final String DEMO_EFFECTS_SELECTIONS = "demo_effects_selections"; @@ -120,6 +121,7 @@ public final class ConfigurationActivity extends AppCompatActivity { private @MonotonicNonNull Spinner rotateSpinner; private @MonotonicNonNull CheckBox trimCheckBox; private @MonotonicNonNull CheckBox enableFallbackCheckBox; + private @MonotonicNonNull CheckBox enableDebugPreviewCheckBox; private @MonotonicNonNull CheckBox enableRequestSdrToneMappingCheckBox; private @MonotonicNonNull CheckBox enableHdrEditingCheckBox; private @MonotonicNonNull Button selectDemoEffectsButton; @@ -200,6 +202,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { trimEndMs = C.TIME_UNSET; enableFallbackCheckBox = findViewById(R.id.enable_fallback_checkbox); + enableDebugPreviewCheckBox = findViewById(R.id.enable_debug_preview_checkbox); enableRequestSdrToneMappingCheckBox = findViewById(R.id.request_sdr_tone_mapping_checkbox); enableRequestSdrToneMappingCheckBox.setEnabled(isRequestSdrToneMappingSupported()); findViewById(R.id.request_sdr_tone_mapping).setEnabled(isRequestSdrToneMappingSupported()); @@ -237,6 +240,7 @@ protected void onNewIntent(Intent intent) { "rotateSpinner", "trimCheckBox", "enableFallbackCheckBox", + "enableDebugPreviewCheckBox", "enableRequestSdrToneMappingCheckBox", "enableHdrEditingCheckBox", "demoEffectsSelections" @@ -275,6 +279,7 @@ private void startTransformation(View view) { bundle.putLong(TRIM_END_MS, trimEndMs); } bundle.putBoolean(ENABLE_FALLBACK, enableFallbackCheckBox.isChecked()); + bundle.putBoolean(ENABLE_DEBUG_PREVIEW, enableDebugPreviewCheckBox.isChecked()); bundle.putBoolean( ENABLE_REQUEST_SDR_TONE_MAPPING, enableRequestSdrToneMappingCheckBox.isChecked()); bundle.putBoolean(ENABLE_HDR_EDITING, enableHdrEditingCheckBox.isChecked()); @@ -377,6 +382,7 @@ private void selectDemoEffect(DialogInterface dialog, int which, boolean isCheck "resolutionHeightSpinner", "scaleSpinner", "rotateSpinner", + "enableDebugPreviewCheckBox", "enableRequestSdrToneMappingCheckBox", "enableHdrEditingCheckBox", "selectDemoEffectsButton" @@ -397,6 +403,7 @@ private void onRemoveAudio(View view) { "resolutionHeightSpinner", "scaleSpinner", "rotateSpinner", + "enableDebugPreviewCheckBox", "enableRequestSdrToneMappingCheckBox", "enableHdrEditingCheckBox", "selectDemoEffectsButton" @@ -416,6 +423,7 @@ private void onRemoveVideo(View view) { "resolutionHeightSpinner", "scaleSpinner", "rotateSpinner", + "enableDebugPreviewCheckBox", "enableRequestSdrToneMappingCheckBox", "enableHdrEditingCheckBox", "selectDemoEffectsButton" @@ -426,6 +434,7 @@ private void enableTrackSpecificOptions(boolean isAudioEnabled, boolean isVideoE resolutionHeightSpinner.setEnabled(isVideoEnabled); scaleSpinner.setEnabled(isVideoEnabled); rotateSpinner.setEnabled(isVideoEnabled); + enableDebugPreviewCheckBox.setEnabled(isVideoEnabled); enableRequestSdrToneMappingCheckBox.setEnabled( isRequestSdrToneMappingSupported() && isVideoEnabled); enableHdrEditingCheckBox.setEnabled(isVideoEnabled); diff --git a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java index 842769f13f..57370ff761 100644 --- a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java +++ b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java @@ -319,6 +319,10 @@ private Transformer createTransformer(@Nullable Bundle bundle, String filePath) } transformerBuilder.setVideoFrameEffects(effects.build()); } + + if (bundle.getBoolean(ConfigurationActivity.ENABLE_DEBUG_PREVIEW)) { + transformerBuilder.setDebugViewProvider(new DemoDebugViewProvider()); + } } return transformerBuilder .addListener( @@ -335,7 +339,6 @@ public void onTransformationError( TransformerActivity.this.onTransformationError(exception); } }) - .setDebugViewProvider(new DemoDebugViewProvider()) .build(); } diff --git a/demos/transformer/src/main/res/layout/configuration_activity.xml b/demos/transformer/src/main/res/layout/configuration_activity.xml index 2879d6a637..eeab077caa 100644 --- a/demos/transformer/src/main/res/layout/configuration_activity.xml +++ b/demos/transformer/src/main/res/layout/configuration_activity.xml @@ -179,6 +179,16 @@ android:layout_gravity="right" android:checked="true"/> + + + + diff --git a/demos/transformer/src/main/res/values/strings.xml b/demos/transformer/src/main/res/values/strings.xml index 50ac310080..69b68cded8 100644 --- a/demos/transformer/src/main/res/values/strings.xml +++ b/demos/transformer/src/main/res/values/strings.xml @@ -27,6 +27,7 @@ Scale video Rotate video (degrees) Enable fallback + Enable debug preview Trim Request SDR tone-mapping (API 31+) [Experimental] HDR editing From f5d8800d51def6304db9c1f5a8f5ea3f6e3c69a6 Mon Sep 17 00:00:00 2001 From: huangdarwin Date: Mon, 20 Jun 2022 14:26:12 +0100 Subject: [PATCH 32/73] FrameProcessor: Use factories instead of a builder for Presentation. PiperOrigin-RevId: 456064021 --- .../FrameProcessorChainPixelTest.java | 17 +-- .../transformer/PresentationPixelTest.java | 30 ++-- .../transformer/FrameProcessorChain.java | 8 +- .../media3/transformer/Presentation.java | 144 +++++++++--------- .../VideoTranscodingSamplePipeline.java | 3 +- .../media3/transformer/PresentationTest.java | 27 ++-- 6 files changed, 109 insertions(+), 120 deletions(-) diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java index 0820049cb9..263714eca3 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java @@ -204,10 +204,10 @@ public void processData_withScaleToFitAndMatrixTransformation_producesExpectedOu } @Test - public void processData_withPresentation_setResolution_producesExpectedOutput() throws Exception { - String testId = "processData_withPresentation_setResolution"; - setUpAndPrepareFirstFrame( - DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO, new Presentation.Builder().setResolution(480).build()); + public void processData_withPresentation_createForHeight_producesExpectedOutput() + throws Exception { + String testId = "processData_withPresentation_createForHeight"; + setUpAndPrepareFirstFrame(DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO, Presentation.createForHeight(480)); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(REQUEST_OUTPUT_HEIGHT_PNG_ASSET_PATH); Bitmap actualBitmap = processFirstFrameAndEnd(); @@ -222,14 +222,13 @@ public void processData_withPresentation_setResolution_producesExpectedOutput() } @Test - public void processData_withCropAndPresentation_producesExpectedOutput() throws Exception { - String testId = "processData_withCropAndPresentation"; + public void processData_withCropThenPresentation_producesExpectedOutput() throws Exception { + String testId = "processData_withCropThenPresentation"; setUpAndPrepareFirstFrame( DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO, new Crop(/* left= */ -.5f, /* right= */ .5f, /* bottom= */ -.5f, /* top= */ .5f), - new Presentation.Builder() - .setAspectRatio(/* aspectRatio= */ .5f, Presentation.LAYOUT_SCALE_TO_FIT) - .build()); + Presentation.createForAspectRatio( + /* aspectRatio= */ .5f, Presentation.LAYOUT_SCALE_TO_FIT)); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(CROP_THEN_ASPECT_RATIO_PNG_ASSET_PATH); Bitmap actualBitmap = processFirstFrameAndEnd(); diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationPixelTest.java index 867aed28ff..53bbbea9ee 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationPixelTest.java @@ -26,6 +26,7 @@ import android.opengl.EGLDisplay; import android.opengl.EGLSurface; import android.util.Size; +import androidx.media3.common.C; import androidx.media3.common.util.GlUtil; import androidx.test.ext.junit.runners.AndroidJUnit4; import java.io.IOException; @@ -95,7 +96,8 @@ public void release() throws GlUtil.GlException, FrameProcessingException { @Test public void drawFrame_noEdits_producesExpectedOutput() throws Exception { String testId = "drawFrame_noEdits"; - presentationTextureProcessor = new Presentation.Builder().build().toGlTextureProcessor(context); + presentationTextureProcessor = + Presentation.createForHeight(C.LENGTH_UNSET).toGlTextureProcessor(context); Size outputSize = presentationTextureProcessor.configure(inputWidth, inputHeight); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ORIGINAL_PNG_ASSET_PATH); @@ -119,9 +121,7 @@ public void drawFrame_changeAspectRatio_scaleToFit_narrow_producesExpectedOutput throws Exception { String testId = "drawFrame_changeAspectRatio_scaleToFit_narrow"; presentationTextureProcessor = - new Presentation.Builder() - .setAspectRatio(1f, Presentation.LAYOUT_SCALE_TO_FIT) - .build() + Presentation.createForAspectRatio(/* aspectRatio= */ 1f, Presentation.LAYOUT_SCALE_TO_FIT) .toGlTextureProcessor(context); Size outputSize = presentationTextureProcessor.configure(inputWidth, inputHeight); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); @@ -147,9 +147,7 @@ public void drawFrame_changeAspectRatio_scaleToFit_wide_producesExpectedOutput() throws Exception { String testId = "drawFrame_changeAspectRatio_scaleToFit_wide"; presentationTextureProcessor = - new Presentation.Builder() - .setAspectRatio(2f, Presentation.LAYOUT_SCALE_TO_FIT) - .build() + Presentation.createForAspectRatio(/* aspectRatio= */ 2f, Presentation.LAYOUT_SCALE_TO_FIT) .toGlTextureProcessor(context); Size outputSize = presentationTextureProcessor.configure(inputWidth, inputHeight); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); @@ -175,9 +173,8 @@ public void drawFrame_changeAspectRatio_scaleToFitWithCrop_narrow_producesExpect throws Exception { String testId = "drawFrame_changeAspectRatio_scaleToFitWithCrop_narrow"; presentationTextureProcessor = - new Presentation.Builder() - .setAspectRatio(1f, Presentation.LAYOUT_SCALE_TO_FIT_WITH_CROP) - .build() + Presentation.createForAspectRatio( + /* aspectRatio= */ 1f, Presentation.LAYOUT_SCALE_TO_FIT_WITH_CROP) .toGlTextureProcessor(context); Size outputSize = presentationTextureProcessor.configure(inputWidth, inputHeight); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); @@ -203,9 +200,8 @@ public void drawFrame_changeAspectRatio_scaleToFitWithCrop_wide_producesExpected throws Exception { String testId = "drawFrame_changeAspectRatio_scaleToFitWithCrop_wide"; presentationTextureProcessor = - new Presentation.Builder() - .setAspectRatio(2f, Presentation.LAYOUT_SCALE_TO_FIT_WITH_CROP) - .build() + Presentation.createForAspectRatio( + /* aspectRatio= */ 2f, Presentation.LAYOUT_SCALE_TO_FIT_WITH_CROP) .toGlTextureProcessor(context); Size outputSize = presentationTextureProcessor.configure(inputWidth, inputHeight); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); @@ -231,9 +227,7 @@ public void drawFrame_changeAspectRatio_stretchToFit_narrow_producesExpectedOutp throws Exception { String testId = "drawFrame_changeAspectRatio_stretchToFit_narrow"; presentationTextureProcessor = - new Presentation.Builder() - .setAspectRatio(1f, Presentation.LAYOUT_STRETCH_TO_FIT) - .build() + Presentation.createForAspectRatio(/* aspectRatio= */ 1f, Presentation.LAYOUT_STRETCH_TO_FIT) .toGlTextureProcessor(context); Size outputSize = presentationTextureProcessor.configure(inputWidth, inputHeight); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); @@ -259,9 +253,7 @@ public void drawFrame_changeAspectRatio_stretchToFit_wide_producesExpectedOutput throws Exception { String testId = "drawFrame_changeAspectRatio_stretchToFit_wide"; presentationTextureProcessor = - new Presentation.Builder() - .setAspectRatio(2f, Presentation.LAYOUT_STRETCH_TO_FIT) - .build() + Presentation.createForAspectRatio(/* aspectRatio= */ 2f, Presentation.LAYOUT_STRETCH_TO_FIT) .toGlTextureProcessor(context); Size outputSize = presentationTextureProcessor.configure(inputWidth, inputHeight); setupOutputTexture(outputSize.getWidth(), outputSize.getHeight()); diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java index f86eda288c..8476dadabb 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java @@ -259,12 +259,8 @@ private static FrameProcessorChain createOpenGlObjectsAndFrameProcessorChain( if (outputSurfaceInfo.width != outputSize.getWidth() || outputSurfaceInfo.height != outputSize.getHeight()) { matrixTransformationListBuilder.add( - new Presentation.Builder() - .setAspectRatio( - outputSurfaceInfo.width / (float) outputSurfaceInfo.height, - Presentation.LAYOUT_SCALE_TO_FIT) - .setResolution(outputSurfaceInfo.height) - .build()); + Presentation.createForWidthAndHeight( + outputSurfaceInfo.width, outputSurfaceInfo.height, Presentation.LAYOUT_SCALE_TO_FIT)); } // Convert final list of matrix transformations (including additional transformations for the diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/Presentation.java b/libraries/transformer/src/main/java/androidx/media3/transformer/Presentation.java index 167e83bf0f..077740aa81 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/Presentation.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/Presentation.java @@ -36,8 +36,6 @@ * the input pixels onto the output frame geometry (for example, by stretching the input frame to * match the specified output frame, or fitting the input frame using letterboxing). * - *

    Aspect ratio is applied before setting resolution. - * *

    The background color of the output frame will be black, with alpha = 0 if applicable. */ @UnstableApi @@ -49,8 +47,7 @@ public final class Presentation implements MatrixTransformation { *

    One of {@link #LAYOUT_SCALE_TO_FIT}, {@link #LAYOUT_SCALE_TO_FIT_WITH_CROP}, or {@link * #LAYOUT_STRETCH_TO_FIT}. * - *

    May scale either width or height, leaving the other output dimension equal to its input, - * unless {@link Builder#setResolution(int)} rescales width and height. + *

    May scale either width or height, leaving the other output dimension equal to its input. */ @Documented @Retention(SOURCE) @@ -100,81 +97,82 @@ public final class Presentation implements MatrixTransformation { */ public static final int LAYOUT_STRETCH_TO_FIT = 2; - /** A builder for {@link Presentation} instances. */ - public static final class Builder { - - // Optional fields. - private int outputHeight; - private float aspectRatio; - private @Layout int layout; + private static final float ASPECT_RATIO_UNSET = -1f; - /** Creates a builder with default values. */ - public Builder() { - outputHeight = C.LENGTH_UNSET; - aspectRatio = C.LENGTH_UNSET; - } + private static void checkLayout(@Layout int layout) { + checkArgument( + layout == LAYOUT_SCALE_TO_FIT + || layout == LAYOUT_SCALE_TO_FIT_WITH_CROP + || layout == LAYOUT_STRETCH_TO_FIT, + "invalid layout " + layout); + } - /** - * Sets the output resolution using the output height. - * - *

    The default value, {@link C#LENGTH_UNSET}, corresponds to using the same height as the - * input. Output width of the displayed frame will scale to preserve the frame's aspect ratio - * after other transformations. - * - *

    For example, a 1920x1440 frame can be scaled to 640x480 by calling {@code - * setResolution(480)}. - * - * @param height The output height of the displayed frame, in pixels. - * @return This builder. - */ - public Builder setResolution(int height) { - this.outputHeight = height; - return this; - } + /** + * Creates a new {@link Presentation} instance. + * + *

    The output frame will have the given aspect ratio (width/height ratio). Width or height will + * be resized to conform to this {@code aspectRatio}, given a {@link Layout}. + * + * @param aspectRatio The aspect ratio (width/height ratio) of the output frame. Must be positive. + * @param layout The layout of the output frame. + */ + public static Presentation createForAspectRatio(float aspectRatio, @Layout int layout) { + checkArgument( + aspectRatio == C.LENGTH_UNSET || aspectRatio > 0, + "aspect ratio " + aspectRatio + " must be positive or unset"); + checkLayout(layout); + return new Presentation( + /* width= */ C.LENGTH_UNSET, /* height= */ C.LENGTH_UNSET, aspectRatio, layout); + } - /** - * Sets the aspect ratio (width/height ratio) for the output frame. - * - *

    Resizes a frame's width or height to conform to an {@code aspectRatio}, given a {@link - * Layout}. {@code aspectRatio} defaults to {@link C#LENGTH_UNSET}, which corresponds to the - * same aspect ratio as the input frame. {@code layout} defaults to {@link #LAYOUT_SCALE_TO_FIT} - * - *

    Width and height values set may be rescaled by {@link #setResolution(int)}, which is - * applied after aspect ratio changes. - * - * @param aspectRatio The aspect ratio (width/height ratio) of the output frame. Must be - * positive. - * @return This builder. - */ - public Builder setAspectRatio(float aspectRatio, @Layout int layout) { - checkArgument(aspectRatio > 0, "aspect ratio " + aspectRatio + " must be positive"); - checkArgument( - layout == LAYOUT_SCALE_TO_FIT - || layout == LAYOUT_SCALE_TO_FIT_WITH_CROP - || layout == LAYOUT_STRETCH_TO_FIT, - "invalid layout " + layout); - this.aspectRatio = aspectRatio; - this.layout = layout; - return this; - } + /** + * Creates a new {@link Presentation} instance. + * + *

    The output frame will have the given height. Width will scale to preserve the input aspect + * ratio. + * + * @param height The height of the output frame, in pixels. + */ + public static Presentation createForHeight(int height) { + return new Presentation( + /* width= */ C.LENGTH_UNSET, height, ASPECT_RATIO_UNSET, LAYOUT_SCALE_TO_FIT); + } - public Presentation build() { - return new Presentation(outputHeight, aspectRatio, layout); - } + /** + * Creates a new {@link Presentation} instance. + * + *

    The output frame will have the given width and height, given a {@link Layout}. + * + *

    Width and height must be positive integers representing the output frame's width and height. + * + * @param width The width of the output frame, in pixels. + * @param height The height of the output frame, in pixels. + * @param layout The layout of the output frame. + */ + public static Presentation createForWidthAndHeight(int width, int height, @Layout int layout) { + checkArgument(width > 0, "width " + width + " must be positive"); + checkArgument(height > 0, "height " + height + " must be positive"); + checkLayout(layout); + return new Presentation(width, height, ASPECT_RATIO_UNSET, layout); } + private final int requestedWidthPixels; private final int requestedHeightPixels; - private final float requestedAspectRatio; + private float requestedAspectRatio; private final @Layout int layout; private float outputWidth; private float outputHeight; private @MonotonicNonNull Matrix transformationMatrix; - /** Creates a new instance. */ - private Presentation(int requestedHeightPixels, float requestedAspectRatio, @Layout int layout) { - this.requestedHeightPixels = requestedHeightPixels; - this.requestedAspectRatio = requestedAspectRatio; + private Presentation(int width, int height, float aspectRatio, @Layout int layout) { + checkArgument( + (aspectRatio == C.LENGTH_UNSET) || (width == C.LENGTH_UNSET), + "width and aspect ratio should not both be set"); + + this.requestedWidthPixels = width; + this.requestedHeightPixels = height; + this.requestedAspectRatio = aspectRatio; this.layout = layout; outputWidth = C.LENGTH_UNSET; @@ -191,13 +189,21 @@ public Size configure(int inputWidth, int inputHeight) { outputWidth = inputWidth; outputHeight = inputHeight; + if ((requestedWidthPixels != C.LENGTH_UNSET) && (requestedHeightPixels != C.LENGTH_UNSET)) { + requestedAspectRatio = (float) requestedWidthPixels / requestedHeightPixels; + } + if (requestedAspectRatio != C.LENGTH_UNSET) { applyAspectRatio(); } - // Scale width and height to desired requestedHeightPixels, preserving aspect ratio. - if (requestedHeightPixels != C.LENGTH_UNSET && requestedHeightPixels != outputHeight) { - outputWidth = requestedHeightPixels * outputWidth / outputHeight; + // Scale output width and height to requested values. + if (requestedHeightPixels != C.LENGTH_UNSET) { + if (requestedWidthPixels != C.LENGTH_UNSET) { + outputWidth = requestedWidthPixels; + } else { + outputWidth = requestedHeightPixels * outputWidth / outputHeight; + } outputHeight = requestedHeightPixels; } return new Size(Math.round(outputWidth), Math.round(outputHeight)); diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java index 6c05da6c51..2a7a9aa37c 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java @@ -88,8 +88,7 @@ public VideoTranscodingSamplePipeline( .build()); } if (transformationRequest.outputHeight != C.LENGTH_UNSET) { - effectsListBuilder.add( - new Presentation.Builder().setResolution(transformationRequest.outputHeight).build()); + effectsListBuilder.add(Presentation.createForHeight(transformationRequest.outputHeight)); } AtomicReference encoderInitializationException = diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/PresentationTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/PresentationTest.java index 60f857c059..6631ab3cef 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/PresentationTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/PresentationTest.java @@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat; import android.util.Size; +import androidx.media3.common.C; import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; @@ -33,7 +34,7 @@ public final class PresentationTest { public void configure_noEdits_leavesFramesUnchanged() { int inputWidth = 200; int inputHeight = 150; - Presentation presentation = new Presentation.Builder().build(); + Presentation presentation = Presentation.createForHeight(C.LENGTH_UNSET); Size outputSize = presentation.configure(inputWidth, inputHeight); @@ -42,11 +43,11 @@ public void configure_noEdits_leavesFramesUnchanged() { } @Test - public void configure_setResolution_changesDimensions() { + public void configure_createForHeight_changesDimensions() { int inputWidth = 200; int inputHeight = 150; int requestedHeight = 300; - Presentation presentation = new Presentation.Builder().setResolution(requestedHeight).build(); + Presentation presentation = Presentation.createForHeight(requestedHeight); Size outputSize = presentation.configure(inputWidth, inputHeight); @@ -55,14 +56,12 @@ public void configure_setResolution_changesDimensions() { } @Test - public void configure_setAspectRatio_changesDimensions() { + public void configure_createForAspectRatio_changesDimensions() { int inputWidth = 300; int inputHeight = 200; float aspectRatio = 2f; Presentation presentation = - new Presentation.Builder() - .setAspectRatio(aspectRatio, Presentation.LAYOUT_SCALE_TO_FIT) - .build(); + Presentation.createForAspectRatio(aspectRatio, Presentation.LAYOUT_SCALE_TO_FIT); Size outputSize = presentation.configure(inputWidth, inputHeight); @@ -71,20 +70,18 @@ public void configure_setAspectRatio_changesDimensions() { } @Test - public void configure_setAspectRatioAndResolution_changesDimensions() { + public void configure_createForWidthAndHeight_changesDimensions() { int inputWidth = 300; int inputHeight = 200; - float aspectRatio = 2f; - int requestedHeight = 100; + int requestedWidth = 100; + int requestedHeight = 300; Presentation presentation = - new Presentation.Builder() - .setAspectRatio(aspectRatio, Presentation.LAYOUT_SCALE_TO_FIT) - .setResolution(requestedHeight) - .build(); + Presentation.createForWidthAndHeight( + requestedWidth, requestedHeight, Presentation.LAYOUT_SCALE_TO_FIT); Size outputSize = presentation.configure(inputWidth, inputHeight); - assertThat(outputSize.getWidth()).isEqualTo(Math.round(aspectRatio * requestedHeight)); + assertThat(outputSize.getWidth()).isEqualTo(requestedWidth); assertThat(outputSize.getHeight()).isEqualTo(requestedHeight); } } From 6dc85dc241dca8f0783d3ffbb3448840b0e75b60 Mon Sep 17 00:00:00 2001 From: olly Date: Mon, 20 Jun 2022 16:46:15 +0100 Subject: [PATCH 33/73] Fix parsing H265 short term reference picture sets Issue: google/ExoPlayer#10316 PiperOrigin-RevId: 456084302 --- RELEASENOTES.md | 2 + .../media3/extractor/NalUnitUtil.java | 98 ++++++++++++++++--- .../media3/extractor/NalUnitUtilTest.java | 26 +++++ 3 files changed, 110 insertions(+), 16 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 3fca7aed2f..3672fcb9fd 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -5,6 +5,8 @@ * Extractors: * Add support for AVI ([#2092](https://github.com/google/ExoPlayer/issues/2092)). + * Fix parsing of H265 short term reference picture sets + ([#10316](https://github.com/google/ExoPlayer/issues/10316)). * RTSP: * Add RTP reader for H263 ([#63](https://github.com/androidx/media/pull/63)). diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/NalUnitUtil.java b/libraries/extractor/src/main/java/androidx/media3/extractor/NalUnitUtil.java index c61d7eaba5..2a401cbbae 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/NalUnitUtil.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/NalUnitUtil.java @@ -18,6 +18,7 @@ import static java.lang.Math.min; import androidx.annotation.Nullable; +import androidx.media3.common.C; import androidx.media3.common.MimeTypes; import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Log; @@ -786,40 +787,105 @@ private static void skipH265ScalingList(ParsableNalUnitBitArray bitArray) { } } + /** + * Skips any short term reference picture sets contained in a SPS. + * + *

    Note: The st_ref_pic_set parsing in this method is simplified for the case where they're + * contained in a SPS, and would need generalizing for use elsewhere. + */ private static void skipShortTermReferencePictureSets(ParsableNalUnitBitArray bitArray) { int numShortTermRefPicSets = bitArray.readUnsignedExpGolombCodedInt(); - boolean interRefPicSetPredictionFlag = false; - int numNegativePics; - int numPositivePics; - // As this method applies in a SPS, the only element of NumDeltaPocs accessed is the previous - // one, so we just keep track of that rather than storing the whole array. - // RefRpsIdx = stRpsIdx - (delta_idx_minus1 + 1) and delta_idx_minus1 is always zero in SPS. - int previousNumDeltaPocs = 0; + // As this method applies in a SPS, each short term reference picture set only accesses data + // from the previous one. This is because RefRpsIdx = stRpsIdx - (delta_idx_minus1 + 1), and + // delta_idx_minus1 is always zero in a SPS. Hence we just keep track of variables from the + // previous one as we iterate. + int previousNumNegativePics = C.INDEX_UNSET; + int previousNumPositivePics = C.INDEX_UNSET; + int[] previousDeltaPocS0 = new int[0]; + int[] previousDeltaPocS1 = new int[0]; for (int stRpsIdx = 0; stRpsIdx < numShortTermRefPicSets; stRpsIdx++) { - if (stRpsIdx != 0) { - interRefPicSetPredictionFlag = bitArray.readBit(); - } + int numNegativePics; + int numPositivePics; + int[] deltaPocS0; + int[] deltaPocS1; + + boolean interRefPicSetPredictionFlag = stRpsIdx != 0 && bitArray.readBit(); if (interRefPicSetPredictionFlag) { - bitArray.skipBit(); // delta_rps_sign - bitArray.readUnsignedExpGolombCodedInt(); // abs_delta_rps_minus1 + int previousNumDeltaPocs = previousNumNegativePics + previousNumPositivePics; + + int deltaRpsSign = bitArray.readBit() ? 1 : 0; + int absDeltaRps = bitArray.readUnsignedExpGolombCodedInt() + 1; + int deltaRps = (1 - 2 * deltaRpsSign) * absDeltaRps; + + boolean[] useDeltaFlags = new boolean[previousNumDeltaPocs + 1]; for (int j = 0; j <= previousNumDeltaPocs; j++) { if (!bitArray.readBit()) { // used_by_curr_pic_flag[j] - bitArray.skipBit(); // use_delta_flag[j] + useDeltaFlags[j] = bitArray.readBit(); + } else { + // When use_delta_flag[j] is not present, its value is 1. + useDeltaFlags[j] = true; + } + } + + // Derive numNegativePics, numPositivePics, deltaPocS0 and deltaPocS1 as per Rec. ITU-T + // H.265 v6 (06/2019) Section 7.4.8 + int i = 0; + deltaPocS0 = new int[previousNumDeltaPocs + 1]; + deltaPocS1 = new int[previousNumDeltaPocs + 1]; + for (int j = previousNumPositivePics - 1; j >= 0; j--) { + int dPoc = previousDeltaPocS1[j] + deltaRps; + if (dPoc < 0 && useDeltaFlags[previousNumNegativePics + j]) { + deltaPocS0[i++] = dPoc; + } + } + if (deltaRps < 0 && useDeltaFlags[previousNumDeltaPocs]) { + deltaPocS0[i++] = deltaRps; + } + for (int j = 0; j < previousNumNegativePics; j++) { + int dPoc = previousDeltaPocS0[j] + deltaRps; + if (dPoc < 0 && useDeltaFlags[j]) { + deltaPocS0[i++] = dPoc; + } + } + numNegativePics = i; + deltaPocS0 = Arrays.copyOf(deltaPocS0, numNegativePics); + + i = 0; + for (int j = previousNumNegativePics - 1; j >= 0; j--) { + int dPoc = previousDeltaPocS0[j] + deltaRps; + if (dPoc > 0 && useDeltaFlags[j]) { + deltaPocS1[i++] = dPoc; + } + } + if (deltaRps > 0 && useDeltaFlags[previousNumDeltaPocs]) { + deltaPocS1[i++] = deltaRps; + } + for (int j = 0; j < previousNumPositivePics; j++) { + int dPoc = previousDeltaPocS1[j] + deltaRps; + if (dPoc > 0 && useDeltaFlags[previousNumNegativePics + j]) { + deltaPocS1[i++] = dPoc; } } + numPositivePics = i; + deltaPocS1 = Arrays.copyOf(deltaPocS1, numPositivePics); } else { numNegativePics = bitArray.readUnsignedExpGolombCodedInt(); numPositivePics = bitArray.readUnsignedExpGolombCodedInt(); - previousNumDeltaPocs = numNegativePics + numPositivePics; + deltaPocS0 = new int[numNegativePics]; for (int i = 0; i < numNegativePics; i++) { - bitArray.readUnsignedExpGolombCodedInt(); // delta_poc_s0_minus1[i] + deltaPocS0[i] = bitArray.readUnsignedExpGolombCodedInt() + 1; bitArray.skipBit(); // used_by_curr_pic_s0_flag[i] } + deltaPocS1 = new int[numPositivePics]; for (int i = 0; i < numPositivePics; i++) { - bitArray.readUnsignedExpGolombCodedInt(); // delta_poc_s1_minus1[i] + deltaPocS1[i] = bitArray.readUnsignedExpGolombCodedInt() + 1; bitArray.skipBit(); // used_by_curr_pic_s1_flag[i] } } + previousNumNegativePics = numNegativePics; + previousNumPositivePics = numPositivePics; + previousDeltaPocS0 = deltaPocS0; + previousDeltaPocS1 = deltaPocS1; } } diff --git a/libraries/extractor/src/test/java/androidx/media3/extractor/NalUnitUtilTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/NalUnitUtilTest.java index 01d7fe15f9..59dd8543db 100644 --- a/libraries/extractor/src/test/java/androidx/media3/extractor/NalUnitUtilTest.java +++ b/libraries/extractor/src/test/java/androidx/media3/extractor/NalUnitUtilTest.java @@ -170,6 +170,32 @@ public void discardToSps() { assertDiscardToSpsMatchesExpected("FF00000001660000000167FF", "0000000167FF"); } + /** Regression test for https://github.com/google/ExoPlayer/issues/10316. */ + @Test + public void parseH265SpsNalUnitPayload_exoghi_10316() { + byte[] spsNalUnitPayload = + new byte[] { + 1, 2, 32, 0, 0, 3, 0, -112, 0, 0, 3, 0, 0, 3, 0, -106, -96, 1, -32, 32, 2, 28, 77, -98, + 87, -110, 66, -111, -123, 22, 74, -86, -53, -101, -98, -68, -28, 9, 119, -21, -103, 120, + -16, 22, -95, 34, 1, 54, -62, 0, 0, 7, -46, 0, 0, -69, -127, -12, 85, -17, 126, 0, -29, + -128, 28, 120, 1, -57, 0, 56, -15 + }; + + NalUnitUtil.H265SpsData spsData = + NalUnitUtil.parseH265SpsNalUnitPayload(spsNalUnitPayload, 0, spsNalUnitPayload.length); + + assertThat(spsData.constraintBytes).isEqualTo(new int[] {144, 0, 0, 0, 0, 0}); + assertThat(spsData.generalLevelIdc).isEqualTo(150); + assertThat(spsData.generalProfileCompatibilityFlags).isEqualTo(4); + assertThat(spsData.generalProfileIdc).isEqualTo(2); + assertThat(spsData.generalProfileSpace).isEqualTo(0); + assertThat(spsData.generalTierFlag).isFalse(); + assertThat(spsData.height).isEqualTo(2160); + assertThat(spsData.pixelWidthHeightRatio).isEqualTo(1); + assertThat(spsData.seqParameterSetId).isEqualTo(0); + assertThat(spsData.width).isEqualTo(3840); + } + private static byte[] buildTestData() { byte[] data = new byte[20]; for (int i = 0; i < data.length; i++) { From a7649b639cef242f70cf832f5dbf56514b7e8c4b Mon Sep 17 00:00:00 2001 From: tonihei Date: Tue, 21 Jun 2022 15:58:04 +0100 Subject: [PATCH 34/73] Clear pending doSomeWork messages when sleeping for offload The offload sleeping stops as soon as a new DO_SOME_WORK message is handled (because this indicates an expected change in rendering and we want to stop sleeping until we know it's safe to do so). Every exit path from doSomeWork needs to clear other pending DO_SOME_WORK messages as these requests have already been handled by the current method invocation. This currently doesn't happen from the offload sleeping return path and a previously queued DO_SOME_WORK message can immediately wake up the rendering loop again. Fix this by moving the message removal to the beginning of the doSomeWork method (as it prevents forgetting it in one of the exit paths later). PiperOrigin-RevId: 456259715 --- .../androidx/media3/exoplayer/ExoPlayerImplInternal.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java index 6eba41d01e..0b37727ecf 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java @@ -960,12 +960,14 @@ private void notifyTrackSelectionRebuffer() { private void doSomeWork() throws ExoPlaybackException, IOException { long operationStartTimeMs = clock.uptimeMillis(); + // Remove other pending DO_SOME_WORK requests that are handled by this invocation. + handler.removeMessages(MSG_DO_SOME_WORK); + updatePeriods(); if (playbackInfo.playbackState == Player.STATE_IDLE || playbackInfo.playbackState == Player.STATE_ENDED) { - // Remove all messages. Prepare (in case of IDLE) or seek (in case of ENDED) will resume. - handler.removeMessages(MSG_DO_SOME_WORK); + // Nothing to do. Prepare (in case of IDLE) or seek (in case of ENDED) will resume. return; } @@ -1088,8 +1090,6 @@ && isLoadingPossible()) { sleepingForOffload = !maybeScheduleWakeup(operationStartTimeMs, ACTIVE_INTERVAL_MS); } else if (enabledRendererCount != 0 && playbackInfo.playbackState != Player.STATE_ENDED) { scheduleNextWork(operationStartTimeMs, IDLE_INTERVAL_MS); - } else { - handler.removeMessages(MSG_DO_SOME_WORK); } if (playbackInfo.sleepingForOffload != sleepingForOffload) { playbackInfo = playbackInfo.copyWithSleepingForOffload(sleepingForOffload); @@ -1125,7 +1125,6 @@ private boolean shouldUseLivePlaybackSpeedControl( } private void scheduleNextWork(long thisOperationStartTimeMs, long intervalMs) { - handler.removeMessages(MSG_DO_SOME_WORK); handler.sendEmptyMessageAtTime(MSG_DO_SOME_WORK, thisOperationStartTimeMs + intervalMs); } From 555ab97e34d6586d38a9979bc0595a4818b7ecb8 Mon Sep 17 00:00:00 2001 From: hschlueter Date: Wed, 22 Jun 2022 12:03:41 +0100 Subject: [PATCH 35/73] Support chaining async GlTextureProcessors in FrameProcessorChain. After this change, FrameProcessorChain chains any GlTextureProcessors instead of only SingleFrameGlTextureProcessors. The GlTextureProcessors are chained in a bidirectional manner using ChainingGlTextureProcessorListener to feed input and output related events forward and release events backwards. PiperOrigin-RevId: 456478414 --- .../demo/transformer/TransformerActivity.java | 21 + ...lMatrixTransformationProcessorWrapper.java | 342 +++++++++++ .../transformer/FrameProcessorChain.java | 553 +++++++----------- .../SingleFrameGlTextureProcessor.java | 10 + .../VideoTranscodingSamplePipeline.java | 23 +- .../transformer/VideoEncoderWrapperTest.java | 3 +- 6 files changed, 582 insertions(+), 370 deletions(-) create mode 100644 libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java diff --git a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java index 57370ff761..2c0b38fbf9 100644 --- a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java +++ b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java @@ -17,6 +17,7 @@ import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static androidx.media3.common.util.Assertions.checkNotNull; +import static androidx.media3.common.util.Assertions.checkState; import android.app.Activity; import android.content.Context; @@ -420,9 +421,28 @@ private void showToast(@StringRes int messageResource) { private final class DemoDebugViewProvider implements Transformer.DebugViewProvider { + private @MonotonicNonNull SurfaceView surfaceView; + private int width; + private int height; + + public DemoDebugViewProvider() { + width = C.LENGTH_UNSET; + height = C.LENGTH_UNSET; + } + @Nullable @Override public SurfaceView getDebugPreviewSurfaceView(int width, int height) { + checkState( + surfaceView == null || (this.width == width && this.height == height), + "Transformer should not change the output size mid-transformation."); + if (surfaceView != null) { + return surfaceView; + } + + this.width = width; + this.height = height; + // Update the UI on the main thread and wait for the output surface to be available. CountDownLatch surfaceCreatedCountDownLatch = new CountDownLatch(1); SurfaceView surfaceView = new SurfaceView(/* context= */ TransformerActivity.this); @@ -459,6 +479,7 @@ public void surfaceDestroyed(SurfaceHolder surfaceHolder) { Thread.currentThread().interrupt(); return null; } + this.surfaceView = surfaceView; return surfaceView; } } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java new file mode 100644 index 0000000000..e582af3309 --- /dev/null +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java @@ -0,0 +1,342 @@ +/* + * Copyright 2022 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 androidx.media3.transformer; + +import static androidx.media3.common.util.Assertions.checkState; + +import android.content.Context; +import android.opengl.EGL14; +import android.opengl.EGLContext; +import android.opengl.EGLDisplay; +import android.opengl.EGLExt; +import android.opengl.EGLSurface; +import android.util.Size; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import androidx.annotation.GuardedBy; +import androidx.annotation.Nullable; +import androidx.annotation.WorkerThread; +import androidx.media3.common.C; +import androidx.media3.common.util.GlUtil; +import androidx.media3.common.util.Log; +import com.google.common.collect.ImmutableList; +import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + +/** + * Wrapper around a {@link GlTextureProcessor} that writes to the provided output surface and + * optional debug surface view. + * + *

    The wrapped {@link GlTextureProcessor} applies the {@link GlMatrixTransformation} instances + * passed to the constructor, followed by any transformations needed to convert the frames to the + * dimensions specified by the provided {@link SurfaceInfo}. + * + *

    This wrapper is used for the final {@link GlTextureProcessor} instance in the chain of {@link + * GlTextureProcessor} instances used by {@link FrameProcessorChain}. + */ +/* package */ final class FinalMatrixTransformationProcessorWrapper implements GlTextureProcessor { + + private static final String TAG = "FinalProcessorWrapper"; + + private final Context context; + private final ImmutableList matrixTransformations; + private final EGLDisplay eglDisplay; + private final EGLContext eglContext; + private final SurfaceInfo.Provider outputSurfaceProvider; + private final long streamOffsetUs; + private final Transformer.DebugViewProvider debugViewProvider; + private final FrameProcessorChain.Listener frameProcessorChainListener; + private final boolean enableExperimentalHdrEditing; + + private int inputWidth; + private int inputHeight; + @Nullable private MatrixTransformationProcessor matrixTransformationProcessor; + @Nullable private SurfaceInfo outputSurfaceInfo; + @Nullable private EGLSurface outputEglSurface; + @Nullable private SurfaceViewWrapper debugSurfaceViewWrapper; + private @MonotonicNonNull Listener listener; + + public FinalMatrixTransformationProcessorWrapper( + Context context, + EGLDisplay eglDisplay, + EGLContext eglContext, + ImmutableList matrixTransformations, + SurfaceInfo.Provider outputSurfaceProvider, + long streamOffsetUs, + FrameProcessorChain.Listener listener, + Transformer.DebugViewProvider debugViewProvider, + boolean enableExperimentalHdrEditing) { + this.context = context; + this.matrixTransformations = matrixTransformations; + this.eglDisplay = eglDisplay; + this.eglContext = eglContext; + this.outputSurfaceProvider = outputSurfaceProvider; + this.streamOffsetUs = streamOffsetUs; + this.debugViewProvider = debugViewProvider; + this.frameProcessorChainListener = listener; + this.enableExperimentalHdrEditing = enableExperimentalHdrEditing; + } + + /** + * {@inheritDoc} + * + *

    The {@code FinalMatrixTransformationProcessorWrapper} will only call {@link + * Listener#onInputFrameProcessed(TextureInfo)}. Other events are handled via the {@link + * FrameProcessorChain.Listener} passed to the constructor. + */ + @Override + public void setListener(Listener listener) { + this.listener = listener; + } + + @Override + public boolean maybeQueueInputFrame(TextureInfo inputTexture, long presentationTimeUs) { + try { + if (!ensureConfigured(inputTexture.width, inputTexture.height)) { + return false; + } + + EGLSurface outputEglSurface = this.outputEglSurface; + SurfaceInfo outputSurfaceInfo = this.outputSurfaceInfo; + MatrixTransformationProcessor matrixTransformationProcessor = + this.matrixTransformationProcessor; + + GlUtil.focusEglSurface( + eglDisplay, + eglContext, + outputEglSurface, + outputSurfaceInfo.width, + outputSurfaceInfo.height); + GlUtil.clearOutputFrame(); + matrixTransformationProcessor.drawFrame(inputTexture.texId, presentationTimeUs); + EGLExt.eglPresentationTimeANDROID( + eglDisplay, + outputEglSurface, + /* presentationTimeNs= */ (presentationTimeUs + streamOffsetUs) * 1000); + EGL14.eglSwapBuffers(eglDisplay, outputEglSurface); + } catch (FrameProcessingException | GlUtil.GlException e) { + frameProcessorChainListener.onFrameProcessingError( + FrameProcessingException.from(e, presentationTimeUs)); + } + + if (debugSurfaceViewWrapper != null && matrixTransformationProcessor != null) { + MatrixTransformationProcessor matrixTransformationProcessor = + this.matrixTransformationProcessor; + try { + debugSurfaceViewWrapper.maybeRenderToSurfaceView( + () -> { + GlUtil.clearOutputFrame(); + matrixTransformationProcessor.drawFrame(inputTexture.texId, presentationTimeUs); + }); + } catch (FrameProcessingException | GlUtil.GlException e) { + Log.d(TAG, "Error rendering to debug preview", e); + } + } + if (listener != null) { + listener.onInputFrameProcessed(inputTexture); + } + return true; + } + + @EnsuresNonNullIf( + expression = {"outputSurfaceInfo", "outputEglSurface", "matrixTransformationProcessor"}, + result = true) + private boolean ensureConfigured(int inputWidth, int inputHeight) + throws FrameProcessingException, GlUtil.GlException { + if (inputWidth == this.inputWidth + && inputHeight == this.inputHeight + && outputSurfaceInfo != null + && outputEglSurface != null + && matrixTransformationProcessor != null) { + return true; + } + + this.inputWidth = inputWidth; + this.inputHeight = inputHeight; + Size requestedOutputSize = + MatrixUtils.configureAndGetOutputSize(inputWidth, inputHeight, matrixTransformations); + @Nullable + SurfaceInfo outputSurfaceInfo = + outputSurfaceProvider.getSurfaceInfo( + requestedOutputSize.getWidth(), requestedOutputSize.getHeight()); + if (outputSurfaceInfo == null) { + if (matrixTransformationProcessor != null) { + matrixTransformationProcessor.release(); + matrixTransformationProcessor = null; + } + outputEglSurface = null; + return false; + } + if (outputSurfaceInfo == this.outputSurfaceInfo + && outputEglSurface != null + && matrixTransformationProcessor != null) { + return true; + } + + EGLSurface outputEglSurface; + if (enableExperimentalHdrEditing) { + // TODO(b/227624622): Don't assume BT.2020 PQ input/output. + outputEglSurface = GlUtil.getEglSurfaceBt2020Pq(eglDisplay, outputSurfaceInfo.surface); + } else { + outputEglSurface = GlUtil.getEglSurface(eglDisplay, outputSurfaceInfo.surface); + } + + @Nullable + SurfaceView debugSurfaceView = + debugViewProvider.getDebugPreviewSurfaceView( + outputSurfaceInfo.width, outputSurfaceInfo.height); + if (debugSurfaceView != null) { + debugSurfaceViewWrapper = + new SurfaceViewWrapper( + eglDisplay, eglContext, enableExperimentalHdrEditing, debugSurfaceView); + } + + matrixTransformationProcessor = + createMatrixTransformationProcessorForOutputSurface(requestedOutputSize, outputSurfaceInfo); + + this.outputSurfaceInfo = outputSurfaceInfo; + this.outputEglSurface = outputEglSurface; + return true; + } + + private MatrixTransformationProcessor createMatrixTransformationProcessorForOutputSurface( + Size requestedOutputSize, SurfaceInfo outputSurfaceInfo) throws FrameProcessingException { + ImmutableList.Builder matrixTransformationListBuilder = + new ImmutableList.Builder().addAll(matrixTransformations); + if (outputSurfaceInfo.orientationDegrees != 0) { + matrixTransformationListBuilder.add( + new ScaleToFitTransformation.Builder() + .setRotationDegrees(outputSurfaceInfo.orientationDegrees) + .build()); + } + if (outputSurfaceInfo.width != requestedOutputSize.getWidth() + || outputSurfaceInfo.height != requestedOutputSize.getHeight()) { + matrixTransformationListBuilder.add( + Presentation.createForWidthAndHeight( + outputSurfaceInfo.width, outputSurfaceInfo.height, Presentation.LAYOUT_SCALE_TO_FIT)); + } + + MatrixTransformationProcessor matrixTransformationProcessor = + new MatrixTransformationProcessor(context, matrixTransformationListBuilder.build()); + Size outputSize = matrixTransformationProcessor.configure(inputWidth, inputHeight); + checkState(outputSize.getWidth() == outputSurfaceInfo.width); + checkState(outputSize.getHeight() == outputSurfaceInfo.height); + return matrixTransformationProcessor; + } + + @Override + public void releaseOutputFrame(TextureInfo outputTexture) { + throw new UnsupportedOperationException( + "The final texture processor writes to a surface so there is no texture to release"); + } + + @Override + public void signalEndOfInputStream() { + frameProcessorChainListener.onFrameProcessingEnded(); + } + + @Override + @WorkerThread + public void release() throws FrameProcessingException { + if (matrixTransformationProcessor != null) { + matrixTransformationProcessor.release(); + } + } + + /** + * Wrapper around a {@link SurfaceView} that keeps track of whether the output surface is valid, + * and makes rendering a no-op if not. + */ + private static final class SurfaceViewWrapper implements SurfaceHolder.Callback { + private final EGLDisplay eglDisplay; + private final EGLContext eglContext; + private final boolean enableExperimentalHdrEditing; + + @GuardedBy("this") + @Nullable + private Surface surface; + + @GuardedBy("this") + @Nullable + private EGLSurface eglSurface; + + private int width; + private int height; + + public SurfaceViewWrapper( + EGLDisplay eglDisplay, + EGLContext eglContext, + boolean enableExperimentalHdrEditing, + SurfaceView surfaceView) { + this.eglDisplay = eglDisplay; + this.eglContext = eglContext; + this.enableExperimentalHdrEditing = enableExperimentalHdrEditing; + surfaceView.getHolder().addCallback(this); + surface = surfaceView.getHolder().getSurface(); + width = surfaceView.getWidth(); + height = surfaceView.getHeight(); + } + + /** + * Focuses the wrapped surface view's surface as an {@link EGLSurface}, renders using {@code + * renderingTask} and swaps buffers, if the view's holder has a valid surface. Does nothing + * otherwise. + */ + @WorkerThread + public synchronized void maybeRenderToSurfaceView(FrameProcessingTask renderingTask) + throws GlUtil.GlException, FrameProcessingException { + if (surface == null) { + return; + } + + if (eglSurface == null) { + if (enableExperimentalHdrEditing) { + eglSurface = GlUtil.getEglSurfaceBt2020Pq(eglDisplay, surface); + } else { + eglSurface = GlUtil.getEglSurface(eglDisplay, surface); + } + } + EGLSurface eglSurface = this.eglSurface; + GlUtil.focusEglSurface(eglDisplay, eglContext, eglSurface, width, height); + renderingTask.run(); + EGL14.eglSwapBuffers(eglDisplay, eglSurface); + } + + @Override + public void surfaceCreated(SurfaceHolder holder) {} + + @Override + public synchronized void surfaceChanged( + SurfaceHolder holder, int format, int width, int height) { + this.width = width; + this.height = height; + Surface newSurface = holder.getSurface(); + if (surface == null || !surface.equals(newSurface)) { + surface = newSurface; + eglSurface = null; + } + } + + @Override + public synchronized void surfaceDestroyed(SurfaceHolder holder) { + surface = null; + eglSurface = null; + width = C.LENGTH_UNSET; + height = C.LENGTH_UNSET; + } + } +} diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java index 8476dadabb..3ebc57741d 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java @@ -17,35 +17,24 @@ import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkState; -import static com.google.common.collect.Iterables.getLast; import android.content.Context; import android.graphics.SurfaceTexture; import android.opengl.EGL14; import android.opengl.EGLContext; import android.opengl.EGLDisplay; -import android.opengl.EGLExt; -import android.opengl.EGLSurface; -import android.util.Size; import android.view.Surface; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import androidx.annotation.GuardedBy; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; import androidx.media3.common.C; import androidx.media3.common.util.GlUtil; -import androidx.media3.common.util.Log; import androidx.media3.common.util.Util; -import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; -import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** * {@code FrameProcessorChain} applies changes to individual video frames. @@ -53,10 +42,10 @@ *

    Input becomes available on its {@linkplain #getInputSurface() input surface} asynchronously * and is processed on a background thread as it becomes available. All input frames should be * {@linkplain #registerInputFrame() registered} before they are rendered to the input surface. - * {@link #getPendingFrameCount()} can be used to check whether there are frames that have not been - * fully processed yet. Output is written to the provided {@linkplain #create(Context, Listener, - * float, int, int, long, List, SurfaceInfo.Provider, Transformer.DebugViewProvider, boolean) output - * surface}. + * {@link #getPendingInputFrameCount()} can be used to check whether there are frames that have not + * been fully processed yet. Output is written to the provided {@linkplain #create(Context, + * Listener, float, int, int, long, List, SurfaceInfo.Provider, Transformer.DebugViewProvider, + * boolean) output surface}. */ // TODO(b/227625423): Factor out FrameProcessor interface and rename this class to GlFrameProcessor. /* package */ final class FrameProcessorChain { @@ -93,17 +82,13 @@ public interface Listener { * Surface}. * @param debugViewProvider A {@link Transformer.DebugViewProvider}. * @param enableExperimentalHdrEditing Whether to attempt to process the input as an HDR signal. - * @return A new instance or {@code null}, if no output surface was provided. + * @return A new instance. * @throws FrameProcessingException If reading shader files fails, or an OpenGL error occurs while * creating and configuring the OpenGL components. */ - // TODO(b/227625423): Remove @Nullable here and allow the output surface to be @Nullable until - // the output surface is requested when the output size becomes available asynchronously - // via the final GlTextureProcessor. - @Nullable public static FrameProcessorChain create( Context context, - Listener listener, + FrameProcessorChain.Listener listener, float pixelWidthHeightRatio, int inputWidth, int inputHeight, @@ -118,25 +103,24 @@ public static FrameProcessorChain create( ExecutorService singleThreadExecutorService = Util.newSingleThreadExecutor(THREAD_NAME); - Future> frameProcessorChainFuture = + Future frameProcessorChainFuture = singleThreadExecutorService.submit( () -> - Optional.fromNullable( - createOpenGlObjectsAndFrameProcessorChain( - context, - listener, - pixelWidthHeightRatio, - inputWidth, - inputHeight, - streamOffsetUs, - effects, - outputSurfaceProvider, - debugViewProvider, - enableExperimentalHdrEditing, - singleThreadExecutorService))); + createOpenGlObjectsAndFrameProcessorChain( + context, + listener, + pixelWidthHeightRatio, + inputWidth, + inputHeight, + streamOffsetUs, + effects, + outputSurfaceProvider, + debugViewProvider, + enableExperimentalHdrEditing, + singleThreadExecutorService)); try { - return frameProcessorChainFuture.get().orNull(); + return frameProcessorChainFuture.get(); } catch (ExecutionException e) { throw new FrameProcessingException(e); } catch (InterruptedException e) { @@ -146,18 +130,17 @@ public static FrameProcessorChain create( } /** - * Creates the OpenGL context, surfaces, textures, and framebuffers, initializes the {@link - * SingleFrameGlTextureProcessor SingleFrameGlTextureProcessors} corresponding to the {@link - * GlEffect GlEffects}, and returns a new {@code FrameProcessorChain}. + * Creates the OpenGL context, surfaces, textures, and framebuffers, initializes {@link + * GlTextureProcessor} instances corresponding to the {@link GlEffect} instances, and returns a + * new {@code FrameProcessorChain}. * - *

    This method must be executed using the {@code singleThreadExecutorService}, as all later - * OpenGL commands will be called on that thread. + *

    This method must be executed using the {@code singleThreadExecutorService}, as later OpenGL + * commands will be called on that thread. */ @WorkerThread - @Nullable private static FrameProcessorChain createOpenGlObjectsAndFrameProcessorChain( Context context, - Listener listener, + FrameProcessorChain.Listener listener, float pixelWidthHeightRatio, int inputWidth, int inputHeight, @@ -188,132 +171,151 @@ private static FrameProcessorChain createOpenGlObjectsAndFrameProcessorChain( ImmutableList.Builder matrixTransformationListBuilder = new ImmutableList.Builder<>(); - // Scale to expand the frame to apply the pixelWidthHeightRatio. - if (pixelWidthHeightRatio > 1f) { - matrixTransformationListBuilder.add( - new ScaleToFitTransformation.Builder() - .setScale(/* scaleX= */ pixelWidthHeightRatio, /* scaleY= */ 1f) - .build()); - } else if (pixelWidthHeightRatio < 1f) { + if (pixelWidthHeightRatio != 1f) { matrixTransformationListBuilder.add( - new ScaleToFitTransformation.Builder() - .setScale(/* scaleX= */ 1f, /* scaleY= */ 1f / pixelWidthHeightRatio) - .build()); + createPixelWidthHeightRatioTransformation(pixelWidthHeightRatio)); } + ImmutableList textureProcessors = + getGlTextureProcessorsForGlEffects( + context, + effects, + eglDisplay, + eglContext, + matrixTransformationListBuilder, + outputSurfaceProvider, + streamOffsetUs, + listener, + debugViewProvider, + enableExperimentalHdrEditing); + ExternalTextureProcessor externalTextureProcessor = new ExternalTextureProcessor(context, enableExperimentalHdrEditing); - int inputExternalTexId = GlUtil.createExternalTexture(); - Size outputSize = externalTextureProcessor.configure(inputWidth, inputHeight); - ImmutableList.Builder intermediateTextures = new ImmutableList.Builder<>(); - ImmutableList.Builder textureProcessors = - new ImmutableList.Builder().add(externalTextureProcessor); - - // Combine consecutive GlMatrixTransformations into a single SingleFrameGlTextureProcessor and - // convert all other GlEffects to SingleFrameGlTextureProcessors. + FrameProcessingTaskExecutor frameProcessingTaskExecutor = + new FrameProcessingTaskExecutor(singleThreadExecutorService, listener); + chainTextureProcessorsWithListeners( + externalTextureProcessor, textureProcessors, frameProcessingTaskExecutor, listener); + + return new FrameProcessorChain( + eglDisplay, + eglContext, + frameProcessingTaskExecutor, + streamOffsetUs, + /* inputExternalTexture= */ new TextureInfo( + GlUtil.createExternalTexture(), /* fboId= */ C.INDEX_UNSET, inputWidth, inputHeight), + externalTextureProcessor, + textureProcessors); + } + + /** + * Returns a new {@link GlMatrixTransformation} to expand or shrink the frame based on the {@code + * pixelWidthHeightRatio}. + * + *

    If {@code pixelWidthHeightRatio} is 1, this method returns an identity transformation that + * can be ignored. + */ + private static GlMatrixTransformation createPixelWidthHeightRatioTransformation( + float pixelWidthHeightRatio) { + if (pixelWidthHeightRatio > 1f) { + return new ScaleToFitTransformation.Builder() + .setScale(/* scaleX= */ pixelWidthHeightRatio, /* scaleY= */ 1f) + .build(); + } else { + return new ScaleToFitTransformation.Builder() + .setScale(/* scaleX= */ 1f, /* scaleY= */ 1f / pixelWidthHeightRatio) + .build(); + } + } + + /** + * Combines consecutive {@link GlMatrixTransformation} instances into a single {@link + * MatrixTransformationProcessor} and converts all other {@link GlEffect} instances to separate + * {@link GlTextureProcessor} instances. + * + *

    The final {@link GlTextureProcessor} is wrapped in a {@link + * FinalMatrixTransformationProcessorWrapper} so that it can write directly to the {@linkplain + * SurfaceInfo.Provider provided output surface}. + */ + private static ImmutableList getGlTextureProcessorsForGlEffects( + Context context, + List effects, + EGLDisplay eglDisplay, + EGLContext eglContext, + ImmutableList.Builder matrixTransformationListBuilder, + SurfaceInfo.Provider outputSurfaceProvider, + long streamOffsetUs, + FrameProcessorChain.Listener listener, + Transformer.DebugViewProvider debugViewProvider, + boolean enableExperimentalHdrEditing) + throws FrameProcessingException { + ImmutableList.Builder textureProcessorListBuilder = + new ImmutableList.Builder<>(); for (int i = 0; i < effects.size(); i++) { GlEffect effect = effects.get(i); if (effect instanceof GlMatrixTransformation) { matrixTransformationListBuilder.add((GlMatrixTransformation) effect); continue; } - ImmutableList matrixTransformations = matrixTransformationListBuilder.build(); if (!matrixTransformations.isEmpty()) { - MatrixTransformationProcessor matrixTransformationProcessor = - new MatrixTransformationProcessor(context, matrixTransformations); - intermediateTextures.add(createTexture(outputSize.getWidth(), outputSize.getHeight())); - outputSize = - matrixTransformationProcessor.configure(outputSize.getWidth(), outputSize.getHeight()); - textureProcessors.add(matrixTransformationProcessor); + textureProcessorListBuilder.add( + new MatrixTransformationProcessor(context, matrixTransformations)); matrixTransformationListBuilder = new ImmutableList.Builder<>(); } - intermediateTextures.add(createTexture(outputSize.getWidth(), outputSize.getHeight())); - SingleFrameGlTextureProcessor textureProcessor = effect.toGlTextureProcessor(context); - outputSize = textureProcessor.configure(outputSize.getWidth(), outputSize.getHeight()); - textureProcessors.add(textureProcessor); - } - - // TODO(b/227625423): Request the output surface during processing when the output size becomes - // available asynchronously via the final GlTextureProcessor instead of requesting it here. - // This will also avoid needing to return null here when no surface is provided. - Size requestedOutputSize = - MatrixUtils.configureAndGetOutputSize( - outputSize.getWidth(), outputSize.getHeight(), matrixTransformationListBuilder.build()); - @Nullable - SurfaceInfo outputSurfaceInfo = - outputSurfaceProvider.getSurfaceInfo( - requestedOutputSize.getWidth(), requestedOutputSize.getHeight()); - if (outputSurfaceInfo == null) { - Log.d(TAG, "No output surface provided."); - return null; - } - - if (outputSurfaceInfo.orientationDegrees != 0) { - matrixTransformationListBuilder.add( - new ScaleToFitTransformation.Builder() - .setRotationDegrees(outputSurfaceInfo.orientationDegrees) - .build()); - } - if (outputSurfaceInfo.width != outputSize.getWidth() - || outputSurfaceInfo.height != outputSize.getHeight()) { - matrixTransformationListBuilder.add( - Presentation.createForWidthAndHeight( - outputSurfaceInfo.width, outputSurfaceInfo.height, Presentation.LAYOUT_SCALE_TO_FIT)); - } - - // Convert final list of matrix transformations (including additional transformations for the - // output surface) to a SingleFrameGlTextureProcessors. - ImmutableList matrixTransformations = - matrixTransformationListBuilder.build(); - if (!matrixTransformations.isEmpty()) { - intermediateTextures.add(createTexture(outputSize.getWidth(), outputSize.getHeight())); - MatrixTransformationProcessor matrixTransformationProcessor = - new MatrixTransformationProcessor(context, matrixTransformations); - outputSize = - matrixTransformationProcessor.configure(outputSize.getWidth(), outputSize.getHeight()); - checkState(outputSize.getWidth() == outputSurfaceInfo.width); - checkState(outputSize.getHeight() == outputSurfaceInfo.height); - textureProcessors.add(matrixTransformationProcessor); - } - - EGLSurface outputEglSurface; - if (enableExperimentalHdrEditing) { - // TODO(b/227624622): Don't assume BT.2020 PQ input/output. - outputEglSurface = GlUtil.getEglSurfaceBt2020Pq(eglDisplay, outputSurfaceInfo.surface); - } else { - outputEglSurface = GlUtil.getEglSurface(eglDisplay, outputSurfaceInfo.surface); + textureProcessorListBuilder.add(effect.toGlTextureProcessor(context)); } - return new FrameProcessorChain( - eglDisplay, - eglContext, - singleThreadExecutorService, - inputExternalTexId, - streamOffsetUs, - intermediateTextures.build(), - textureProcessors.build(), - outputSurfaceInfo.width, - outputSurfaceInfo.height, - outputEglSurface, - listener, - debugViewProvider.getDebugPreviewSurfaceView( - outputSurfaceInfo.width, outputSurfaceInfo.height), - enableExperimentalHdrEditing); + textureProcessorListBuilder.add( + new FinalMatrixTransformationProcessorWrapper( + context, + eglDisplay, + eglContext, + matrixTransformationListBuilder.build(), + outputSurfaceProvider, + streamOffsetUs, + listener, + debugViewProvider, + enableExperimentalHdrEditing)); + return textureProcessorListBuilder.build(); } - private static TextureInfo createTexture(int outputWidth, int outputHeight) - throws GlUtil.GlException { - int texId = GlUtil.createTexture(outputWidth, outputHeight); - int fboId = GlUtil.createFboForTexture(texId); - return new TextureInfo(texId, fboId, outputWidth, outputHeight); + /** + * Chains the given {@link GlTextureProcessor} instances using {@link + * ChainingGlTextureProcessorListener} instances. + * + *

    The {@link ExternalTextureProcessor} is the first processor in the chain. + */ + private static void chainTextureProcessorsWithListeners( + ExternalTextureProcessor externalTextureProcessor, + ImmutableList textureProcessors, + FrameProcessingTaskExecutor frameProcessingTaskExecutor, + FrameProcessorChain.Listener listener) { + externalTextureProcessor.setListener( + new ChainingGlTextureProcessorListener( + /* previousGlTextureProcessor= */ null, + textureProcessors.get(0), + frameProcessingTaskExecutor, + listener)); + GlTextureProcessor previousGlTextureProcessor = externalTextureProcessor; + for (int i = 0; i < textureProcessors.size(); i++) { + GlTextureProcessor glTextureProcessor = textureProcessors.get(i); + @Nullable + GlTextureProcessor nextGlTextureProcessor = + i + 1 < textureProcessors.size() ? textureProcessors.get(i + 1) : null; + glTextureProcessor.setListener( + new ChainingGlTextureProcessorListener( + previousGlTextureProcessor, + nextGlTextureProcessor, + frameProcessingTaskExecutor, + listener)); + previousGlTextureProcessor = glTextureProcessor; + } } private static final String TAG = "FrameProcessorChain"; private static final String THREAD_NAME = "Transformer:FrameProcessorChain"; private static final long RELEASE_WAIT_TIME_MS = 100; - private final boolean enableExperimentalHdrEditing; private final EGLDisplay eglDisplay; private final EGLContext eglContext; private final FrameProcessingTaskExecutor frameProcessingTaskExecutor; @@ -322,100 +324,52 @@ private static TextureInfo createTexture(int outputWidth, int outputHeight) * timestamps, in microseconds. */ private final long streamOffsetUs; - /** Number of frames {@linkplain #registerInputFrame() registered} but not fully processed. */ - private final AtomicInteger pendingFrameCount; - /** Wraps the {@link #inputSurfaceTexture}. */ - private final Surface inputSurface; - /** Associated with an OpenGL external texture. */ - private final SurfaceTexture inputSurfaceTexture; - /** Identifier of the OpenGL texture associated with the input {@link SurfaceTexture}. */ - private final int inputExternalTexId; - /** Transformation matrix associated with the {@link #inputSurfaceTexture}. */ - private final float[] textureTransformMatrix; - /** - * Contains an {@link ExternalTextureProcessor} at the 0th index and optionally other {@link - * SingleFrameGlTextureProcessor SingleFrameGlTextureProcessors} at indices >= 1. + * Number of frames {@linkplain #registerInputFrame() registered} but not processed off the {@link + * #inputSurfaceTexture} yet. */ - private final ImmutableList textureProcessors; - - /** - * {@link TextureInfo} instances describing the intermediate textures that receive output from the - * previous {@link SingleFrameGlTextureProcessor}, and provide input for the following {@link - * SingleFrameGlTextureProcessor}. - */ - private final ImmutableList intermediateTextures; - - private final Listener listener; - - /** - * Prevents further frame processing tasks from being scheduled or executed after {@link - * #release()} is called or an exception occurred. - */ - private final AtomicBoolean stopProcessing; + private final AtomicInteger pendingInputFrameCount; + /** Associated with an OpenGL external texture. */ + private final SurfaceTexture inputSurfaceTexture; + /** Wraps the {@link #inputSurfaceTexture}. */ + private final Surface inputSurface; - private final int outputWidth; - private final int outputHeight; - /** - * Wraps the output {@link Surface} that is populated with the output of the final {@link - * SingleFrameGlTextureProcessor} for each frame. - */ - private final EGLSurface outputEglSurface; - /** - * Wraps a debug {@link SurfaceView} that is populated with the output of the final {@link - * SingleFrameGlTextureProcessor} for each frame. - */ - private @MonotonicNonNull SurfaceViewWrapper debugSurfaceViewWrapper; + private final float[] inputSurfaceTextureTransformMatrix; + private final TextureInfo inputExternalTexture; + private final ExternalTextureProcessor inputExternalTextureProcessor; + private final ImmutableList textureProcessors; private boolean inputStreamEnded; - // TODO(b/227625423): accept GlTextureProcessors instead of SingleFrameGlTextureProcessors once - // this interface exists. private FrameProcessorChain( EGLDisplay eglDisplay, EGLContext eglContext, - ExecutorService singleThreadExecutorService, - int inputExternalTexId, + FrameProcessingTaskExecutor frameProcessingTaskExecutor, long streamOffsetUs, - ImmutableList intermediateTextures, - ImmutableList textureProcessors, - int outputWidth, - int outputHeight, - EGLSurface outputEglSurface, - Listener listener, - @Nullable SurfaceView debugSurfaceView, - boolean enableExperimentalHdrEditing) { + TextureInfo inputExternalTexture, + ExternalTextureProcessor inputExternalTextureProcessor, + ImmutableList textureProcessors) { checkState(!textureProcessors.isEmpty()); this.eglDisplay = eglDisplay; this.eglContext = eglContext; - this.inputExternalTexId = inputExternalTexId; + this.frameProcessingTaskExecutor = frameProcessingTaskExecutor; this.streamOffsetUs = streamOffsetUs; - this.intermediateTextures = intermediateTextures; + this.inputExternalTexture = inputExternalTexture; + this.inputExternalTextureProcessor = inputExternalTextureProcessor; this.textureProcessors = textureProcessors; - this.outputWidth = outputWidth; - this.outputHeight = outputHeight; - this.outputEglSurface = outputEglSurface; - this.listener = listener; - this.stopProcessing = new AtomicBoolean(); - this.enableExperimentalHdrEditing = enableExperimentalHdrEditing; - - frameProcessingTaskExecutor = - new FrameProcessingTaskExecutor(singleThreadExecutorService, listener); - pendingFrameCount = new AtomicInteger(); - inputSurfaceTexture = new SurfaceTexture(inputExternalTexId); + + pendingInputFrameCount = new AtomicInteger(); + inputSurfaceTexture = new SurfaceTexture(inputExternalTexture.texId); inputSurface = new Surface(inputSurfaceTexture); - textureTransformMatrix = new float[16]; - if (debugSurfaceView != null) { - debugSurfaceViewWrapper = new SurfaceViewWrapper(debugSurfaceView); - } + inputSurfaceTextureTransformMatrix = new float[16]; } /** Returns the input {@link Surface}. */ public Surface getInputSurface() { // TODO(b/227625423): Allow input surface to be recreated for input size change. inputSurfaceTexture.setOnFrameAvailableListener( - surfaceTexture -> frameProcessingTaskExecutor.submit(this::processFrame)); + surfaceTexture -> frameProcessingTaskExecutor.submit(this::processInputFrame)); return inputSurface; } @@ -428,15 +382,15 @@ public Surface getInputSurface() { */ public void registerInputFrame() { checkState(!inputStreamEnded); - pendingFrameCount.incrementAndGet(); + pendingInputFrameCount.incrementAndGet(); } /** * Returns the number of input frames that have been {@linkplain #registerInputFrame() registered} - * but not completely processed yet. + * but not processed off the {@linkplain #getInputSurface() input surface} yet. */ - public int getPendingFrameCount() { - return pendingFrameCount.get(); + public int getPendingInputFrameCount() { + return pendingInputFrameCount.get(); } /** @@ -447,7 +401,7 @@ public int getPendingFrameCount() { public void signalEndOfInputStream() { checkState(!inputStreamEnded); inputStreamEnded = true; - frameProcessingTaskExecutor.submit(this::signalEndOfOutputStream); + frameProcessingTaskExecutor.submit(this::processEndOfInputStream); } /** @@ -461,7 +415,6 @@ public void signalEndOfInputStream() { *

    This method blocks until all OpenGL resources are released or releasing times out. */ public void release() { - stopProcessing.set(true); try { frameProcessingTaskExecutor.release( /* releaseTask= */ this::releaseTextureProcessorsAndDestroyGlContext, @@ -475,163 +428,61 @@ public void release() { } /** - * Processes an input frame. + * Processes an input frame from the {@linkplain #getInputSurface() external input surface + * texture}. * *

    This method must be called on the {@linkplain #THREAD_NAME background thread}. */ @WorkerThread - private void processFrame() throws FrameProcessingException { + private void processInputFrame() { checkState(Thread.currentThread().getName().equals(THREAD_NAME)); + if (!inputExternalTextureProcessor.acceptsInputFrame()) { + frameProcessingTaskExecutor.submit(this::processInputFrame); // Try again later. + return; + } inputSurfaceTexture.updateTexImage(); long inputFrameTimeNs = inputSurfaceTexture.getTimestamp(); // Correct for the stream offset so processors see original media presentation timestamps. long presentationTimeUs = inputFrameTimeNs / 1000 - streamOffsetUs; - inputSurfaceTexture.getTransformMatrix(textureTransformMatrix); - ((ExternalTextureProcessor) textureProcessors.get(0)) - .setTextureTransformMatrix(textureTransformMatrix); - int inputTexId = inputExternalTexId; - - try { - for (int i = 0; i < textureProcessors.size() - 1; i++) { - if (stopProcessing.get()) { - return; - } - - TextureInfo outputTexture = intermediateTextures.get(i); - GlUtil.focusFramebuffer( - eglDisplay, - eglContext, - outputEglSurface, - outputTexture.fboId, - outputTexture.width, - outputTexture.height); - GlUtil.clearOutputFrame(); - textureProcessors.get(i).drawFrame(inputTexId, presentationTimeUs); - inputTexId = outputTexture.texId; - } - GlUtil.focusEglSurface(eglDisplay, eglContext, outputEglSurface, outputWidth, outputHeight); - GlUtil.clearOutputFrame(); - getLast(textureProcessors).drawFrame(inputTexId, presentationTimeUs); - - EGLExt.eglPresentationTimeANDROID(eglDisplay, outputEglSurface, inputFrameTimeNs); - EGL14.eglSwapBuffers(eglDisplay, outputEglSurface); - } catch (GlUtil.GlException e) { - throw new FrameProcessingException(e, presentationTimeUs); - } - - try { - if (debugSurfaceViewWrapper != null) { - long finalPresentationTimeUs = presentationTimeUs; - int finalInputTexId = inputTexId; - debugSurfaceViewWrapper.maybeRenderToSurfaceView( - () -> { - GlUtil.clearOutputFrame(); - getLast(textureProcessors).drawFrame(finalInputTexId, finalPresentationTimeUs); - }); - } - } catch (FrameProcessingException | GlUtil.GlException e) { - Log.d(TAG, "Error rendering to debug preview", e); - } - - checkState(pendingFrameCount.getAndDecrement() > 0); + inputSurfaceTexture.getTransformMatrix(inputSurfaceTextureTransformMatrix); + inputExternalTextureProcessor.setTextureTransformMatrix(inputSurfaceTextureTransformMatrix); + checkState( + inputExternalTextureProcessor.maybeQueueInputFrame( + inputExternalTexture, presentationTimeUs)); + checkState(pendingInputFrameCount.getAndDecrement() > 0); + // After the inputExternalTextureProcessor has produced an output frame, it is processed + // asynchronously by the texture processors chained after it. } - /** Calls {@link Listener#onFrameProcessingEnded()} once no more frames are pending. */ + /** + * Propagates the end-of-stream signal through the texture processors once no more input frames + * are pending. + * + *

    This method must be called on the {@linkplain #THREAD_NAME background thread}. + */ @WorkerThread - private void signalEndOfOutputStream() { - if (getPendingFrameCount() == 0) { - listener.onFrameProcessingEnded(); + private void processEndOfInputStream() { + if (getPendingInputFrameCount() == 0) { + // Propagates the end of stream signal through the chained texture processors. + inputExternalTextureProcessor.signalEndOfInputStream(); } else { - frameProcessingTaskExecutor.submit(this::signalEndOfOutputStream); + frameProcessingTaskExecutor.submit(this::processEndOfInputStream); } } /** - * Releases the {@link SingleFrameGlTextureProcessor SingleFrameGlTextureProcessors} and destroys - * the OpenGL context. + * Releases the {@link GlTextureProcessor} instances and destroys the OpenGL context. * *

    This method must be called on the {@linkplain #THREAD_NAME background thread}. */ @WorkerThread private void releaseTextureProcessorsAndDestroyGlContext() throws GlUtil.GlException, FrameProcessingException { + inputExternalTextureProcessor.release(); for (int i = 0; i < textureProcessors.size(); i++) { textureProcessors.get(i).release(); } GlUtil.destroyEglContext(eglDisplay, eglContext); } - - /** - * Wrapper around a {@link SurfaceView} that keeps track of whether the output surface is valid, - * and makes rendering a no-op if not. - */ - private final class SurfaceViewWrapper implements SurfaceHolder.Callback { - - @GuardedBy("this") - @Nullable - private Surface surface; - - @GuardedBy("this") - @Nullable - private EGLSurface eglSurface; - - private int width; - private int height; - - public SurfaceViewWrapper(SurfaceView surfaceView) { - surfaceView.getHolder().addCallback(this); - surface = surfaceView.getHolder().getSurface(); - width = surfaceView.getWidth(); - height = surfaceView.getHeight(); - } - - /** - * Focuses the wrapped surface view's surface as an {@link EGLSurface}, renders using {@code - * renderingTask} and swaps buffers, if the view's holder has a valid surface. Does nothing - * otherwise. - */ - @WorkerThread - public synchronized void maybeRenderToSurfaceView(FrameProcessingTask renderingTask) - throws GlUtil.GlException, FrameProcessingException { - if (surface == null) { - return; - } - - if (eglSurface == null) { - if (enableExperimentalHdrEditing) { - eglSurface = GlUtil.getEglSurfaceBt2020Pq(eglDisplay, surface); - } else { - eglSurface = GlUtil.getEglSurface(eglDisplay, surface); - } - } - EGLSurface eglSurface = this.eglSurface; - GlUtil.focusEglSurface(eglDisplay, eglContext, eglSurface, width, height); - renderingTask.run(); - EGL14.eglSwapBuffers(eglDisplay, eglSurface); - } - - @Override - public void surfaceCreated(SurfaceHolder holder) {} - - @Override - public synchronized void surfaceChanged( - SurfaceHolder holder, int format, int width, int height) { - this.width = width; - this.height = height; - Surface newSurface = holder.getSurface(); - if (surface == null || !surface.equals(newSurface)) { - surface = newSurface; - eglSurface = null; - } - } - - @Override - public synchronized void surfaceDestroyed(SurfaceHolder holder) { - surface = null; - eglSurface = null; - width = C.LENGTH_UNSET; - height = C.LENGTH_UNSET; - } - } } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/SingleFrameGlTextureProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/SingleFrameGlTextureProcessor.java index 84f05c815b..b767f973a5 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/SingleFrameGlTextureProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/SingleFrameGlTextureProcessor.java @@ -75,6 +75,16 @@ public final void setListener(Listener listener) { this.listener = listener; } + /** + * Returns whether the {@code SingleFrameGlTextureProcessor} can accept an input frame. + * + *

    If this method returns {@code true}, the next call to {@link #maybeQueueInputFrame( + * TextureInfo, long)} will also return {@code true}. + */ + public boolean acceptsInputFrame() { + return !outputTextureInUse; + } + @Override public final boolean maybeQueueInputFrame(TextureInfo inputTexture, long presentationTimeUs) { if (outputTextureInUse) { diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java index 2a7a9aa37c..3bdb16f73e 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java @@ -17,7 +17,6 @@ package androidx.media3.transformer; import static androidx.media3.common.util.Assertions.checkNotNull; -import static androidx.media3.common.util.Assertions.checkStateNotNull; import android.content.Context; import android.media.MediaCodec; @@ -32,7 +31,6 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.atomic.AtomicReference; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.dataflow.qual.Pure; @@ -91,8 +89,6 @@ public VideoTranscodingSamplePipeline( effectsListBuilder.add(Presentation.createForHeight(transformationRequest.outputHeight)); } - AtomicReference encoderInitializationException = - new AtomicReference<>(); encoderWrapper = new EncoderWrapper( encoderFactory, @@ -100,9 +96,8 @@ public VideoTranscodingSamplePipeline( allowedOutputMimeTypes, transformationRequest, fallbackListener, - encoderInitializationException); + asyncErrorListener); - @Nullable FrameProcessorChain frameProcessorChain; try { frameProcessorChain = FrameProcessorChain.create( @@ -137,12 +132,6 @@ public void onFrameProcessingEnded() { e, TransformationException.ERROR_CODE_GL_INIT_FAILED); } - if (frameProcessorChain == null) { - // Failed to create FrameProcessorChain because the encoder could not provide a surface. - throw checkStateNotNull(encoderInitializationException.get()); - } - this.frameProcessorChain = frameProcessorChain; - decoder = decoderFactory.createForVideoDecoding( inputFormat, @@ -266,7 +255,7 @@ private boolean maybeProcessDecoderOutput() throws TransformationException { } if (maxPendingFrameCount != Codec.UNLIMITED_PENDING_FRAME_COUNT - && frameProcessorChain.getPendingFrameCount() == maxPendingFrameCount) { + && frameProcessorChain.getPendingInputFrameCount() == maxPendingFrameCount) { return false; } @@ -303,7 +292,7 @@ private boolean isDecodeOnlyBuffer(long presentationTimeUs) { private final List allowedOutputMimeTypes; private final TransformationRequest transformationRequest; private final FallbackListener fallbackListener; - private final AtomicReference encoderInitializationException; + private final Transformer.AsyncErrorListener asyncErrorListener; private @MonotonicNonNull SurfaceInfo encoderSurfaceInfo; @@ -317,14 +306,14 @@ public EncoderWrapper( List allowedOutputMimeTypes, TransformationRequest transformationRequest, FallbackListener fallbackListener, - AtomicReference encoderInitializationException) { + Transformer.AsyncErrorListener asyncErrorListener) { this.encoderFactory = encoderFactory; this.inputFormat = inputFormat; this.allowedOutputMimeTypes = allowedOutputMimeTypes; this.transformationRequest = transformationRequest; this.fallbackListener = fallbackListener; - this.encoderInitializationException = encoderInitializationException; + this.asyncErrorListener = asyncErrorListener; } @Override @@ -365,7 +354,7 @@ public SurfaceInfo getSurfaceInfo(int requestedWidth, int requestedHeight) { encoder = encoderFactory.createForVideoEncoding(requestedEncoderFormat, allowedOutputMimeTypes); } catch (TransformationException e) { - encoderInitializationException.set(e); + asyncErrorListener.onTransformationException(e); return null; } Format encoderSupportedFormat = encoder.getConfigurationFormat(); diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/VideoEncoderWrapperTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/VideoEncoderWrapperTest.java index e7e7c5e4f6..ac86e370dd 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/VideoEncoderWrapperTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/VideoEncoderWrapperTest.java @@ -29,7 +29,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.common.collect.ImmutableList; import java.util.List; -import java.util.concurrent.atomic.AtomicReference; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -52,7 +51,7 @@ public final class VideoEncoderWrapperTest { /* allowedOutputMimeTypes= */ ImmutableList.of(), emptyTransformationRequest, fallbackListener, - new AtomicReference<>()); + mock(Transformer.AsyncErrorListener.class)); @Before public void registerTrack() { From 69ab79418ef21033ca25cebdf5a5e80752818ab5 Mon Sep 17 00:00:00 2001 From: hschlueter Date: Wed, 22 Jun 2022 17:16:54 +0100 Subject: [PATCH 36/73] Use GlTextureProcessor to avoid redundant copy in MediaPipeProcessor. After this change GlEffects can use any GlTextureProcessor not just SingleFrameGlTextureProcessor. MediaPipeProcessor now implements GlTextureProcessor directly which allows it to reuse MediaPipe's output texture for its output texture and avoids an extra copy shader step. PiperOrigin-RevId: 456530718 --- .../demo/transformer/TransformerActivity.java | 4 +- .../demo/transformer/MediaPipeProcessor.java | 157 +++++++++--------- .../FrameProcessorChainPixelTest.java | 2 +- ...lMatrixTransformationProcessorWrapper.java | 3 + .../androidx/media3/transformer/GlEffect.java | 10 +- .../media3/transformer/TextureInfo.java | 2 +- 6 files changed, 92 insertions(+), 86 deletions(-) diff --git a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java index 2c0b38fbf9..0c41d8c1f4 100644 --- a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java +++ b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java @@ -44,8 +44,8 @@ import androidx.media3.transformer.DefaultEncoderFactory; import androidx.media3.transformer.EncoderSelector; import androidx.media3.transformer.GlEffect; +import androidx.media3.transformer.GlTextureProcessor; import androidx.media3.transformer.ProgressHolder; -import androidx.media3.transformer.SingleFrameGlTextureProcessor; import androidx.media3.transformer.TransformationException; import androidx.media3.transformer.TransformationRequest; import androidx.media3.transformer.TransformationResult; @@ -281,7 +281,7 @@ private Transformer createTransformer(@Nullable Bundle bundle, String filePath) effects.add( (Context context) -> { try { - return (SingleFrameGlTextureProcessor) + return (GlTextureProcessor) constructor.newInstance( context, /* graphName= */ "edge_detector_mediapipe_graph.binarypb", diff --git a/demos/transformer/src/withMediaPipe/java/androidx/media3/demo/transformer/MediaPipeProcessor.java b/demos/transformer/src/withMediaPipe/java/androidx/media3/demo/transformer/MediaPipeProcessor.java index 2ceb8cf12f..3fcd65e9fa 100644 --- a/demos/transformer/src/withMediaPipe/java/androidx/media3/demo/transformer/MediaPipeProcessor.java +++ b/demos/transformer/src/withMediaPipe/java/androidx/media3/demo/transformer/MediaPipeProcessor.java @@ -20,27 +20,24 @@ import android.content.Context; import android.opengl.EGL14; -import android.opengl.GLES20; -import android.util.Size; -import androidx.media3.common.util.ConditionVariable; -import androidx.media3.common.util.GlProgram; -import androidx.media3.common.util.GlUtil; +import android.os.Build; +import androidx.annotation.ChecksSdkIntAtLeast; +import androidx.annotation.Nullable; +import androidx.media3.common.C; import androidx.media3.common.util.LibraryLoader; +import androidx.media3.common.util.Util; import androidx.media3.transformer.FrameProcessingException; -import androidx.media3.transformer.SingleFrameGlTextureProcessor; +import androidx.media3.transformer.GlTextureProcessor; +import androidx.media3.transformer.TextureInfo; import com.google.mediapipe.components.FrameProcessor; -import com.google.mediapipe.framework.AndroidAssetUtil; import com.google.mediapipe.framework.AppTextureFrame; import com.google.mediapipe.framework.TextureFrame; import com.google.mediapipe.glutil.EglManager; -import java.io.IOException; +import java.util.concurrent.ConcurrentHashMap; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -/** - * Runs a MediaPipe graph on input frames. The implementation is currently limited to graphs that - * can immediately produce one output frame per input frame. - */ -/* package */ final class MediaPipeProcessor extends SingleFrameGlTextureProcessor { +/** Runs a MediaPipe graph on input frames. */ +/* package */ final class MediaPipeProcessor implements GlTextureProcessor { private static final LibraryLoader LOADER = new LibraryLoader("mediapipe_jni") { @@ -60,17 +57,14 @@ protected void loadLibrary(String name) { } } - private static final String COPY_VERTEX_SHADER_NAME = "vertex_shader_copy_es2.glsl"; - private static final String COPY_FRAGMENT_SHADER_NAME = "shaders/fragment_shader_copy_es2.glsl"; - - private final ConditionVariable frameProcessorConditionVariable; private final FrameProcessor frameProcessor; - private final GlProgram glProgram; - - private int inputWidth; - private int inputHeight; - private @MonotonicNonNull TextureFrame outputFrame; - private @MonotonicNonNull RuntimeException frameProcessorPendingError; + private volatile GlTextureProcessor.@MonotonicNonNull Listener listener; + private volatile boolean acceptedFrame; + // Only available from API 23 and above. + @Nullable private final ConcurrentHashMap outputFrames; + // Used instead for API 21 and 22. + @Nullable private volatile TextureInfo outputTexture; + @Nullable private volatile TextureFrame outputFrame; /** * Creates a new texture processor that wraps a MediaPipe graph. @@ -79,92 +73,103 @@ protected void loadLibrary(String name) { * @param graphName Name of a MediaPipe graph asset to load. * @param inputStreamName Name of the input video stream in the graph. * @param outputStreamName Name of the input video stream in the graph. - * @throws FrameProcessingException If a problem occurs while reading shader files or initializing - * MediaPipe resources. */ + @SuppressWarnings("AndroidConcurrentHashMap") // Only used on API >= 23. public MediaPipeProcessor( - Context context, String graphName, String inputStreamName, String outputStreamName) - throws FrameProcessingException { + Context context, String graphName, String inputStreamName, String outputStreamName) { checkState(LOADER.isAvailable()); - - frameProcessorConditionVariable = new ConditionVariable(); - AndroidAssetUtil.initializeNativeAssetManager(context); EglManager eglManager = new EglManager(EGL14.eglGetCurrentContext()); frameProcessor = new FrameProcessor( context, eglManager.getNativeContext(), graphName, inputStreamName, outputStreamName); - // Unblock drawFrame when there is an output frame or an error. + outputFrames = areMultipleOutputFramesSupported() ? new ConcurrentHashMap<>() : null; frameProcessor.setConsumer( frame -> { - outputFrame = frame; - frameProcessorConditionVariable.open(); + TextureInfo texture = + new TextureInfo( + frame.getTextureName(), + /* fboId= */ C.INDEX_UNSET, + frame.getWidth(), + frame.getHeight()); + if (areMultipleOutputFramesSupported()) { + checkStateNotNull(outputFrames).put(texture, frame); + } else { + outputFrame = frame; + outputTexture = texture; + } + if (listener != null) { + listener.onOutputFrameAvailable(texture, frame.getTimestamp()); + } }); frameProcessor.setAsynchronousErrorListener( error -> { - frameProcessorPendingError = error; - frameProcessorConditionVariable.open(); + if (listener != null) { + listener.onFrameProcessingError(new FrameProcessingException(error)); + } }); - try { - glProgram = new GlProgram(context, COPY_VERTEX_SHADER_NAME, COPY_FRAGMENT_SHADER_NAME); - } catch (IOException | GlUtil.GlException e) { - throw new FrameProcessingException(e); - } + frameProcessor.setOnWillAddFrameListener((long timestamp) -> acceptedFrame = true); } @Override - public Size configure(int inputWidth, int inputHeight) { - this.inputWidth = inputWidth; - this.inputHeight = inputHeight; - return new Size(inputWidth, inputHeight); + public void setListener(GlTextureProcessor.Listener listener) { + this.listener = listener; } @Override - public void drawFrame(int inputTexId, long presentationTimeUs) throws FrameProcessingException { - frameProcessorConditionVariable.close(); + public boolean maybeQueueInputFrame(TextureInfo inputTexture, long presentationTimeUs) { + if (!areMultipleOutputFramesSupported() && outputTexture != null) { + return false; + } - // Pass the input frame to MediaPipe. - AppTextureFrame appTextureFrame = new AppTextureFrame(inputTexId, inputWidth, inputHeight); + acceptedFrame = false; + AppTextureFrame appTextureFrame = + new AppTextureFrame(inputTexture.texId, inputTexture.width, inputTexture.height); appTextureFrame.setTimestamp(presentationTimeUs); checkStateNotNull(frameProcessor).onNewFrame(appTextureFrame); - - // Wait for output to be passed to the consumer. try { - frameProcessorConditionVariable.block(); + appTextureFrame.waitUntilReleasedWithGpuSync(); } catch (InterruptedException e) { - // Propagate the interrupted flag so the next blocking operation will throw. - // TODO(b/230469581): The next processor that runs will not have valid input due to returning - // early here. This could be fixed by checking for interruption in the outer loop that runs - // through the texture processors. Thread.currentThread().interrupt(); - return; + if (listener != null) { + listener.onFrameProcessingError(new FrameProcessingException(e)); + } } - - if (frameProcessorPendingError != null) { - throw new FrameProcessingException(frameProcessorPendingError); + if (listener != null) { + listener.onInputFrameProcessed(inputTexture); } + return acceptedFrame; + } - // Copy from MediaPipe's output texture to the current output. - try { - checkStateNotNull(glProgram).use(); - glProgram.setSamplerTexIdUniform( - "uTexSampler", checkStateNotNull(outputFrame).getTextureName(), /* texUnitIndex= */ 0); - glProgram.setBufferAttribute( - "aFramePosition", - GlUtil.getNormalizedCoordinateBounds(), - GlUtil.HOMOGENEOUS_COORDINATE_VECTOR_SIZE); - glProgram.bindAttributesAndUniforms(); - GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, /* first= */ 0, /* count= */ 4); - GlUtil.checkGlError(); - } catch (GlUtil.GlException e) { - throw new FrameProcessingException(e, presentationTimeUs); - } finally { + @Override + public void releaseOutputFrame(TextureInfo outputTexture) { + if (areMultipleOutputFramesSupported()) { + checkStateNotNull(checkStateNotNull(outputFrames).get(outputTexture)).release(); + } else { + checkState(Util.areEqual(outputTexture, this.outputTexture)); + this.outputTexture = null; checkStateNotNull(outputFrame).release(); + outputFrame = null; } } @Override - public void release() throws FrameProcessingException { - super.release(); + public void release() { checkStateNotNull(frameProcessor).close(); } + + @Override + public final void signalEndOfInputStream() { + frameProcessor.waitUntilIdle(); + if (listener != null) { + listener.onOutputStreamEnded(); + } + } + + @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.M) + private static boolean areMultipleOutputFramesSupported() { + // Android devices running Lollipop (API 21/22) have a bug in ConcurrentHashMap that can result + // in lost updates, so we only allow one output frame to be pending at a time to avoid using + // ConcurrentHashMap. + return Util.SDK_INT >= 23; + } } diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java index 263714eca3..880c36bdf3 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java @@ -491,7 +491,7 @@ public GlEffectWrapper(GlEffect effect) { } @Override - public SingleFrameGlTextureProcessor toGlTextureProcessor(Context context) + public GlTextureProcessor toGlTextureProcessor(Context context) throws FrameProcessingException { return effect.toGlTextureProcessor(context); } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java index e582af3309..84040ab6e1 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java @@ -23,6 +23,7 @@ import android.opengl.EGLDisplay; import android.opengl.EGLExt; import android.opengl.EGLSurface; +import android.opengl.GLES20; import android.util.Size; import android.view.Surface; import android.view.SurfaceHolder; @@ -314,6 +315,8 @@ public synchronized void maybeRenderToSurfaceView(FrameProcessingTask renderingT GlUtil.focusEglSurface(eglDisplay, eglContext, eglSurface, width, height); renderingTask.run(); EGL14.eglSwapBuffers(eglDisplay, eglSurface); + // Prevents white flashing on the debug SurfaceView when frames are rendered too fast. + GLES20.glFinish(); } @Override diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffect.java b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffect.java index 10a587a026..0d4b77a388 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffect.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffect.java @@ -19,17 +19,15 @@ import androidx.media3.common.util.UnstableApi; /** - * Interface for a video frame effect with a {@link SingleFrameGlTextureProcessor} implementation. + * Interface for a video frame effect with a {@link GlTextureProcessor} implementation. * *

    Implementations contain information specifying the effect and can be {@linkplain - * #toGlTextureProcessor(Context) converted} to a {@link SingleFrameGlTextureProcessor} which - * applies the effect. + * #toGlTextureProcessor(Context) converted} to a {@link GlTextureProcessor} which applies the + * effect. */ @UnstableApi public interface GlEffect { /** Returns a {@link SingleFrameGlTextureProcessor} that applies the effect. */ - // TODO(b/227625423): use GlTextureProcessor here once this interface exists. - SingleFrameGlTextureProcessor toGlTextureProcessor(Context context) - throws FrameProcessingException; + GlTextureProcessor toGlTextureProcessor(Context context) throws FrameProcessingException; } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TextureInfo.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TextureInfo.java index f81f99d2c0..9e96c8e923 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/TextureInfo.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TextureInfo.java @@ -19,7 +19,7 @@ /** Contains information describing an OpenGL texture. */ @UnstableApi -/* package */ final class TextureInfo { +public final class TextureInfo { /** The OpenGL texture identifier. */ public final int texId; /** Identifier of a framebuffer object associated with the texture. */ From 74d61bbffb834cdb50d003a8de66af0e094ef702 Mon Sep 17 00:00:00 2001 From: rohks Date: Wed, 22 Jun 2022 17:19:55 +0100 Subject: [PATCH 37/73] Add timestamp to `CueGroup` `TextRenderer` is updated to output `CueGroup`, which contains the presentation time of the cues, in microseconds. PiperOrigin-RevId: 456531399 --- .../java/androidx/media3/cast/CastPlayer.java | 4 +- .../androidx/media3/common/text/CueGroup.java | 21 +- .../media3/common/text/CueGroupTest.java | 2 +- .../media3/exoplayer/ExoPlayerImpl.java | 6 +- .../media3/exoplayer/text/TextRenderer.java | 57 +- .../e2etest/PlaylistPlaybackTest.java | 47 ++ .../media3/session/MediaController.java | 6 +- .../session/MediaControllerImplLegacy.java | 6 +- .../androidx/media3/session/PlayerInfo.java | 8 +- .../playlists/playlist_with_subtitles.dump | 723 ++++++++++++++++++ .../assets/playbackdumps/webvtt/typical.dump | 5 + .../session/MediaControllerListenerTest.java | 10 +- .../session/MediaSessionProviderService.java | 4 +- .../androidx/media3/session/MockPlayer.java | 4 +- .../utils/robolectric/PlaybackOutput.java | 24 +- 15 files changed, 885 insertions(+), 42 deletions(-) create mode 100644 libraries/test_data/src/test/assets/playbackdumps/playlists/playlist_with_subtitles.dump diff --git a/libraries/cast/src/main/java/androidx/media3/cast/CastPlayer.java b/libraries/cast/src/main/java/androidx/media3/cast/CastPlayer.java index b01ff7345f..4ec40f6846 100644 --- a/libraries/cast/src/main/java/androidx/media3/cast/CastPlayer.java +++ b/libraries/cast/src/main/java/androidx/media3/cast/CastPlayer.java @@ -113,6 +113,8 @@ public final class CastPlayer extends BasePlayer { private static final long PROGRESS_REPORT_PERIOD_MS = 1000; private static final long[] EMPTY_TRACK_ID_ARRAY = new long[0]; + private static final CueGroup EMPTY_CUE_GROUP = + new CueGroup(ImmutableList.of(), /* presentationTimeUs= */ 0); private final CastContext castContext; private final MediaItemConverter mediaItemConverter; @@ -714,7 +716,7 @@ public VideoSize getVideoSize() { /** This method is not supported and returns an empty {@link CueGroup}. */ @Override public CueGroup getCurrentCues() { - return CueGroup.EMPTY; + return EMPTY_CUE_GROUP; } /** This method is not supported and always returns {@link DeviceInfo#UNKNOWN}. */ diff --git a/libraries/common/src/main/java/androidx/media3/common/text/CueGroup.java b/libraries/common/src/main/java/androidx/media3/common/text/CueGroup.java index 9a26d0ec26..3d1f1bec20 100644 --- a/libraries/common/src/main/java/androidx/media3/common/text/CueGroup.java +++ b/libraries/common/src/main/java/androidx/media3/common/text/CueGroup.java @@ -22,6 +22,7 @@ import androidx.annotation.IntDef; import androidx.annotation.Nullable; import androidx.media3.common.Bundleable; +import androidx.media3.common.Timeline; import androidx.media3.common.util.BundleableUtil; import androidx.media3.common.util.UnstableApi; import com.google.common.collect.ImmutableList; @@ -34,10 +35,6 @@ /** Class to represent the state of active {@link Cue Cues} at a particular time. */ public final class CueGroup implements Bundleable { - - /** Empty {@link CueGroup}. */ - @UnstableApi public static final CueGroup EMPTY = new CueGroup(ImmutableList.of()); - /** * The cues in this group. * @@ -47,11 +44,18 @@ public final class CueGroup implements Bundleable { *

    This list may be empty if the group represents a state with no cues. */ public final ImmutableList cues; + /** + * The presentation time of the {@link #cues}, in microseconds. + * + *

    This time is an offset from the start of the current {@link Timeline.Period} + */ + @UnstableApi public final long presentationTimeUs; /** Creates a CueGroup. */ @UnstableApi - public CueGroup(List cues) { + public CueGroup(List cues, long presentationTimeUs) { this.cues = ImmutableList.copyOf(cues); + this.presentationTimeUs = presentationTimeUs; } // Bundleable implementation. @@ -59,10 +63,11 @@ public CueGroup(List cues) { @Documented @Retention(RetentionPolicy.SOURCE) @Target(TYPE_USE) - @IntDef({FIELD_CUES}) + @IntDef({FIELD_CUES, FIELD_PRESENTATION_TIME_US}) private @interface FieldNumber {} private static final int FIELD_CUES = 0; + private static final int FIELD_PRESENTATION_TIME_US = 1; @UnstableApi @Override @@ -70,6 +75,7 @@ public Bundle toBundle() { Bundle bundle = new Bundle(); bundle.putParcelableArrayList( keyForField(FIELD_CUES), BundleableUtil.toBundleArrayList(filterOutBitmapCues(cues))); + bundle.putLong(keyForField(FIELD_PRESENTATION_TIME_US), presentationTimeUs); return bundle; } @@ -81,7 +87,8 @@ private static final CueGroup fromBundle(Bundle bundle) { cueBundles == null ? ImmutableList.of() : BundleableUtil.fromBundleList(Cue.CREATOR, cueBundles); - return new CueGroup(cues); + long presentationTimeUs = bundle.getLong(keyForField(FIELD_PRESENTATION_TIME_US)); + return new CueGroup(cues, presentationTimeUs); } private static String keyForField(@FieldNumber int field) { diff --git a/libraries/common/src/test/java/androidx/media3/common/text/CueGroupTest.java b/libraries/common/src/test/java/androidx/media3/common/text/CueGroupTest.java index 6a8f4d6e9c..03d898f3fa 100644 --- a/libraries/common/src/test/java/androidx/media3/common/text/CueGroupTest.java +++ b/libraries/common/src/test/java/androidx/media3/common/text/CueGroupTest.java @@ -37,7 +37,7 @@ public void bundleAndUnBundleCueGroup() { Cue bitmapCue = new Cue.Builder().setBitmap(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)).build(); ImmutableList cues = ImmutableList.of(textCue, bitmapCue); - CueGroup cueGroup = new CueGroup(cues); + CueGroup cueGroup = new CueGroup(cues, /* presentationTimeUs= */ 1_230_000); Parcel parcel = Parcel.obtain(); try { diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java index 389112484a..a8587da565 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java @@ -355,7 +355,7 @@ public ExoPlayerImpl(ExoPlayer.Builder builder, @Nullable Player wrappingPlayer) } else { audioSessionId = Util.generateAudioSessionIdV21(applicationContext); } - currentCueGroup = CueGroup.EMPTY; + currentCueGroup = new CueGroup(ImmutableList.of(), /* presentationTimeUs= */ 0); throwsWhenUsingWrongThread = true; addListener(analyticsCollector); @@ -939,7 +939,7 @@ public void stop(boolean reset) { verifyApplicationThread(); audioFocusManager.updateAudioFocus(getPlayWhenReady(), Player.STATE_IDLE); stopInternal(reset, /* error= */ null); - currentCueGroup = CueGroup.EMPTY; + currentCueGroup = new CueGroup(ImmutableList.of(), playbackInfo.positionUs); } @Override @@ -993,7 +993,7 @@ public void release() { checkNotNull(priorityTaskManager).remove(C.PRIORITY_PLAYBACK); isPriorityTaskManagerRegistered = false; } - currentCueGroup = CueGroup.EMPTY; + currentCueGroup = new CueGroup(ImmutableList.of(), /* presentationTimeUs= */ 0); playerReleased = true; } diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextRenderer.java index 506a69a842..2ddbd5908b 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextRenderer.java @@ -42,12 +42,13 @@ import androidx.media3.extractor.text.SubtitleDecoderException; import androidx.media3.extractor.text.SubtitleInputBuffer; import androidx.media3.extractor.text.SubtitleOutputBuffer; +import com.google.common.collect.ImmutableList; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import java.util.Collections; -import java.util.List; +import org.checkerframework.checker.nullness.qual.RequiresNonNull; +import org.checkerframework.dataflow.qual.SideEffectFree; /** * A renderer for text. @@ -103,6 +104,8 @@ public final class TextRenderer extends BaseRenderer implements Callback { @Nullable private SubtitleOutputBuffer nextSubtitle; private int nextSubtitleEventIndex; private long finalStreamEndPositionUs; + private long outputStreamOffsetUs; + private long lastRendererPositionUs; /** * @param output The output. @@ -134,6 +137,8 @@ public TextRenderer( this.decoderFactory = decoderFactory; formatHolder = new FormatHolder(); finalStreamEndPositionUs = C.TIME_UNSET; + outputStreamOffsetUs = C.TIME_UNSET; + lastRendererPositionUs = C.TIME_UNSET; } @Override @@ -170,6 +175,7 @@ public void setFinalStreamEndPositionUs(long streamEndPositionUs) { @Override protected void onStreamChanged(Format[] formats, long startPositionUs, long offsetUs) { + outputStreamOffsetUs = offsetUs; streamFormat = formats[0]; if (decoder != null) { decoderReplacementState = REPLACEMENT_STATE_SIGNAL_END_OF_STREAM; @@ -180,6 +186,7 @@ protected void onStreamChanged(Format[] formats, long startPositionUs, long offs @Override protected void onPositionReset(long positionUs, boolean joining) { + lastRendererPositionUs = positionUs; clearOutput(); inputStreamEnded = false; outputStreamEnded = false; @@ -194,6 +201,7 @@ protected void onPositionReset(long positionUs, boolean joining) { @Override public void render(long positionUs, long elapsedRealtimeUs) { + lastRendererPositionUs = positionUs; if (isCurrentStreamFinal() && finalStreamEndPositionUs != C.TIME_UNSET && positionUs >= finalStreamEndPositionUs) { @@ -257,7 +265,9 @@ public void render(long positionUs, long elapsedRealtimeUs) { // If textRendererNeedsUpdate then subtitle must be non-null. checkNotNull(subtitle); // textRendererNeedsUpdate is set and we're playing. Update the renderer. - updateOutput(subtitle.getCues(positionUs)); + long presentationTimeUs = getPresentationTimeUs(getCurrentEventTimeUs(positionUs)); + CueGroup cueGroup = new CueGroup(subtitle.getCues(positionUs), presentationTimeUs); + updateOutput(cueGroup); } if (decoderReplacementState == REPLACEMENT_STATE_WAIT_END_OF_STREAM) { @@ -315,6 +325,8 @@ protected void onDisabled() { streamFormat = null; finalStreamEndPositionUs = C.TIME_UNSET; clearOutput(); + outputStreamOffsetUs = C.TIME_UNSET; + lastRendererPositionUs = C.TIME_UNSET; releaseDecoder(); } @@ -370,33 +382,33 @@ private long getNextEventTime() { : subtitle.getEventTime(nextSubtitleEventIndex); } - private void updateOutput(List cues) { + private void updateOutput(CueGroup cueGroup) { if (outputHandler != null) { - outputHandler.obtainMessage(MSG_UPDATE_OUTPUT, cues).sendToTarget(); + outputHandler.obtainMessage(MSG_UPDATE_OUTPUT, cueGroup).sendToTarget(); } else { - invokeUpdateOutputInternal(cues); + invokeUpdateOutputInternal(cueGroup); } } private void clearOutput() { - updateOutput(Collections.emptyList()); + updateOutput(new CueGroup(ImmutableList.of(), getPresentationTimeUs(lastRendererPositionUs))); } - @SuppressWarnings("unchecked") @Override public boolean handleMessage(Message msg) { switch (msg.what) { case MSG_UPDATE_OUTPUT: - invokeUpdateOutputInternal((List) msg.obj); + invokeUpdateOutputInternal((CueGroup) msg.obj); return true; default: throw new IllegalStateException(); } } - private void invokeUpdateOutputInternal(List cues) { - output.onCues(cues); - output.onCues(new CueGroup(cues)); + @SuppressWarnings("deprecation") // We need to call both onCues method for backward compatibility. + private void invokeUpdateOutputInternal(CueGroup cueGroup) { + output.onCues(cueGroup.cues); + output.onCues(cueGroup); } /** @@ -410,4 +422,25 @@ private void handleDecoderError(SubtitleDecoderException e) { clearOutput(); replaceDecoder(); } + + @RequiresNonNull("subtitle") + @SideEffectFree + private long getCurrentEventTimeUs(long positionUs) { + int nextEventTimeIndex = subtitle.getNextEventTimeIndex(positionUs); + if (nextEventTimeIndex == 0) { + return subtitle.timeUs; + } + + return nextEventTimeIndex == C.INDEX_UNSET + ? subtitle.getEventTime(subtitle.getEventTimeCount() - 1) + : subtitle.getEventTime(nextEventTimeIndex - 1); + } + + @SideEffectFree + private long getPresentationTimeUs(long positionUs) { + checkState(positionUs != C.TIME_UNSET); + checkState(outputStreamOffsetUs != C.TIME_UNSET); + + return positionUs - outputStreamOffsetUs; + } } diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/PlaylistPlaybackTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/PlaylistPlaybackTest.java index 1987a556dc..d4de66ad9e 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/PlaylistPlaybackTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/PlaylistPlaybackTest.java @@ -16,9 +16,16 @@ package androidx.media3.exoplayer.e2etest; import android.content.Context; +import android.graphics.SurfaceTexture; +import android.net.Uri; +import android.view.Surface; +import androidx.media3.common.C; import androidx.media3.common.MediaItem; +import androidx.media3.common.MimeTypes; import androidx.media3.common.Player; import androidx.media3.exoplayer.ExoPlayer; +import androidx.media3.exoplayer.source.DefaultMediaSourceFactory; +import androidx.media3.exoplayer.source.MediaSource; import androidx.media3.test.utils.CapturingRenderersFactory; import androidx.media3.test.utils.DumpFileAsserts; import androidx.media3.test.utils.FakeClock; @@ -27,6 +34,7 @@ import androidx.media3.test.utils.robolectric.TestPlayerRunHelper; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.common.collect.ImmutableList; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -82,4 +90,43 @@ public void test_bypassOffThenOn() throws Exception { DumpFileAsserts.assertOutput( applicationContext, playbackOutput, "playbackdumps/playlists/bypass-off-then-on.dump"); } + + @Test + public void test_subtitle() throws Exception { + Context applicationContext = ApplicationProvider.getApplicationContext(); + CapturingRenderersFactory capturingRenderersFactory = + new CapturingRenderersFactory(applicationContext); + MediaSource.Factory mediaSourceFactory = + new DefaultMediaSourceFactory(applicationContext) + .experimentalUseProgressiveMediaSourceForSubtitles(true); + ExoPlayer player = + new ExoPlayer.Builder(applicationContext, capturingRenderersFactory) + .setClock(new FakeClock(/* isAutoAdvancing= */ true)) + .setMediaSourceFactory(mediaSourceFactory) + .build(); + player.setVideoSurface(new Surface(new SurfaceTexture(/* texName= */ 1))); + PlaybackOutput playbackOutput = PlaybackOutput.register(player, capturingRenderersFactory); + + player.addMediaItem(MediaItem.fromUri("asset:///media/mp4/preroll-5s.mp4")); + MediaItem mediaItemWithSubtitle = + new MediaItem.Builder() + .setUri("asset:///media/mp4/preroll-5s.mp4") + .setSubtitleConfigurations( + ImmutableList.of( + new MediaItem.SubtitleConfiguration.Builder( + Uri.parse("asset:///media/webvtt/typical")) + .setMimeType(MimeTypes.TEXT_VTT) + .setLanguage("en") + .setSelectionFlags(C.SELECTION_FLAG_DEFAULT) + .build())) + .build(); + player.addMediaItem(mediaItemWithSubtitle); + player.prepare(); + player.play(); + TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_ENDED); + player.release(); + + DumpFileAsserts.assertOutput( + applicationContext, playbackOutput, "playbackdumps/playlists/playlist_with_subtitles.dump"); + } } diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaController.java b/libraries/session/src/main/java/androidx/media3/session/MediaController.java index e47fc02253..a3a140c772 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaController.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaController.java @@ -56,6 +56,7 @@ import androidx.media3.common.util.Log; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; +import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import java.util.List; @@ -164,6 +165,9 @@ public class MediaController implements Player { "MediaController method is called from a wrong thread." + " See javadoc of MediaController for details."; + private static final CueGroup EMPTY_CUE_GROUP = + new CueGroup(ImmutableList.of(), /* presentationTimeUs= */ 0); + /** A builder for {@link MediaController}. */ public static final class Builder { @@ -1576,7 +1580,7 @@ public void clearVideoTextureView(@Nullable TextureView textureView) { @Override public CueGroup getCurrentCues() { verifyApplicationThread(); - return isConnected() ? impl.getCurrentCues() : CueGroup.EMPTY; + return isConnected() ? impl.getCurrentCues() : EMPTY_CUE_GROUP; } @Override diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java index 6a2dc56c1f..04006c7e53 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java @@ -105,6 +105,8 @@ private static final long AGGREGATES_CALLBACKS_WITHIN_TIMEOUT_MS = 500L; private static final int VOLUME_FLAGS = AudioManager.FLAG_SHOW_UI; + private static final CueGroup EMPTY_CUE_GROUP = + new CueGroup(ImmutableList.of(), /* presentationTimeUs= */ 0); /* package */ final Context context; /* package */ final MediaController instance; @@ -1016,7 +1018,7 @@ public void clearVideoTextureView(@Nullable TextureView textureView) { @Override public CueGroup getCurrentCues() { Log.w(TAG, "Session doesn't support getting Cue"); - return CueGroup.EMPTY; + return EMPTY_CUE_GROUP; } @Override @@ -2086,7 +2088,7 @@ private static ControllerInfo createControllerInfo( /* playlistMetadata= */ playlistMetadata, /* volume= */ 1.0f, /* audioAttributes= */ audioAttributes, - /* cueGroup= */ CueGroup.EMPTY, + /* cueGroup= */ EMPTY_CUE_GROUP, /* deviceInfo= */ deviceInfo, /* deviceVolume= */ deviceVolume, /* deviceMuted= */ deviceMuted, diff --git a/libraries/session/src/main/java/androidx/media3/session/PlayerInfo.java b/libraries/session/src/main/java/androidx/media3/session/PlayerInfo.java index f6bd408b7a..6b886bb568 100644 --- a/libraries/session/src/main/java/androidx/media3/session/PlayerInfo.java +++ b/libraries/session/src/main/java/androidx/media3/session/PlayerInfo.java @@ -45,6 +45,7 @@ import androidx.media3.common.VideoSize; import androidx.media3.common.text.CueGroup; import androidx.media3.common.util.Assertions; +import com.google.common.collect.ImmutableList; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -56,6 +57,9 @@ */ /* package */ class PlayerInfo implements Bundleable { + private static final CueGroup EMPTY_CUE_GROUP = + new CueGroup(ImmutableList.of(), /* presentationTimeUs= */ 0); + public static class Builder { @Nullable private PlaybackException playerError; @@ -332,7 +336,7 @@ public PlayerInfo build() { MediaMetadata.EMPTY, /* volume= */ 1f, AudioAttributes.DEFAULT, - /* cueGroup = */ CueGroup.EMPTY, + /* cueGroup = */ EMPTY_CUE_GROUP, DeviceInfo.UNKNOWN, /* deviceVolume= */ 0, /* deviceMuted= */ false, @@ -846,7 +850,7 @@ private static PlayerInfo fromBundle(Bundle bundle) { : AudioAttributes.CREATOR.fromBundle(audioAttributesBundle); @Nullable Bundle cueGroupBundle = bundle.getBundle(keyForField(FIELD_CUE_GROUP)); CueGroup cueGroup = - cueGroupBundle == null ? CueGroup.EMPTY : CueGroup.CREATOR.fromBundle(cueGroupBundle); + cueGroupBundle == null ? EMPTY_CUE_GROUP : CueGroup.CREATOR.fromBundle(cueGroupBundle); @Nullable Bundle deviceInfoBundle = bundle.getBundle(keyForField(FIELD_DEVICE_INFO)); DeviceInfo deviceInfo = deviceInfoBundle == null diff --git a/libraries/test_data/src/test/assets/playbackdumps/playlists/playlist_with_subtitles.dump b/libraries/test_data/src/test/assets/playbackdumps/playlists/playlist_with_subtitles.dump new file mode 100644 index 0000000000..718fd4bd43 --- /dev/null +++ b/libraries/test_data/src/test/assets/playbackdumps/playlists/playlist_with_subtitles.dump @@ -0,0 +1,723 @@ +MediaCodecAdapter (exotest.audio.aac): + buffers.length = 436 + buffers[0] = length 21, hash D57A2CCC + buffers[1] = length 4, hash EE9DF + buffers[2] = length 4, hash EE9DF + buffers[3] = length 4, hash EE9DF + buffers[4] = length 4, hash EE9DF + buffers[5] = length 4, hash EE9DF + buffers[6] = length 4, hash EE9DF + buffers[7] = length 4, hash EE9DF + buffers[8] = length 4, hash EE9DF + buffers[9] = length 4, hash EE9DF + buffers[10] = length 4, hash EE9DF + buffers[11] = length 4, hash EE9DF + buffers[12] = length 4, hash EE9DF + buffers[13] = length 4, hash EE9DF + buffers[14] = length 4, hash EE9DF + buffers[15] = length 4, hash EE9DF + buffers[16] = length 4, hash EE9DF + buffers[17] = length 4, hash EE9DF + buffers[18] = length 4, hash EE9DF + buffers[19] = length 4, hash EE9DF + buffers[20] = length 4, hash EE9DF + buffers[21] = length 4, hash EE9DF + buffers[22] = length 4, hash EE9DF + buffers[23] = length 4, hash EE9DF + buffers[24] = length 4, hash EE9DF + buffers[25] = length 4, hash EE9DF + buffers[26] = length 4, hash EE9DF + buffers[27] = length 4, hash EE9DF + buffers[28] = length 4, hash EE9DF + buffers[29] = length 4, hash EE9DF + buffers[30] = length 4, hash EE9DF + buffers[31] = length 4, hash EE9DF + buffers[32] = length 4, hash EE9DF + buffers[33] = length 4, hash EE9DF + buffers[34] = length 4, hash EE9DF + buffers[35] = length 4, hash EE9DF + buffers[36] = length 4, hash EE9DF + buffers[37] = length 4, hash EE9DF + buffers[38] = length 4, hash EE9DF + buffers[39] = length 4, hash EE9DF + buffers[40] = length 4, hash EE9DF + buffers[41] = length 4, hash EE9DF + buffers[42] = length 4, hash EE9DF + buffers[43] = length 4, hash EE9DF + buffers[44] = length 4, hash EE9DF + buffers[45] = length 4, hash EE9DF + buffers[46] = length 4, hash EE9DF + buffers[47] = length 4, hash EE9DF + buffers[48] = length 4, hash EE9DF + buffers[49] = length 4, hash EE9DF + buffers[50] = length 4, hash EE9DF + buffers[51] = length 4, hash EE9DF + buffers[52] = length 4, hash EE9DF + buffers[53] = length 4, hash EE9DF + buffers[54] = length 4, hash EE9DF + buffers[55] = length 4, hash EE9DF + buffers[56] = length 4, hash EE9DF + buffers[57] = length 4, hash EE9DF + buffers[58] = length 4, hash EE9DF + buffers[59] = length 4, hash EE9DF + buffers[60] = length 4, hash EE9DF + buffers[61] = length 4, hash EE9DF + buffers[62] = length 4, hash EE9DF + buffers[63] = length 4, hash EE9DF + buffers[64] = length 4, hash EE9DF + buffers[65] = length 4, hash EE9DF + buffers[66] = length 4, hash EE9DF + buffers[67] = length 4, hash EE9DF + buffers[68] = length 4, hash EE9DF + buffers[69] = length 4, hash EE9DF + buffers[70] = length 4, hash EE9DF + buffers[71] = length 4, hash EE9DF + buffers[72] = length 4, hash EE9DF + buffers[73] = length 4, hash EE9DF + buffers[74] = length 4, hash EE9DF + buffers[75] = length 4, hash EE9DF + buffers[76] = length 4, hash EE9DF + buffers[77] = length 4, hash EE9DF + buffers[78] = length 4, hash EE9DF + buffers[79] = length 4, hash EE9DF + buffers[80] = length 4, hash EE9DF + buffers[81] = length 4, hash EE9DF + buffers[82] = length 4, hash EE9DF + buffers[83] = length 4, hash EE9DF + buffers[84] = length 4, hash EE9DF + buffers[85] = length 4, hash EE9DF + buffers[86] = length 4, hash EE9DF + buffers[87] = length 4, hash EE9DF + buffers[88] = length 4, hash EE9DF + buffers[89] = length 4, hash EE9DF + buffers[90] = length 4, hash EE9DF + buffers[91] = length 4, hash EE9DF + buffers[92] = length 4, hash EE9DF + buffers[93] = length 4, hash EE9DF + buffers[94] = length 4, hash EE9DF + buffers[95] = length 4, hash EE9DF + buffers[96] = length 4, hash EE9DF + buffers[97] = length 4, hash EE9DF + buffers[98] = length 4, hash EE9DF + buffers[99] = length 4, hash EE9DF + buffers[100] = length 4, hash EE9DF + buffers[101] = length 4, hash EE9DF + buffers[102] = length 4, hash EE9DF + buffers[103] = length 4, hash EE9DF + buffers[104] = length 4, hash EE9DF + buffers[105] = length 4, hash EE9DF + buffers[106] = length 4, hash EE9DF + buffers[107] = length 4, hash EE9DF + buffers[108] = length 4, hash EE9DF + buffers[109] = length 4, hash EE9DF + buffers[110] = length 4, hash EE9DF + buffers[111] = length 4, hash EE9DF + buffers[112] = length 4, hash EE9DF + buffers[113] = length 4, hash EE9DF + buffers[114] = length 4, hash EE9DF + buffers[115] = length 4, hash EE9DF + buffers[116] = length 4, hash EE9DF + buffers[117] = length 4, hash EE9DF + buffers[118] = length 4, hash EE9DF + buffers[119] = length 4, hash EE9DF + buffers[120] = length 4, hash EE9DF + buffers[121] = length 4, hash EE9DF + buffers[122] = length 4, hash EE9DF + buffers[123] = length 4, hash EE9DF + buffers[124] = length 4, hash EE9DF + buffers[125] = length 4, hash EE9DF + buffers[126] = length 4, hash EE9DF + buffers[127] = length 4, hash EE9DF + buffers[128] = length 4, hash EE9DF + buffers[129] = length 4, hash EE9DF + buffers[130] = length 4, hash EE9DF + buffers[131] = length 4, hash EE9DF + buffers[132] = length 4, hash EE9DF + buffers[133] = length 4, hash EE9DF + buffers[134] = length 4, hash EE9DF + buffers[135] = length 4, hash EE9DF + buffers[136] = length 4, hash EE9DF + buffers[137] = length 4, hash EE9DF + buffers[138] = length 4, hash EE9DF + buffers[139] = length 4, hash EE9DF + buffers[140] = length 4, hash EE9DF + buffers[141] = length 4, hash EE9DF + buffers[142] = length 4, hash EE9DF + buffers[143] = length 4, hash EE9DF + buffers[144] = length 4, hash EE9DF + buffers[145] = length 4, hash EE9DF + buffers[146] = length 4, hash EE9DF + buffers[147] = length 4, hash EE9DF + buffers[148] = length 4, hash EE9DF + buffers[149] = length 4, hash EE9DF + buffers[150] = length 4, hash EE9DF + buffers[151] = length 4, hash EE9DF + buffers[152] = length 4, hash EE9DF + buffers[153] = length 4, hash EE9DF + buffers[154] = length 4, hash EE9DF + buffers[155] = length 4, hash EE9DF + buffers[156] = length 4, hash EE9DF + buffers[157] = length 4, hash EE9DF + buffers[158] = length 4, hash EE9DF + buffers[159] = length 4, hash EE9DF + buffers[160] = length 4, hash EE9DF + buffers[161] = length 4, hash EE9DF + buffers[162] = length 4, hash EE9DF + buffers[163] = length 4, hash EE9DF + buffers[164] = length 4, hash EE9DF + buffers[165] = length 4, hash EE9DF + buffers[166] = length 4, hash EE9DF + buffers[167] = length 4, hash EE9DF + buffers[168] = length 4, hash EE9DF + buffers[169] = length 4, hash EE9DF + buffers[170] = length 4, hash EE9DF + buffers[171] = length 4, hash EE9DF + buffers[172] = length 4, hash EE9DF + buffers[173] = length 4, hash EE9DF + buffers[174] = length 4, hash EE9DF + buffers[175] = length 4, hash EE9DF + buffers[176] = length 4, hash EE9DF + buffers[177] = length 4, hash EE9DF + buffers[178] = length 4, hash EE9DF + buffers[179] = length 4, hash EE9DF + buffers[180] = length 4, hash EE9DF + buffers[181] = length 4, hash EE9DF + buffers[182] = length 4, hash EE9DF + buffers[183] = length 4, hash EE9DF + buffers[184] = length 4, hash EE9DF + buffers[185] = length 4, hash EE9DF + buffers[186] = length 4, hash EE9DF + buffers[187] = length 4, hash EE9DF + buffers[188] = length 4, hash EE9DF + buffers[189] = length 4, hash EE9DF + buffers[190] = length 4, hash EE9DF + buffers[191] = length 4, hash EE9DF + buffers[192] = length 4, hash EE9DF + buffers[193] = length 4, hash EE9DF + buffers[194] = length 4, hash EE9DF + buffers[195] = length 4, hash EE9DF + buffers[196] = length 4, hash EE9DF + buffers[197] = length 4, hash EE9DF + buffers[198] = length 4, hash EE9DF + buffers[199] = length 4, hash EE9DF + buffers[200] = length 4, hash EE9DF + buffers[201] = length 4, hash EE9DF + buffers[202] = length 4, hash EE9DF + buffers[203] = length 4, hash EE9DF + buffers[204] = length 4, hash EE9DF + buffers[205] = length 4, hash EE9DF + buffers[206] = length 4, hash EE9DF + buffers[207] = length 4, hash EE9DF + buffers[208] = length 4, hash EE9DF + buffers[209] = length 4, hash EE9DF + buffers[210] = length 4, hash EE9DF + buffers[211] = length 4, hash EE9DF + buffers[212] = length 4, hash EE9DF + buffers[213] = length 4, hash EE9DF + buffers[214] = length 4, hash EE9DF + buffers[215] = length 4, hash EE9DF + buffers[216] = length 4, hash EE9DF + buffers[217] = length 0, hash 1 + buffers[218] = length 21, hash D57A2CCC + buffers[219] = length 4, hash EE9DF + buffers[220] = length 4, hash EE9DF + buffers[221] = length 4, hash EE9DF + buffers[222] = length 4, hash EE9DF + buffers[223] = length 4, hash EE9DF + buffers[224] = length 4, hash EE9DF + buffers[225] = length 4, hash EE9DF + buffers[226] = length 4, hash EE9DF + buffers[227] = length 4, hash EE9DF + buffers[228] = length 4, hash EE9DF + buffers[229] = length 4, hash EE9DF + buffers[230] = length 4, hash EE9DF + buffers[231] = length 4, hash EE9DF + buffers[232] = length 4, hash EE9DF + buffers[233] = length 4, hash EE9DF + buffers[234] = length 4, hash EE9DF + buffers[235] = length 4, hash EE9DF + buffers[236] = length 4, hash EE9DF + buffers[237] = length 4, hash EE9DF + buffers[238] = length 4, hash EE9DF + buffers[239] = length 4, hash EE9DF + buffers[240] = length 4, hash EE9DF + buffers[241] = length 4, hash EE9DF + buffers[242] = length 4, hash EE9DF + buffers[243] = length 4, hash EE9DF + buffers[244] = length 4, hash EE9DF + buffers[245] = length 4, hash EE9DF + buffers[246] = length 4, hash EE9DF + buffers[247] = length 4, hash EE9DF + buffers[248] = length 4, hash EE9DF + buffers[249] = length 4, hash EE9DF + buffers[250] = length 4, hash EE9DF + buffers[251] = length 4, hash EE9DF + buffers[252] = length 4, hash EE9DF + buffers[253] = length 4, hash EE9DF + buffers[254] = length 4, hash EE9DF + buffers[255] = length 4, hash EE9DF + buffers[256] = length 4, hash EE9DF + buffers[257] = length 4, hash EE9DF + buffers[258] = length 4, hash EE9DF + buffers[259] = length 4, hash EE9DF + buffers[260] = length 4, hash EE9DF + buffers[261] = length 4, hash EE9DF + buffers[262] = length 4, hash EE9DF + buffers[263] = length 4, hash EE9DF + buffers[264] = length 4, hash EE9DF + buffers[265] = length 4, hash EE9DF + buffers[266] = length 4, hash EE9DF + buffers[267] = length 4, hash EE9DF + buffers[268] = length 4, hash EE9DF + buffers[269] = length 4, hash EE9DF + buffers[270] = length 4, hash EE9DF + buffers[271] = length 4, hash EE9DF + buffers[272] = length 4, hash EE9DF + buffers[273] = length 4, hash EE9DF + buffers[274] = length 4, hash EE9DF + buffers[275] = length 4, hash EE9DF + buffers[276] = length 4, hash EE9DF + buffers[277] = length 4, hash EE9DF + buffers[278] = length 4, hash EE9DF + buffers[279] = length 4, hash EE9DF + buffers[280] = length 4, hash EE9DF + buffers[281] = length 4, hash EE9DF + buffers[282] = length 4, hash EE9DF + buffers[283] = length 4, hash EE9DF + buffers[284] = length 4, hash EE9DF + buffers[285] = length 4, hash EE9DF + buffers[286] = length 4, hash EE9DF + buffers[287] = length 4, hash EE9DF + buffers[288] = length 4, hash EE9DF + buffers[289] = length 4, hash EE9DF + buffers[290] = length 4, hash EE9DF + buffers[291] = length 4, hash EE9DF + buffers[292] = length 4, hash EE9DF + buffers[293] = length 4, hash EE9DF + buffers[294] = length 4, hash EE9DF + buffers[295] = length 4, hash EE9DF + buffers[296] = length 4, hash EE9DF + buffers[297] = length 4, hash EE9DF + buffers[298] = length 4, hash EE9DF + buffers[299] = length 4, hash EE9DF + buffers[300] = length 4, hash EE9DF + buffers[301] = length 4, hash EE9DF + buffers[302] = length 4, hash EE9DF + buffers[303] = length 4, hash EE9DF + buffers[304] = length 4, hash EE9DF + buffers[305] = length 4, hash EE9DF + buffers[306] = length 4, hash EE9DF + buffers[307] = length 4, hash EE9DF + buffers[308] = length 4, hash EE9DF + buffers[309] = length 4, hash EE9DF + buffers[310] = length 4, hash EE9DF + buffers[311] = length 4, hash EE9DF + buffers[312] = length 4, hash EE9DF + buffers[313] = length 4, hash EE9DF + buffers[314] = length 4, hash EE9DF + buffers[315] = length 4, hash EE9DF + buffers[316] = length 4, hash EE9DF + buffers[317] = length 4, hash EE9DF + buffers[318] = length 4, hash EE9DF + buffers[319] = length 4, hash EE9DF + buffers[320] = length 4, hash EE9DF + buffers[321] = length 4, hash EE9DF + buffers[322] = length 4, hash EE9DF + buffers[323] = length 4, hash EE9DF + buffers[324] = length 4, hash EE9DF + buffers[325] = length 4, hash EE9DF + buffers[326] = length 4, hash EE9DF + buffers[327] = length 4, hash EE9DF + buffers[328] = length 4, hash EE9DF + buffers[329] = length 4, hash EE9DF + buffers[330] = length 4, hash EE9DF + buffers[331] = length 4, hash EE9DF + buffers[332] = length 4, hash EE9DF + buffers[333] = length 4, hash EE9DF + buffers[334] = length 4, hash EE9DF + buffers[335] = length 4, hash EE9DF + buffers[336] = length 4, hash EE9DF + buffers[337] = length 4, hash EE9DF + buffers[338] = length 4, hash EE9DF + buffers[339] = length 4, hash EE9DF + buffers[340] = length 4, hash EE9DF + buffers[341] = length 4, hash EE9DF + buffers[342] = length 4, hash EE9DF + buffers[343] = length 4, hash EE9DF + buffers[344] = length 4, hash EE9DF + buffers[345] = length 4, hash EE9DF + buffers[346] = length 4, hash EE9DF + buffers[347] = length 4, hash EE9DF + buffers[348] = length 4, hash EE9DF + buffers[349] = length 4, hash EE9DF + buffers[350] = length 4, hash EE9DF + buffers[351] = length 4, hash EE9DF + buffers[352] = length 4, hash EE9DF + buffers[353] = length 4, hash EE9DF + buffers[354] = length 4, hash EE9DF + buffers[355] = length 4, hash EE9DF + buffers[356] = length 4, hash EE9DF + buffers[357] = length 4, hash EE9DF + buffers[358] = length 4, hash EE9DF + buffers[359] = length 4, hash EE9DF + buffers[360] = length 4, hash EE9DF + buffers[361] = length 4, hash EE9DF + buffers[362] = length 4, hash EE9DF + buffers[363] = length 4, hash EE9DF + buffers[364] = length 4, hash EE9DF + buffers[365] = length 4, hash EE9DF + buffers[366] = length 4, hash EE9DF + buffers[367] = length 4, hash EE9DF + buffers[368] = length 4, hash EE9DF + buffers[369] = length 4, hash EE9DF + buffers[370] = length 4, hash EE9DF + buffers[371] = length 4, hash EE9DF + buffers[372] = length 4, hash EE9DF + buffers[373] = length 4, hash EE9DF + buffers[374] = length 4, hash EE9DF + buffers[375] = length 4, hash EE9DF + buffers[376] = length 4, hash EE9DF + buffers[377] = length 4, hash EE9DF + buffers[378] = length 4, hash EE9DF + buffers[379] = length 4, hash EE9DF + buffers[380] = length 4, hash EE9DF + buffers[381] = length 4, hash EE9DF + buffers[382] = length 4, hash EE9DF + buffers[383] = length 4, hash EE9DF + buffers[384] = length 4, hash EE9DF + buffers[385] = length 4, hash EE9DF + buffers[386] = length 4, hash EE9DF + buffers[387] = length 4, hash EE9DF + buffers[388] = length 4, hash EE9DF + buffers[389] = length 4, hash EE9DF + buffers[390] = length 4, hash EE9DF + buffers[391] = length 4, hash EE9DF + buffers[392] = length 4, hash EE9DF + buffers[393] = length 4, hash EE9DF + buffers[394] = length 4, hash EE9DF + buffers[395] = length 4, hash EE9DF + buffers[396] = length 4, hash EE9DF + buffers[397] = length 4, hash EE9DF + buffers[398] = length 4, hash EE9DF + buffers[399] = length 4, hash EE9DF + buffers[400] = length 4, hash EE9DF + buffers[401] = length 4, hash EE9DF + buffers[402] = length 4, hash EE9DF + buffers[403] = length 4, hash EE9DF + buffers[404] = length 4, hash EE9DF + buffers[405] = length 4, hash EE9DF + buffers[406] = length 4, hash EE9DF + buffers[407] = length 4, hash EE9DF + buffers[408] = length 4, hash EE9DF + buffers[409] = length 4, hash EE9DF + buffers[410] = length 4, hash EE9DF + buffers[411] = length 4, hash EE9DF + buffers[412] = length 4, hash EE9DF + buffers[413] = length 4, hash EE9DF + buffers[414] = length 4, hash EE9DF + buffers[415] = length 4, hash EE9DF + buffers[416] = length 4, hash EE9DF + buffers[417] = length 4, hash EE9DF + buffers[418] = length 4, hash EE9DF + buffers[419] = length 4, hash EE9DF + buffers[420] = length 4, hash EE9DF + buffers[421] = length 4, hash EE9DF + buffers[422] = length 4, hash EE9DF + buffers[423] = length 4, hash EE9DF + buffers[424] = length 4, hash EE9DF + buffers[425] = length 4, hash EE9DF + buffers[426] = length 4, hash EE9DF + buffers[427] = length 4, hash EE9DF + buffers[428] = length 4, hash EE9DF + buffers[429] = length 4, hash EE9DF + buffers[430] = length 4, hash EE9DF + buffers[431] = length 4, hash EE9DF + buffers[432] = length 4, hash EE9DF + buffers[433] = length 4, hash EE9DF + buffers[434] = length 4, hash EE9DF + buffers[435] = length 0, hash 1 +MediaCodecAdapter (exotest.video.avc): + buffers.length = 251 + buffers[0] = length 5245, hash C090A41E + buffers[1] = length 63, hash 5141C80D + buffers[2] = length 22, hash A32E59A1 + buffers[3] = length 20, hash A09DEAB8 + buffers[4] = length 18, hash B64DA059 + buffers[5] = length 28, hash FC8EF2BB + buffers[6] = length 22, hash BF8A4A9F + buffers[7] = length 18, hash D163DF61 + buffers[8] = length 18, hash FD82E95 + buffers[9] = length 28, hash 44A16E72 + buffers[10] = length 22, hash 31C06057 + buffers[11] = length 18, hash DC93CC9D + buffers[12] = length 18, hash 1B081BD1 + buffers[13] = length 28, hash 2700AF + buffers[14] = length 22, hash 6D292D94 + buffers[15] = length 18, hash D646C05A + buffers[16] = length 18, hash 14BB0F8E + buffers[17] = length 28, hash 5DE2C2B + buffers[18] = length 22, hash 57E81CD0 + buffers[19] = length 18, hash E176AD96 + buffers[20] = length 18, hash 1FEAFCCA + buffers[21] = length 28, hash C163BE68 + buffers[22] = length 22, hash B0C92D0B + buffers[23] = length 18, hash 3B013BD2 + buffers[24] = length 18, hash 79758B06 + buffers[25] = length 28, hash F72EB1A3 + buffers[26] = length 22, hash 9B881C48 + buffers[27] = length 18, hash 4631290E + buffers[28] = length 18, hash 84A57842 + buffers[29] = length 28, hash E1FCF000 + buffers[30] = length 22, hash 359D2D82 + buffers[31] = length 18, hash 62DE0FC9 + buffers[32] = length 18, hash A1525EFD + buffers[33] = length 28, hash 5350E8FA + buffers[34] = length 22, hash EE2060DF + buffers[35] = length 18, hash 77D95125 + buffers[36] = length 18, hash B64DA059 + buffers[37] = length 28, hash ED67B37 + buffers[38] = length 22, hash 4701711B + buffers[39] = length 18, hash D163DF61 + buffers[40] = length 18, hash FD82E95 + buffers[41] = length 28, hash 44A16E72 + buffers[42] = length 22, hash 31C06057 + buffers[43] = length 18, hash DC93CC9D + buffers[44] = length 18, hash 1B081BD1 + buffers[45] = length 28, hash 2700AF + buffers[46] = length 22, hash 6D292D94 + buffers[47] = length 18, hash D646C05A + buffers[48] = length 18, hash 14BB0F8E + buffers[49] = length 28, hash 5DE2C2B + buffers[50] = length 22, hash 57E81CD0 + buffers[51] = length 18, hash E176AD96 + buffers[52] = length 18, hash 1FEAFCCA + buffers[53] = length 28, hash C163BE68 + buffers[54] = length 22, hash B0C92D0B + buffers[55] = length 18, hash 3B013BD2 + buffers[56] = length 18, hash 79758B06 + buffers[57] = length 28, hash F72EB1A3 + buffers[58] = length 22, hash 9B881C48 + buffers[59] = length 18, hash 4631290E + buffers[60] = length 18, hash 84A57842 + buffers[61] = length 28, hash E1FCF000 + buffers[62] = length 22, hash 359D2D82 + buffers[63] = length 18, hash 62DE0FC9 + buffers[64] = length 18, hash A1525EFD + buffers[65] = length 28, hash 5350E8FA + buffers[66] = length 22, hash EE2060DF + buffers[67] = length 18, hash 77D95125 + buffers[68] = length 18, hash B64DA059 + buffers[69] = length 28, hash ED67B37 + buffers[70] = length 22, hash 4701711B + buffers[71] = length 18, hash D163DF61 + buffers[72] = length 18, hash FD82E95 + buffers[73] = length 28, hash 44A16E72 + buffers[74] = length 22, hash 31C06057 + buffers[75] = length 18, hash DC93CC9D + buffers[76] = length 18, hash 1B081BD1 + buffers[77] = length 28, hash 2700AF + buffers[78] = length 22, hash 6D292D94 + buffers[79] = length 18, hash D646C05A + buffers[80] = length 18, hash 14BB0F8E + buffers[81] = length 28, hash 5DE2C2B + buffers[82] = length 22, hash 57E81CD0 + buffers[83] = length 18, hash E176AD96 + buffers[84] = length 18, hash 1FEAFCCA + buffers[85] = length 28, hash C163BE68 + buffers[86] = length 22, hash B0C92D0B + buffers[87] = length 18, hash 3B013BD2 + buffers[88] = length 18, hash 79758B06 + buffers[89] = length 28, hash F72EB1A3 + buffers[90] = length 22, hash 9B881C48 + buffers[91] = length 18, hash 4631290E + buffers[92] = length 18, hash 84A57842 + buffers[93] = length 33, hash AF5CF49E + buffers[94] = length 22, hash 359D2D82 + buffers[95] = length 18, hash 62DE0FC9 + buffers[96] = length 18, hash A1525EFD + buffers[97] = length 33, hash F4C6DE46 + buffers[98] = length 22, hash EE2060DF + buffers[99] = length 18, hash 77D95125 + buffers[100] = length 18, hash B64DA059 + buffers[101] = length 28, hash ED67B37 + buffers[102] = length 22, hash 4701711B + buffers[103] = length 18, hash D163DF61 + buffers[104] = length 18, hash FD82E95 + buffers[105] = length 28, hash 44A16E72 + buffers[106] = length 22, hash 31C06057 + buffers[107] = length 18, hash DC93CC9D + buffers[108] = length 18, hash 1B081BD1 + buffers[109] = length 28, hash 2700AF + buffers[110] = length 22, hash 6D292D94 + buffers[111] = length 18, hash D646C05A + buffers[112] = length 18, hash 14BB0F8E + buffers[113] = length 27, hash 5292D9E + buffers[114] = length 22, hash 57E81CD0 + buffers[115] = length 18, hash E176AD96 + buffers[116] = length 18, hash 1FEAFCCA + buffers[117] = length 26, hash B0CAA4C9 + buffers[118] = length 22, hash B0C92D0B + buffers[119] = length 18, hash 3B013BD2 + buffers[120] = length 18, hash 79758B06 + buffers[121] = length 26, hash C63A1445 + buffers[122] = length 22, hash 9B881C48 + buffers[123] = length 18, hash 4631290E + buffers[124] = length 18, hash 84A57842 + buffers[125] = length 5245, hash C090A41E + buffers[126] = length 63, hash 5141C80D + buffers[127] = length 22, hash A32E59A1 + buffers[128] = length 20, hash A09DEAB8 + buffers[129] = length 18, hash B64DA059 + buffers[130] = length 28, hash FC8EF2BB + buffers[131] = length 22, hash BF8A4A9F + buffers[132] = length 18, hash D163DF61 + buffers[133] = length 18, hash FD82E95 + buffers[134] = length 28, hash 44A16E72 + buffers[135] = length 22, hash 31C06057 + buffers[136] = length 18, hash DC93CC9D + buffers[137] = length 18, hash 1B081BD1 + buffers[138] = length 28, hash 2700AF + buffers[139] = length 22, hash 6D292D94 + buffers[140] = length 18, hash D646C05A + buffers[141] = length 18, hash 14BB0F8E + buffers[142] = length 28, hash 5DE2C2B + buffers[143] = length 22, hash 57E81CD0 + buffers[144] = length 18, hash E176AD96 + buffers[145] = length 18, hash 1FEAFCCA + buffers[146] = length 28, hash C163BE68 + buffers[147] = length 22, hash B0C92D0B + buffers[148] = length 18, hash 3B013BD2 + buffers[149] = length 18, hash 79758B06 + buffers[150] = length 28, hash F72EB1A3 + buffers[151] = length 22, hash 9B881C48 + buffers[152] = length 18, hash 4631290E + buffers[153] = length 18, hash 84A57842 + buffers[154] = length 28, hash E1FCF000 + buffers[155] = length 22, hash 359D2D82 + buffers[156] = length 18, hash 62DE0FC9 + buffers[157] = length 18, hash A1525EFD + buffers[158] = length 28, hash 5350E8FA + buffers[159] = length 22, hash EE2060DF + buffers[160] = length 18, hash 77D95125 + buffers[161] = length 18, hash B64DA059 + buffers[162] = length 28, hash ED67B37 + buffers[163] = length 22, hash 4701711B + buffers[164] = length 18, hash D163DF61 + buffers[165] = length 18, hash FD82E95 + buffers[166] = length 28, hash 44A16E72 + buffers[167] = length 22, hash 31C06057 + buffers[168] = length 18, hash DC93CC9D + buffers[169] = length 18, hash 1B081BD1 + buffers[170] = length 28, hash 2700AF + buffers[171] = length 22, hash 6D292D94 + buffers[172] = length 18, hash D646C05A + buffers[173] = length 18, hash 14BB0F8E + buffers[174] = length 28, hash 5DE2C2B + buffers[175] = length 22, hash 57E81CD0 + buffers[176] = length 18, hash E176AD96 + buffers[177] = length 18, hash 1FEAFCCA + buffers[178] = length 28, hash C163BE68 + buffers[179] = length 22, hash B0C92D0B + buffers[180] = length 18, hash 3B013BD2 + buffers[181] = length 18, hash 79758B06 + buffers[182] = length 28, hash F72EB1A3 + buffers[183] = length 22, hash 9B881C48 + buffers[184] = length 18, hash 4631290E + buffers[185] = length 18, hash 84A57842 + buffers[186] = length 28, hash E1FCF000 + buffers[187] = length 22, hash 359D2D82 + buffers[188] = length 18, hash 62DE0FC9 + buffers[189] = length 18, hash A1525EFD + buffers[190] = length 28, hash 5350E8FA + buffers[191] = length 22, hash EE2060DF + buffers[192] = length 18, hash 77D95125 + buffers[193] = length 18, hash B64DA059 + buffers[194] = length 28, hash ED67B37 + buffers[195] = length 22, hash 4701711B + buffers[196] = length 18, hash D163DF61 + buffers[197] = length 18, hash FD82E95 + buffers[198] = length 28, hash 44A16E72 + buffers[199] = length 22, hash 31C06057 + buffers[200] = length 18, hash DC93CC9D + buffers[201] = length 18, hash 1B081BD1 + buffers[202] = length 28, hash 2700AF + buffers[203] = length 22, hash 6D292D94 + buffers[204] = length 18, hash D646C05A + buffers[205] = length 18, hash 14BB0F8E + buffers[206] = length 28, hash 5DE2C2B + buffers[207] = length 22, hash 57E81CD0 + buffers[208] = length 18, hash E176AD96 + buffers[209] = length 18, hash 1FEAFCCA + buffers[210] = length 28, hash C163BE68 + buffers[211] = length 22, hash B0C92D0B + buffers[212] = length 18, hash 3B013BD2 + buffers[213] = length 18, hash 79758B06 + buffers[214] = length 28, hash F72EB1A3 + buffers[215] = length 22, hash 9B881C48 + buffers[216] = length 18, hash 4631290E + buffers[217] = length 18, hash 84A57842 + buffers[218] = length 33, hash AF5CF49E + buffers[219] = length 22, hash 359D2D82 + buffers[220] = length 18, hash 62DE0FC9 + buffers[221] = length 18, hash A1525EFD + buffers[222] = length 33, hash F4C6DE46 + buffers[223] = length 22, hash EE2060DF + buffers[224] = length 18, hash 77D95125 + buffers[225] = length 18, hash B64DA059 + buffers[226] = length 28, hash ED67B37 + buffers[227] = length 22, hash 4701711B + buffers[228] = length 18, hash D163DF61 + buffers[229] = length 18, hash FD82E95 + buffers[230] = length 28, hash 44A16E72 + buffers[231] = length 22, hash 31C06057 + buffers[232] = length 18, hash DC93CC9D + buffers[233] = length 18, hash 1B081BD1 + buffers[234] = length 28, hash 2700AF + buffers[235] = length 22, hash 6D292D94 + buffers[236] = length 18, hash D646C05A + buffers[237] = length 18, hash 14BB0F8E + buffers[238] = length 27, hash 5292D9E + buffers[239] = length 22, hash 57E81CD0 + buffers[240] = length 18, hash E176AD96 + buffers[241] = length 18, hash 1FEAFCCA + buffers[242] = length 26, hash B0CAA4C9 + buffers[243] = length 22, hash B0C92D0B + buffers[244] = length 18, hash 3B013BD2 + buffers[245] = length 18, hash 79758B06 + buffers[246] = length 26, hash C63A1445 + buffers[247] = length 22, hash 9B881C48 + buffers[248] = length 18, hash 4631290E + buffers[249] = length 18, hash 84A57842 + buffers[250] = length 0, hash 1 +TextOutput: + Subtitle[0]: + presentationTimeUs = 0 + Cues = [] + Subtitle[1]: + presentationTimeUs = 0 + Cue[0]: + text = This is the first subtitle. + textAlignment = ALIGN_CENTER + line = -1.0 + lineType = 1 + lineAnchor = 0 + position = 0.5 + positionAnchor = 1 + size = 1.0 + Subtitle[2]: + presentationTimeUs = 1234000 + Cues = [] + Subtitle[3]: + presentationTimeUs = 2345000 + Cue[0]: + text = This is the second subtitle. + textAlignment = ALIGN_CENTER + line = -1.0 + lineType = 1 + lineAnchor = 0 + position = 0.5 + positionAnchor = 1 + size = 1.0 + Subtitle[4]: + presentationTimeUs = 3456000 + Cues = [] diff --git a/libraries/test_data/src/test/assets/playbackdumps/webvtt/typical.dump b/libraries/test_data/src/test/assets/playbackdumps/webvtt/typical.dump index db4b4047c5..bc1e7b954a 100644 --- a/libraries/test_data/src/test/assets/playbackdumps/webvtt/typical.dump +++ b/libraries/test_data/src/test/assets/playbackdumps/webvtt/typical.dump @@ -348,8 +348,10 @@ MediaCodecAdapter (exotest.video.avc): buffers[125] = length 0, hash 1 TextOutput: Subtitle[0]: + presentationTimeUs = 0 Cues = [] Subtitle[1]: + presentationTimeUs = 0 Cue[0]: text = This is the first subtitle. textAlignment = ALIGN_CENTER @@ -360,8 +362,10 @@ TextOutput: positionAnchor = 1 size = 1.0 Subtitle[2]: + presentationTimeUs = 1234000 Cues = [] Subtitle[3]: + presentationTimeUs = 2345000 Cue[0]: text = This is the second subtitle. textAlignment = ALIGN_CENTER @@ -372,4 +376,5 @@ TextOutput: positionAnchor = 1 size = 1.0 Subtitle[4]: + presentationTimeUs = 3456000 Cues = [] diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerTest.java index 2cfaf781b6..b84b90a9a6 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerTest.java @@ -1920,7 +1920,7 @@ public void getCurrentCues_afterConnected() throws Exception { Bundle playerConfig = new RemoteMediaSession.MockPlayerConfigBuilder() - .setCurrentCues(new CueGroup(testCues)) + .setCurrentCues(new CueGroup(testCues, /* presentationTimeUs= */ 1_230_000)) .build(); remoteSession.setPlayer(playerConfig); @@ -1938,7 +1938,7 @@ public void onCues_emptyList_whenCommandUnavailable() throws Exception { Bundle playerConfig = new RemoteMediaSession.MockPlayerConfigBuilder() - .setCurrentCues(new CueGroup(testCues)) + .setCurrentCues(new CueGroup(testCues, /* presentationTimeUs= */ 1_230_000)) .build(); remoteSession.setPlayer(playerConfig); @@ -1991,7 +1991,7 @@ public void onCues(CueGroup cueGroup) { Bundle playerConfig = new RemoteMediaSession.MockPlayerConfigBuilder() - .setCurrentCues(new CueGroup(testCues)) + .setCurrentCues(new CueGroup(testCues, /* presentationTimeUs= */ 1_230_000)) .build(); remoteSession.setPlayer(playerConfig); @@ -2021,7 +2021,9 @@ public void onCues(CueGroup cueGroup) { }; threadTestRule.getHandler().postAndSync(() -> controller.addListener(listener)); - remoteSession.getMockPlayer().notifyCuesChanged(new CueGroup(testCues)); + remoteSession + .getMockPlayer() + .notifyCuesChanged(new CueGroup(testCues, /* presentationTimeUs= */ 1_230_000)); assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); assertThat(cuesFromParam).isEqualTo(testCues); diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/MediaSessionProviderService.java b/libraries/test_session_current/src/main/java/androidx/media3/session/MediaSessionProviderService.java index 6bf44ca49f..fa4605cfaa 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/MediaSessionProviderService.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/MediaSessionProviderService.java @@ -105,6 +105,8 @@ public class MediaSessionProviderService extends Service { private static final String TAG = "MSProviderService"; + private static final CueGroup EMPTY_CUE_GROUP = + new CueGroup(ImmutableList.of(), /* presentationTimeUs= */ 0); private Map sessionMap = new HashMap<>(); private RemoteMediaSessionStub sessionBinder; @@ -327,7 +329,7 @@ private Player createMockPlayer(Bundle config) { } Bundle cueGroupBundle = config.getBundle(KEY_CURRENT_CUE_GROUP); player.cueGroup = - cueGroupBundle == null ? CueGroup.EMPTY : CueGroup.CREATOR.fromBundle(cueGroupBundle); + cueGroupBundle == null ? EMPTY_CUE_GROUP : CueGroup.CREATOR.fromBundle(cueGroupBundle); @Nullable Bundle deviceInfoBundle = config.getBundle(KEY_DEVICE_INFO); if (deviceInfoBundle != null) { player.deviceInfo = DeviceInfo.CREATOR.fromBundle(deviceInfoBundle); diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/MockPlayer.java b/libraries/test_session_current/src/main/java/androidx/media3/session/MockPlayer.java index d9a9258b65..ee26b18e33 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/MockPlayer.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/MockPlayer.java @@ -196,6 +196,8 @@ public class MockPlayer implements Player { private final ArraySet listeners = new ArraySet<>(); private final ImmutableMap<@Method Integer, ConditionVariable> conditionVariables = createMethodConditionVariables(); + private static final CueGroup EMPTY_CUE_GROUP = + new CueGroup(ImmutableList.of(), /* presentationTimeUs= */ 0); @Nullable PlaybackException playerError; public AudioAttributes audioAttributes; @@ -276,7 +278,7 @@ private MockPlayer(Builder builder) { repeatMode = Player.REPEAT_MODE_OFF; videoSize = VideoSize.UNKNOWN; volume = 1.0f; - cueGroup = CueGroup.EMPTY; + cueGroup = EMPTY_CUE_GROUP; deviceInfo = DeviceInfo.UNKNOWN; seekPositionMs = C.TIME_UNSET; seekMediaItemIndex = C.INDEX_UNSET; diff --git a/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/PlaybackOutput.java b/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/PlaybackOutput.java index 947ab7d82c..8fc015fc9c 100644 --- a/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/PlaybackOutput.java +++ b/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/PlaybackOutput.java @@ -15,6 +15,8 @@ */ package androidx.media3.test.utils.robolectric; +import static java.lang.Math.max; + import android.graphics.Bitmap; import androidx.annotation.Nullable; import androidx.media3.common.Metadata; @@ -56,7 +58,7 @@ public final class PlaybackOutput implements Dumper.Dumpable { private final CapturingRenderersFactory capturingRenderersFactory; private final List metadatas; - private final List> subtitles; + private final List subtitles; private final List> subtitlesFromDeprecatedTextOutput; private PlaybackOutput(ExoPlayer player, CapturingRenderersFactory capturingRenderersFactory) { @@ -65,8 +67,8 @@ private PlaybackOutput(ExoPlayer player, CapturingRenderersFactory capturingRend metadatas = Collections.synchronizedList(new ArrayList<>()); subtitles = Collections.synchronizedList(new ArrayList<>()); subtitlesFromDeprecatedTextOutput = Collections.synchronizedList(new ArrayList<>()); - // TODO: Consider passing playback position into MetadataOutput and TextOutput. Calling - // player.getCurrentPosition() inside onMetadata/Cues will likely be non-deterministic + // TODO: Consider passing playback position into MetadataOutput. Calling + // player.getCurrentPosition() inside onMetadata will likely be non-deterministic // because renderer-thread != playback-thread. player.addListener( new Player.Listener() { @@ -82,7 +84,7 @@ public void onCues(List cues) { @Override public void onCues(CueGroup cueGroup) { - subtitles.add(cueGroup.cues); + subtitles.add(cueGroup); } }); } @@ -154,9 +156,9 @@ private static String getEntryAsString(Metadata.Entry entry) { } private void dumpSubtitles(Dumper dumper) { - if (!subtitles.equals(subtitlesFromDeprecatedTextOutput)) { + if (subtitles.size() != subtitlesFromDeprecatedTextOutput.size()) { throw new IllegalStateException( - "Expected subtitles to be equal from both implementations of onCues method."); + "Expected subtitles to be of equal length from both implementations of onCues method."); } if (subtitles.isEmpty()) { @@ -165,7 +167,15 @@ private void dumpSubtitles(Dumper dumper) { dumper.startBlock("TextOutput"); for (int i = 0; i < subtitles.size(); i++) { dumper.startBlock("Subtitle[" + i + "]"); - List subtitle = subtitles.get(i); + // TODO: Solving https://github.com/google/ExoPlayer/issues/9672 will allow us to remove this + // hack of forcing presentationTimeUs to be >= 0. + dumper.add("presentationTimeUs", max(0, subtitles.get(i).presentationTimeUs)); + ImmutableList subtitle = subtitles.get(i).cues; + if (!subtitle.equals(subtitlesFromDeprecatedTextOutput.get(i))) { + throw new IllegalStateException( + "Expected subtitle to be equal from both implementations of onCues method for index " + + i); + } if (subtitle.isEmpty()) { dumper.add("Cues", ImmutableList.of()); } From 352967f65661296ff5551138fd6346fce0c52a3f Mon Sep 17 00:00:00 2001 From: samrobinson Date: Thu, 23 Jun 2022 11:37:19 +0100 Subject: [PATCH 38/73] Add a Builder for DefaultEncoderFactory. PiperOrigin-RevId: 456728032 --- .../demo/transformer/TransformerActivity.java | 8 +- .../media3/transformer/AndroidTestUtil.java | 2 +- .../transformer/TransformerEndToEndTest.java | 8 +- .../transformer/mh/TransformationTest.java | 10 +- .../mh/analysis/BitrateAnalysisTest.java | 17 ++- .../EncoderPerformanceAnalysisTest.java | 15 ++- .../transformer/DefaultEncoderFactory.java | 109 ++++++++++++++---- .../media3/transformer/Transformer.java | 2 +- .../DefaultEncoderFactoryTest.java | 19 +-- .../transformer/TransformerEndToEndTest.java | 2 +- 10 files changed, 124 insertions(+), 68 deletions(-) diff --git a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java index 0c41d8c1f4..3e969ff938 100644 --- a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java +++ b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java @@ -42,7 +42,6 @@ import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.util.DebugTextViewHelper; import androidx.media3.transformer.DefaultEncoderFactory; -import androidx.media3.transformer.EncoderSelector; import androidx.media3.transformer.GlEffect; import androidx.media3.transformer.GlTextureProcessor; import androidx.media3.transformer.ProgressHolder; @@ -260,10 +259,9 @@ private Transformer createTransformer(@Nullable Bundle bundle, String filePath) .setRemoveAudio(bundle.getBoolean(ConfigurationActivity.SHOULD_REMOVE_AUDIO)) .setRemoveVideo(bundle.getBoolean(ConfigurationActivity.SHOULD_REMOVE_VIDEO)) .setEncoderFactory( - new DefaultEncoderFactory( - /* context= */ this, - EncoderSelector.DEFAULT, - /* enableFallback= */ bundle.getBoolean(ConfigurationActivity.ENABLE_FALLBACK))); + new DefaultEncoderFactory.Builder(this.getApplicationContext()) + .setEnableFallback(bundle.getBoolean(ConfigurationActivity.ENABLE_FALLBACK)) + .build()); ImmutableList.Builder effects = new ImmutableList.Builder<>(); @Nullable diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/AndroidTestUtil.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/AndroidTestUtil.java index ea0c498522..9e6c3faf67 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/AndroidTestUtil.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/AndroidTestUtil.java @@ -225,7 +225,7 @@ public static final class ForceEncodeEncoderFactory implements Codec.EncoderFact /** Creates an instance that wraps {@link DefaultEncoderFactory}. */ public ForceEncodeEncoderFactory(Context context) { - encoderFactory = new DefaultEncoderFactory(context); + encoderFactory = new DefaultEncoderFactory.Builder(context).build(); } /** diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java index f7aeb0ca91..c7e3cb4766 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java @@ -46,8 +46,7 @@ public void videoEditing_completesWithConsistentFrameCount() throws Exception { .setTransformationRequest( new TransformationRequest.Builder().setResolution(480).build()) .setEncoderFactory( - new DefaultEncoderFactory( - context, EncoderSelector.DEFAULT, /* enableFallback= */ false)) + new DefaultEncoderFactory.Builder(context).setEnableFallback(false).build()) .build(); // Result of the following command: // ffprobe -count_frames -select_streams v:0 -show_entries stream=nb_read_frames sample.mp4 @@ -71,8 +70,7 @@ public void videoOnly_completesWithConsistentDuration() throws Exception { .setTransformationRequest( new TransformationRequest.Builder().setResolution(480).build()) .setEncoderFactory( - new DefaultEncoderFactory( - context, EncoderSelector.DEFAULT, /* enableFallback= */ false)) + new DefaultEncoderFactory.Builder(context).setEnableFallback(false).build()) .build(); long expectedDurationMs = 967; @@ -138,7 +136,7 @@ private static final class VideoUnsupportedEncoderFactory implements Codec.Encod private final Codec.EncoderFactory encoderFactory; public VideoUnsupportedEncoderFactory(Context context) { - encoderFactory = new DefaultEncoderFactory(context); + encoderFactory = new DefaultEncoderFactory.Builder(context).build(); } @Override diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/TransformationTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/TransformationTest.java index 045961c1a1..edfd6101ab 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/TransformationTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/TransformationTest.java @@ -31,7 +31,6 @@ import androidx.media3.transformer.AndroidTestUtil; import androidx.media3.transformer.AndroidTestUtil.ForceEncodeEncoderFactory; import androidx.media3.transformer.DefaultEncoderFactory; -import androidx.media3.transformer.EncoderSelector; import androidx.media3.transformer.TransformationRequest; import androidx.media3.transformer.Transformer; import androidx.media3.transformer.TransformerAndroidTestRunner; @@ -81,11 +80,10 @@ public void transformToSpecificBitrate() throws Exception { .setRemoveAudio(true) .setEncoderFactory( new ForceEncodeEncoderFactory( - /* wrappedEncoderFactory= */ new DefaultEncoderFactory( - context, - EncoderSelector.DEFAULT, - new VideoEncoderSettings.Builder().setBitrate(5_000_000).build(), - /* enableFallback= */ true))) + /* wrappedEncoderFactory= */ new DefaultEncoderFactory.Builder(context) + .setRequestedVideoEncoderSettings( + new VideoEncoderSettings.Builder().setBitrate(5_000_000).build()) + .build())) .build(); new TransformerAndroidTestRunner.Builder(context, transformer) .setMaybeCalculateSsim(true) diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/analysis/BitrateAnalysisTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/analysis/BitrateAnalysisTest.java index 45e4cb60d6..1b8837f137 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/analysis/BitrateAnalysisTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/analysis/BitrateAnalysisTest.java @@ -24,7 +24,6 @@ import androidx.media3.common.util.Assertions; import androidx.media3.transformer.AndroidTestUtil; import androidx.media3.transformer.DefaultEncoderFactory; -import androidx.media3.transformer.EncoderSelector; import androidx.media3.transformer.Transformer; import androidx.media3.transformer.TransformerAndroidTestRunner; import androidx.media3.transformer.VideoEncoderSettings; @@ -117,14 +116,14 @@ public void analyzeBitrate() throws Exception { .setRemoveAudio(true) .setEncoderFactory( new AndroidTestUtil.ForceEncodeEncoderFactory( - /* wrappedEncoderFactory= */ new DefaultEncoderFactory( - context, - EncoderSelector.DEFAULT, - new VideoEncoderSettings.Builder() - .setBitrate(bitrate) - .setBitrateMode(bitrateMode) - .build(), - /* enableFallback= */ false))) + /* wrappedEncoderFactory= */ new DefaultEncoderFactory.Builder(context) + .setRequestedVideoEncoderSettings( + new VideoEncoderSettings.Builder() + .setBitrate(bitrate) + .setBitrateMode(bitrateMode) + .build()) + .setEnableFallback(false) + .build())) .build(); new TransformerAndroidTestRunner.Builder(context, transformer) diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/analysis/EncoderPerformanceAnalysisTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/analysis/EncoderPerformanceAnalysisTest.java index f2e28184fc..1ef1566c1d 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/analysis/EncoderPerformanceAnalysisTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/analysis/EncoderPerformanceAnalysisTest.java @@ -26,7 +26,6 @@ import androidx.media3.common.util.Util; import androidx.media3.transformer.AndroidTestUtil; import androidx.media3.transformer.DefaultEncoderFactory; -import androidx.media3.transformer.EncoderSelector; import androidx.media3.transformer.Transformer; import androidx.media3.transformer.TransformerAndroidTestRunner; import androidx.media3.transformer.VideoEncoderSettings; @@ -127,13 +126,13 @@ public void analyzeEncoderPerformance() throws Exception { .setRemoveAudio(true) .setEncoderFactory( new AndroidTestUtil.ForceEncodeEncoderFactory( - /* wrappedEncoderFactory= */ new DefaultEncoderFactory( - context, - EncoderSelector.DEFAULT, - new VideoEncoderSettings.Builder() - .setEncoderPerformanceParameters(operatingRate, priority) - .build(), - /* enableFallback= */ false))) + /* wrappedEncoderFactory= */ new DefaultEncoderFactory.Builder(context) + .setRequestedVideoEncoderSettings( + new VideoEncoderSettings.Builder() + .setEncoderPerformanceParameters(operatingRate, priority) + .build()) + .setEnableFallback(false) + .build())) .build(); new TransformerAndroidTestRunner.Builder(context, transformer) diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java b/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java index 4303463b18..fda367d6f0 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java @@ -47,48 +47,109 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { private static final int DEFAULT_FRAME_RATE = 30; private static final String TAG = "DefaultEncoderFactory"; + /** A builder for {@link DefaultEncoderFactory} instances. */ + public static final class Builder { + private final Context context; + + @Nullable private EncoderSelector encoderSelector; + @Nullable private VideoEncoderSettings requestedVideoEncoderSettings; + private boolean enableFallback; + + /** Creates a new {@link Builder}. */ + public Builder(Context context) { + this.context = context; + this.enableFallback = true; + } + + /** + * Sets the video {@link EncoderSelector}. + * + *

    The default value is {@link EncoderSelector#DEFAULT}. + */ + public Builder setVideoEncoderSelector(EncoderSelector encoderSelector) { + this.encoderSelector = encoderSelector; + return this; + } + + /** + * Sets the requested {@link VideoEncoderSettings}. + * + *

    Values in {@code requestedVideoEncoderSettings} could be adjusted to improve encoding + * quality and/or reduce failures. Specifically, {@link VideoEncoderSettings#profile} and {@link + * VideoEncoderSettings#level} are ignored for {@link MimeTypes#VIDEO_H264}. Consider + * implementing {@link Codec.EncoderFactory} if such adjustments are unwanted. + * + *

    {@code requestedVideoEncoderSettings} should be handled with care because there is no + * fallback support for it. For example, using incompatible {@link VideoEncoderSettings#profile} + * and {@link VideoEncoderSettings#level} can cause codec configuration failure. Setting an + * unsupported {@link VideoEncoderSettings#bitrateMode} may cause encoder instantiation failure. + * + *

    The default value is {@link VideoEncoderSettings#DEFAULT}. + */ + public Builder setRequestedVideoEncoderSettings( + VideoEncoderSettings requestedVideoEncoderSettings) { + this.requestedVideoEncoderSettings = requestedVideoEncoderSettings; + return this; + } + + /** + * Sets whether the encoder can fallback. + * + *

    With format fallback enabled, when the requested {@link Format} is not supported, {@code + * DefaultEncoderFactory} finds a format that is supported by the device and configures the + * {@link Codec} with it. The fallback process may change the requested {@link + * Format#sampleMimeType MIME type}, resolution, {@link Format#bitrate bitrate}, {@link + * Format#codecs profile/level} etc. + * + *

    The default value is {@code true}. + */ + public Builder setEnableFallback(boolean enableFallback) { + this.enableFallback = enableFallback; + return this; + } + + /** Creates an instance of {@link DefaultEncoderFactory}, using defaults if values are unset. */ + @SuppressWarnings("deprecation") + public DefaultEncoderFactory build() { + if (encoderSelector == null) { + encoderSelector = EncoderSelector.DEFAULT; + } + if (requestedVideoEncoderSettings == null) { + requestedVideoEncoderSettings = VideoEncoderSettings.DEFAULT; + } + return new DefaultEncoderFactory( + context, encoderSelector, requestedVideoEncoderSettings, enableFallback); + } + } + private final Context context; private final EncoderSelector videoEncoderSelector; private final VideoEncoderSettings requestedVideoEncoderSettings; private final boolean enableFallback; /** - * Creates a new instance using the {@link EncoderSelector#DEFAULT default encoder selector}, a - * default {@link VideoEncoderSettings}, and with format fallback enabled. + * @deprecated Use {@link Builder} instead. */ + @Deprecated + @SuppressWarnings("deprecation") public DefaultEncoderFactory(Context context) { this(context, EncoderSelector.DEFAULT, /* enableFallback= */ true); } - /** Creates a new instance using a default {@link VideoEncoderSettings}. */ + /** + * @deprecated Use {@link Builder} instead. + */ + @Deprecated + @SuppressWarnings("deprecation") public DefaultEncoderFactory( Context context, EncoderSelector videoEncoderSelector, boolean enableFallback) { this(context, videoEncoderSelector, VideoEncoderSettings.DEFAULT, enableFallback); } /** - * Creates a new instance. - * - *

    With format fallback enabled, when the requested {@link Format} is not supported, {@code - * DefaultEncoderFactory} finds a format that is supported by the device and configures the {@link - * Codec} with it. The fallback process may change the requested {@link Format#sampleMimeType MIME - * type}, resolution, {@link Format#bitrate bitrate}, {@link Format#codecs profile/level} etc. - * - *

    Values in {@code requestedVideoEncoderSettings} could be adjusted to improve encoding - * quality and/or reduce failures. Specifically, {@link VideoEncoderSettings#profile} and {@link - * VideoEncoderSettings#level} are ignored for {@link MimeTypes#VIDEO_H264}. Consider implementing - * {@link Codec.EncoderFactory} if such adjustments are unwanted. - * - *

    {@code requestedVideoEncoderSettings} should be handled with care because there is no - * fallback support for it. For example, using incompatible {@link VideoEncoderSettings#profile} - * and {@link VideoEncoderSettings#level} can cause codec configuration failure. Setting an - * unsupported {@link VideoEncoderSettings#bitrateMode} may cause encoder instantiation failure. - * - * @param context The {@link Context}. - * @param videoEncoderSelector The {@link EncoderSelector}. - * @param requestedVideoEncoderSettings The {@link VideoEncoderSettings}. - * @param enableFallback Whether to enable fallback. + * @deprecated Use {@link Builder} instead. */ + @Deprecated public DefaultEncoderFactory( Context context, EncoderSelector videoEncoderSelector, diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java b/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java index e8af343ce7..433b777a75 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java @@ -122,7 +122,7 @@ public Builder(Context context) { looper = Util.getCurrentOrMainLooper(); clock = Clock.DEFAULT; listeners = new ListenerSet<>(looper, clock, (listener, flags) -> {}); - encoderFactory = new DefaultEncoderFactory(this.context); + encoderFactory = new DefaultEncoderFactory.Builder(this.context).build(); decoderFactory = new DefaultDecoderFactory(this.context); debugViewProvider = DebugViewProvider.NONE; containerMimeType = MimeTypes.VIDEO_MP4; diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/DefaultEncoderFactoryTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/DefaultEncoderFactoryTest.java index 6272ff9036..0896c7f427 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/DefaultEncoderFactoryTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/DefaultEncoderFactoryTest.java @@ -68,7 +68,8 @@ public void createForVideoEncoding_withFallbackOnAndSupportedInputFormat_configu throws Exception { Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30); Format actualVideoFormat = - new DefaultEncoderFactory(context) + new DefaultEncoderFactory.Builder(context) + .build() .createForVideoEncoding( requestedVideoFormat, /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) @@ -86,7 +87,8 @@ public void createForVideoEncoding_withFallbackOnAndUnsupportedMimeType_configur throws Exception { Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H265, 1920, 1080, 30); Format actualVideoFormat = - new DefaultEncoderFactory(context) + new DefaultEncoderFactory.Builder(context) + .build() .createForVideoEncoding( requestedVideoFormat, /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) @@ -104,7 +106,8 @@ public void createForVideoEncoding_withFallbackOnAndUnsupportedResolution_config throws Exception { Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 3840, 2160, 60); Format actualVideoFormat = - new DefaultEncoderFactory(context) + new DefaultEncoderFactory.Builder(context) + .build() .createForVideoEncoding( requestedVideoFormat, /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) @@ -122,7 +125,8 @@ public void createForVideoEncoding_withNoSupportedEncoder_throws() { assertThrows( TransformationException.class, () -> - new DefaultEncoderFactory(context) + new DefaultEncoderFactory.Builder(context) + .build() .createForVideoEncoding( requestedVideoFormat, /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H265))); @@ -138,10 +142,9 @@ public void createForVideoEncoding_withNoAvailableEncoderFromEncoderSelector_thr assertThrows( TransformationException.class, () -> - new DefaultEncoderFactory( - context, - /* videoEncoderSelector= */ mimeType -> ImmutableList.of(), - /* enableFallback= */ true) + new DefaultEncoderFactory.Builder(context) + .setVideoEncoderSelector(mimeType -> ImmutableList.of()) + .build() .createForVideoEncoding( requestedVideoFormat, /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264))); diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/TransformerEndToEndTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/TransformerEndToEndTest.java index 3395270373..5f883b5b88 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/TransformerEndToEndTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/TransformerEndToEndTest.java @@ -751,7 +751,7 @@ private Transformer.Builder createTransformerBuilder(boolean enableFallback) { .setClock(clock) .setMuxerFactory(new TestMuxerFactory()) .setEncoderFactory( - new DefaultEncoderFactory(context, EncoderSelector.DEFAULT, enableFallback)); + new DefaultEncoderFactory.Builder(context).setEnableFallback(enableFallback).build()); } private static void createEncodersAndDecoders() { From 709224fb1ed3a1dab1433a5dc7fbb33a04eecaae Mon Sep 17 00:00:00 2001 From: hschlueter Date: Thu, 23 Jun 2022 13:13:56 +0100 Subject: [PATCH 39/73] Rename FrameProcessorChain to GlEffectsFrameProcessor. This change is just renaming. There is no functional change intended. The FrameProcessor interface will be created in a follow-up. PiperOrigin-RevId: 456741628 --- .../media3/transformer/BitmapTestUtil.java | 2 +- .../media3/transformer/CropPixelTest.java | 2 +- ... => GlEffectsFrameProcessorPixelTest.java} | 48 +++++++++--------- ...atrixTransformationProcessorPixelTest.java | 2 +- .../transformer/PresentationPixelTest.java | 2 +- .../ChainingGlTextureProcessorListener.java | 10 ++-- ...lMatrixTransformationProcessorWrapper.java | 14 +++--- .../FrameProcessingTaskExecutor.java | 8 +-- ...hain.java => GlEffectsFrameProcessor.java} | 49 ++++++++++--------- .../transformer/TransformationException.java | 8 +-- .../VideoTranscodingSamplePipeline.java | 22 ++++----- ...hainingGlTextureProcessorListenerTest.java | 10 ++-- 12 files changed, 91 insertions(+), 86 deletions(-) rename libraries/transformer/src/androidTest/java/androidx/media3/transformer/{FrameProcessorChainPixelTest.java => GlEffectsFrameProcessorPixelTest.java} (93%) rename libraries/transformer/src/main/java/androidx/media3/transformer/{FrameProcessorChain.java => GlEffectsFrameProcessor.java} (92%) diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/BitmapTestUtil.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/BitmapTestUtil.java index 2f38910bd8..585fe0ef2f 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/BitmapTestUtil.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/BitmapTestUtil.java @@ -39,7 +39,7 @@ import java.nio.ByteBuffer; /** - * Utilities for instrumentation tests for the {@link FrameProcessorChain} and {@link + * Utilities for instrumentation tests for the {@link GlEffectsFrameProcessor} and {@link * SingleFrameGlTextureProcessor SingleFrameGlTextureProcessors}. */ public class BitmapTestUtil { diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/CropPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/CropPixelTest.java index b0de6571fb..fe85fb8d88 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/CropPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/CropPixelTest.java @@ -41,7 +41,7 @@ *

    Expected images are taken from an emulator, so tests on different emulators or physical * devices may fail. To test on other devices, please increase the {@link * BitmapTestUtil#MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE} and/or inspect the saved output bitmaps - * as recommended in {@link FrameProcessorChainPixelTest}. + * as recommended in {@link GlEffectsFrameProcessorPixelTest}. */ @RunWith(AndroidJUnit4.class) public final class CropPixelTest { diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java similarity index 93% rename from libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java rename to libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java index 880c36bdf3..4cc38115bb 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/FrameProcessorChainPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java @@ -46,7 +46,7 @@ import org.junit.runner.RunWith; /** - * Pixel test for frame processing via {@link FrameProcessorChain}. + * Pixel test for frame processing via {@link GlEffectsFrameProcessor}. * *

    Expected images are taken from an emulator, so tests on different emulators or physical * devices may fail. To test on other devices, please increase the {@link @@ -54,7 +54,7 @@ * bitmaps. */ @RunWith(AndroidJUnit4.class) -public final class FrameProcessorChainPixelTest { +public final class GlEffectsFrameProcessorPixelTest { public static final String ORIGINAL_PNG_ASSET_PATH = "media/bitmap/sample_mp4_first_frame/original.png"; public static final String SCALE_WIDE_PNG_ASSET_PATH = @@ -79,8 +79,9 @@ public final class FrameProcessorChainPixelTest { /** Timeout for dequeueing buffers from the codec, in microseconds. */ private static final int DEQUEUE_TIMEOUT_US = 5_000_000; /** - * Time to wait for the decoded frame to populate the {@link FrameProcessorChain}'s input surface - * and the {@link FrameProcessorChain} to finish processing the frame, in milliseconds. + * Time to wait for the decoded frame to populate the {@link GlEffectsFrameProcessor} instance's + * input surface and the {@link GlEffectsFrameProcessor} to finish processing the frame, in + * milliseconds. */ private static final int FRAME_PROCESSING_WAIT_MS = 5000; /** The ratio of width over height, for each pixel in a frame. */ @@ -90,14 +91,14 @@ public final class FrameProcessorChainPixelTest { new AtomicReference<>(); private @MonotonicNonNull MediaFormat mediaFormat; - private @MonotonicNonNull FrameProcessorChain frameProcessorChain; + private @MonotonicNonNull GlEffectsFrameProcessor glEffectsFrameProcessor; private volatile @MonotonicNonNull ImageReader outputImageReader; private volatile boolean frameProcessingEnded; @After public void release() { - if (frameProcessorChain != null) { - frameProcessorChain.release(); + if (glEffectsFrameProcessor != null) { + glEffectsFrameProcessor.release(); } } @@ -321,8 +322,8 @@ public void processData_withTwoWrappedScaleToFitTransformations_producesExpected /** * Set up and prepare the first frame from an input video, as well as relevant test - * infrastructure. The frame will be sent towards the {@link FrameProcessorChain}, and may be - * accessed on the {@link FrameProcessorChain}'s output {@code outputImageReader}. + * infrastructure. The frame will be sent towards the {@link GlEffectsFrameProcessor}, and output + * may be accessed on the {@code outputImageReader}. * * @param pixelWidthHeightRatio The ratio of width over height for each pixel. * @param effects The {@link GlEffect GlEffects} to apply to the input frame. @@ -350,11 +351,11 @@ private void setUpAndPrepareFirstFrame(float pixelWidthHeightRatio, ListThis ensures that {@link FrameProcessorChain} uses a separate {@link GlTextureProcessor} for - * the wrapped {@link GlEffect} rather than merging it with preceding or subsequent {@link + *

    This ensures that {@link GlEffectsFrameProcessor} uses a separate {@link GlTextureProcessor} + * for the wrapped {@link GlEffect} rather than merging it with preceding or subsequent {@link * GlEffect} instances and applying them in one combined {@link GlTextureProcessor}. */ private static final class GlEffectWrapper implements GlEffect { diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/MatrixTransformationProcessorPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/MatrixTransformationProcessorPixelTest.java index 3255c093cb..971403d5ae 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/MatrixTransformationProcessorPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/MatrixTransformationProcessorPixelTest.java @@ -40,7 +40,7 @@ *

    Expected images are taken from an emulator, so tests on different emulators or physical * devices may fail. To test on other devices, please increase the {@link * BitmapTestUtil#MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE} and/or inspect the saved output bitmaps - * as recommended in {@link FrameProcessorChainPixelTest}. + * as recommended in {@link GlEffectsFrameProcessorPixelTest}. */ @RunWith(AndroidJUnit4.class) public final class MatrixTransformationProcessorPixelTest { diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationPixelTest.java index 53bbbea9ee..e0a0facc6b 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/PresentationPixelTest.java @@ -42,7 +42,7 @@ *

    Expected images are taken from an emulator, so tests on different emulators or physical * devices may fail. To test on other devices, please increase the {@link * BitmapTestUtil#MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE} and/or inspect the saved output bitmaps - * as recommended in {@link FrameProcessorChainPixelTest}. + * as recommended in {@link GlEffectsFrameProcessorPixelTest}. */ @RunWith(AndroidJUnit4.class) public final class PresentationPixelTest { diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/ChainingGlTextureProcessorListener.java b/libraries/transformer/src/main/java/androidx/media3/transformer/ChainingGlTextureProcessorListener.java index 3017107b2f..b4d3b43bdf 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/ChainingGlTextureProcessorListener.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/ChainingGlTextureProcessorListener.java @@ -31,7 +31,7 @@ @Nullable private final GlTextureProcessor previousGlTextureProcessor; @Nullable private final GlTextureProcessor nextGlTextureProcessor; private final FrameProcessingTaskExecutor frameProcessingTaskExecutor; - private final FrameProcessorChain.Listener frameProcessorChainListener; + private final GlEffectsFrameProcessor.Listener frameProcessorListener; private final Queue> pendingFrames; /** @@ -45,18 +45,18 @@ * OpenGL calls. All calls to the previous/next {@link GlTextureProcessor} will be executed by * the {@link FrameProcessingTaskExecutor}. The caller is responsible for releasing the {@link * FrameProcessingTaskExecutor}. - * @param frameProcessorChainListener The {@link FrameProcessorChain.Listener} to forward + * @param frameProcessorListener The {@link GlEffectsFrameProcessor.Listener} to forward * exceptions to. */ public ChainingGlTextureProcessorListener( @Nullable GlTextureProcessor previousGlTextureProcessor, @Nullable GlTextureProcessor nextGlTextureProcessor, FrameProcessingTaskExecutor frameProcessingTaskExecutor, - FrameProcessorChain.Listener frameProcessorChainListener) { + GlEffectsFrameProcessor.Listener frameProcessorListener) { this.previousGlTextureProcessor = previousGlTextureProcessor; this.nextGlTextureProcessor = nextGlTextureProcessor; this.frameProcessingTaskExecutor = frameProcessingTaskExecutor; - this.frameProcessorChainListener = frameProcessorChainListener; + this.frameProcessorListener = frameProcessorListener; pendingFrames = new ArrayDeque<>(); } @@ -101,6 +101,6 @@ public void onOutputStreamEnded() { @Override public void onFrameProcessingError(FrameProcessingException e) { - frameProcessorChainListener.onFrameProcessingError(e); + frameProcessorListener.onFrameProcessingError(e); } } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java index 84040ab6e1..e936495398 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java @@ -47,7 +47,7 @@ * dimensions specified by the provided {@link SurfaceInfo}. * *

    This wrapper is used for the final {@link GlTextureProcessor} instance in the chain of {@link - * GlTextureProcessor} instances used by {@link FrameProcessorChain}. + * GlTextureProcessor} instances used by {@link GlEffectsFrameProcessor}. */ /* package */ final class FinalMatrixTransformationProcessorWrapper implements GlTextureProcessor { @@ -60,7 +60,7 @@ private final SurfaceInfo.Provider outputSurfaceProvider; private final long streamOffsetUs; private final Transformer.DebugViewProvider debugViewProvider; - private final FrameProcessorChain.Listener frameProcessorChainListener; + private final GlEffectsFrameProcessor.Listener frameProcessorListener; private final boolean enableExperimentalHdrEditing; private int inputWidth; @@ -78,7 +78,7 @@ public FinalMatrixTransformationProcessorWrapper( ImmutableList matrixTransformations, SurfaceInfo.Provider outputSurfaceProvider, long streamOffsetUs, - FrameProcessorChain.Listener listener, + GlEffectsFrameProcessor.Listener frameProcessorListener, Transformer.DebugViewProvider debugViewProvider, boolean enableExperimentalHdrEditing) { this.context = context; @@ -88,7 +88,7 @@ public FinalMatrixTransformationProcessorWrapper( this.outputSurfaceProvider = outputSurfaceProvider; this.streamOffsetUs = streamOffsetUs; this.debugViewProvider = debugViewProvider; - this.frameProcessorChainListener = listener; + this.frameProcessorListener = frameProcessorListener; this.enableExperimentalHdrEditing = enableExperimentalHdrEditing; } @@ -97,7 +97,7 @@ public FinalMatrixTransformationProcessorWrapper( * *

    The {@code FinalMatrixTransformationProcessorWrapper} will only call {@link * Listener#onInputFrameProcessed(TextureInfo)}. Other events are handled via the {@link - * FrameProcessorChain.Listener} passed to the constructor. + * GlEffectsFrameProcessor.Listener} passed to the constructor. */ @Override public void setListener(Listener listener) { @@ -130,7 +130,7 @@ public boolean maybeQueueInputFrame(TextureInfo inputTexture, long presentationT /* presentationTimeNs= */ (presentationTimeUs + streamOffsetUs) * 1000); EGL14.eglSwapBuffers(eglDisplay, outputEglSurface); } catch (FrameProcessingException | GlUtil.GlException e) { - frameProcessorChainListener.onFrameProcessingError( + frameProcessorListener.onFrameProcessingError( FrameProcessingException.from(e, presentationTimeUs)); } @@ -247,7 +247,7 @@ public void releaseOutputFrame(TextureInfo outputTexture) { @Override public void signalEndOfInputStream() { - frameProcessorChainListener.onFrameProcessingEnded(); + frameProcessorListener.onFrameProcessingEnded(); } @Override diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessingTaskExecutor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessingTaskExecutor.java index d228494831..7f3399532c 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessingTaskExecutor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessingTaskExecutor.java @@ -30,19 +30,19 @@ * instances. * *

    The wrapper handles calling {@link - * FrameProcessorChain.Listener#onFrameProcessingError(FrameProcessingException)} for errors that - * occur during these tasks. + * GlEffectsFrameProcessor.Listener#onFrameProcessingError(FrameProcessingException)} for errors + * that occur during these tasks. */ /* package */ final class FrameProcessingTaskExecutor { private final ExecutorService singleThreadExecutorService; - private final FrameProcessorChain.Listener listener; + private final GlEffectsFrameProcessor.Listener listener; private final ConcurrentLinkedQueue> futures; private final AtomicBoolean shouldCancelTasks; /** Creates a new instance. */ public FrameProcessingTaskExecutor( - ExecutorService singleThreadExecutorService, FrameProcessorChain.Listener listener) { + ExecutorService singleThreadExecutorService, GlEffectsFrameProcessor.Listener listener) { this.singleThreadExecutorService = singleThreadExecutorService; this.listener = listener; diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java similarity index 92% rename from libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java rename to libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java index 3ebc57741d..38917b99b5 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessorChain.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java @@ -37,7 +37,7 @@ import java.util.concurrent.atomic.AtomicInteger; /** - * {@code FrameProcessorChain} applies changes to individual video frames. + * {@code GlEffectsFrameProcessor} applies changes to individual video frames. * *

    Input becomes available on its {@linkplain #getInputSurface() input surface} asynchronously * and is processed on a background thread as it becomes available. All input frames should be @@ -47,20 +47,21 @@ * Listener, float, int, int, long, List, SurfaceInfo.Provider, Transformer.DebugViewProvider, * boolean) output surface}. */ -// TODO(b/227625423): Factor out FrameProcessor interface and rename this class to GlFrameProcessor. -/* package */ final class FrameProcessorChain { +// TODO(b/227625423): Factor out FrameProcessor interface +/* package */ final class GlEffectsFrameProcessor { /** * Listener for asynchronous frame processing events. * - *

    This listener is only called from the {@link FrameProcessorChain}'s background thread. + *

    This listener is only called from the {@link GlEffectsFrameProcessor} instance's background + * thread. */ public interface Listener { /** * Called when an exception occurs during asynchronous frame processing. * *

    If an error occurred, consuming and producing further frames will not work as expected and - * the {@link FrameProcessorChain} should be released. + * the {@link GlEffectsFrameProcessor} should be released. */ void onFrameProcessingError(FrameProcessingException exception); @@ -86,9 +87,9 @@ public interface Listener { * @throws FrameProcessingException If reading shader files fails, or an OpenGL error occurs while * creating and configuring the OpenGL components. */ - public static FrameProcessorChain create( + public static GlEffectsFrameProcessor create( Context context, - FrameProcessorChain.Listener listener, + GlEffectsFrameProcessor.Listener listener, float pixelWidthHeightRatio, int inputWidth, int inputHeight, @@ -103,10 +104,10 @@ public static FrameProcessorChain create( ExecutorService singleThreadExecutorService = Util.newSingleThreadExecutor(THREAD_NAME); - Future frameProcessorChainFuture = + Future glFrameProcessorFuture = singleThreadExecutorService.submit( () -> - createOpenGlObjectsAndFrameProcessorChain( + createOpenGlObjectsAndFrameProcessor( context, listener, pixelWidthHeightRatio, @@ -120,7 +121,7 @@ public static FrameProcessorChain create( singleThreadExecutorService)); try { - return frameProcessorChainFuture.get(); + return glFrameProcessorFuture.get(); } catch (ExecutionException e) { throw new FrameProcessingException(e); } catch (InterruptedException e) { @@ -132,15 +133,15 @@ public static FrameProcessorChain create( /** * Creates the OpenGL context, surfaces, textures, and framebuffers, initializes {@link * GlTextureProcessor} instances corresponding to the {@link GlEffect} instances, and returns a - * new {@code FrameProcessorChain}. + * new {@code GlEffectsFrameProcessor}. * *

    This method must be executed using the {@code singleThreadExecutorService}, as later OpenGL * commands will be called on that thread. */ @WorkerThread - private static FrameProcessorChain createOpenGlObjectsAndFrameProcessorChain( + private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( Context context, - FrameProcessorChain.Listener listener, + GlEffectsFrameProcessor.Listener listener, float pixelWidthHeightRatio, int inputWidth, int inputHeight, @@ -196,7 +197,7 @@ private static FrameProcessorChain createOpenGlObjectsAndFrameProcessorChain( chainTextureProcessorsWithListeners( externalTextureProcessor, textureProcessors, frameProcessingTaskExecutor, listener); - return new FrameProcessorChain( + return new GlEffectsFrameProcessor( eglDisplay, eglContext, frameProcessingTaskExecutor, @@ -244,7 +245,7 @@ private static ImmutableList getGlTextureProcessorsForGlEffe ImmutableList.Builder matrixTransformationListBuilder, SurfaceInfo.Provider outputSurfaceProvider, long streamOffsetUs, - FrameProcessorChain.Listener listener, + GlEffectsFrameProcessor.Listener listener, Transformer.DebugViewProvider debugViewProvider, boolean enableExperimentalHdrEditing) throws FrameProcessingException { @@ -289,7 +290,7 @@ private static void chainTextureProcessorsWithListeners( ExternalTextureProcessor externalTextureProcessor, ImmutableList textureProcessors, FrameProcessingTaskExecutor frameProcessingTaskExecutor, - FrameProcessorChain.Listener listener) { + GlEffectsFrameProcessor.Listener listener) { externalTextureProcessor.setListener( new ChainingGlTextureProcessorListener( /* previousGlTextureProcessor= */ null, @@ -312,8 +313,8 @@ private static void chainTextureProcessorsWithListeners( } } - private static final String TAG = "FrameProcessorChain"; - private static final String THREAD_NAME = "Transformer:FrameProcessorChain"; + private static final String TAG = "GlEffectsFrameProcessor"; + private static final String THREAD_NAME = "Transformer:GlEffectsFrameProcessor"; private static final long RELEASE_WAIT_TIME_MS = 100; private final EGLDisplay eglDisplay; @@ -341,7 +342,7 @@ private static void chainTextureProcessorsWithListeners( private boolean inputStreamEnded; - private FrameProcessorChain( + private GlEffectsFrameProcessor( EGLDisplay eglDisplay, EGLContext eglContext, FrameProcessingTaskExecutor frameProcessingTaskExecutor, @@ -374,9 +375,9 @@ public Surface getInputSurface() { } /** - * Informs the {@code FrameProcessorChain} that a frame will be queued to its input surface. + * Informs the {@code GlEffectsFrameProcessor} that a frame will be queued to its input surface. * - *

    Must be called before rendering a frame to the frame processor chain's input surface. + *

    Must be called before rendering a frame to the frame processor's input surface. * * @throws IllegalStateException If called after {@link #signalEndOfInputStream()}. */ @@ -394,7 +395,7 @@ public int getPendingInputFrameCount() { } /** - * Informs the {@code FrameProcessorChain} that no further input frames should be accepted. + * Informs the {@code GlEffectsFrameProcessor} that no further input frames should be accepted. * * @throws IllegalStateException If called more than once. */ @@ -407,12 +408,12 @@ public void signalEndOfInputStream() { /** * Releases all resources. * - *

    If the frame processor chain is released before it has {@linkplain + *

    If the frame processor is released before it has {@linkplain * Listener#onFrameProcessingEnded() ended}, it will attempt to cancel processing any input frames * that have already become available. Input frames that become available after release are * ignored. * - *

    This method blocks until all OpenGL resources are released or releasing times out. + *

    This method blocks until all resources are released or releasing times out. */ public void release() { try { diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformationException.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformationException.java index aad804edec..803ab0d53f 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformationException.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformationException.java @@ -274,15 +274,15 @@ public static TransformationException createForAudioProcessor( } /** - * Creates an instance for a {@link FrameProcessorChain} related exception. + * Creates an instance for a {@link GlEffectsFrameProcessor} related exception. * * @param cause The cause of the failure. * @param errorCode See {@link #errorCode}. * @return The created instance. */ - /* package */ static TransformationException createForFrameProcessorChain( - Throwable cause, int errorCode) { - return new TransformationException("FrameProcessorChain error", cause, errorCode); + /* package */ static TransformationException createForFrameProcessingException( + FrameProcessingException cause, int errorCode) { + return new TransformationException("Frame processing error", cause, errorCode); } /** diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java index 3bdb16f73e..99703bc8c1 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java @@ -44,7 +44,7 @@ private final Codec decoder; private final ArrayList decodeOnlyPresentationTimestamps; - private final FrameProcessorChain frameProcessorChain; + private final GlEffectsFrameProcessor frameProcessor; private final EncoderWrapper encoderWrapper; private final DecoderInputBuffer encoderOutputBuffer; @@ -99,14 +99,14 @@ public VideoTranscodingSamplePipeline( asyncErrorListener); try { - frameProcessorChain = - FrameProcessorChain.create( + frameProcessor = + GlEffectsFrameProcessor.create( context, - new FrameProcessorChain.Listener() { + new GlEffectsFrameProcessor.Listener() { @Override public void onFrameProcessingError(FrameProcessingException exception) { asyncErrorListener.onTransformationException( - TransformationException.createForFrameProcessorChain( + TransformationException.createForFrameProcessingException( exception, TransformationException.ERROR_CODE_GL_PROCESSING_FAILED)); } @@ -128,14 +128,14 @@ public void onFrameProcessingEnded() { debugViewProvider, transformationRequest.enableHdrEditing); } catch (FrameProcessingException e) { - throw TransformationException.createForFrameProcessorChain( + throw TransformationException.createForFrameProcessingException( e, TransformationException.ERROR_CODE_GL_INIT_FAILED); } decoder = decoderFactory.createForVideoDecoding( inputFormat, - frameProcessorChain.getInputSurface(), + frameProcessor.getInputSurface(), transformationRequest.enableRequestSdrToneMapping); maxPendingFrameCount = decoder.getMaxPendingFrameCount(); } @@ -165,7 +165,7 @@ public boolean processData() throws TransformationException { processedData = true; } if (decoder.isEnded()) { - frameProcessorChain.signalEndOfInputStream(); + frameProcessor.signalEndOfInputStream(); } // If the decoder produced output, signal that it may be possible to process data again. return processedData; @@ -202,7 +202,7 @@ public boolean isEnded() { @Override public void release() { - frameProcessorChain.release(); + frameProcessor.release(); decoder.release(); encoderWrapper.release(); } @@ -255,11 +255,11 @@ private boolean maybeProcessDecoderOutput() throws TransformationException { } if (maxPendingFrameCount != Codec.UNLIMITED_PENDING_FRAME_COUNT - && frameProcessorChain.getPendingInputFrameCount() == maxPendingFrameCount) { + && frameProcessor.getPendingInputFrameCount() == maxPendingFrameCount) { return false; } - frameProcessorChain.registerInputFrame(); + frameProcessor.registerInputFrame(); decoder.releaseOutputBuffer(/* render= */ true); return true; } diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/ChainingGlTextureProcessorListenerTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/ChainingGlTextureProcessorListenerTest.java index 9c74cb9306..39bbf1b3d4 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/ChainingGlTextureProcessorListenerTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/ChainingGlTextureProcessorListenerTest.java @@ -31,11 +31,11 @@ public final class ChainingGlTextureProcessorListenerTest { private static final long EXECUTOR_WAIT_TIME_MS = 100; - private final FrameProcessorChain.Listener mockFrameProcessorChainListener = - mock(FrameProcessorChain.Listener.class); + private final GlEffectsFrameProcessor.Listener mockframeProcessorListener = + mock(GlEffectsFrameProcessor.Listener.class); private final FrameProcessingTaskExecutor frameProcessingTaskExecutor = new FrameProcessingTaskExecutor( - Util.newSingleThreadExecutor("Test"), mockFrameProcessorChainListener); + Util.newSingleThreadExecutor("Test"), mockframeProcessorListener); private final GlTextureProcessor mockPreviousGlTextureProcessor = mock(GlTextureProcessor.class); private final FakeGlTextureProcessor fakeNextGlTextureProcessor = spy(new FakeGlTextureProcessor()); @@ -44,7 +44,7 @@ public final class ChainingGlTextureProcessorListenerTest { mockPreviousGlTextureProcessor, fakeNextGlTextureProcessor, frameProcessingTaskExecutor, - mockFrameProcessorChainListener); + mockframeProcessorListener); @After public void release() throws InterruptedException { @@ -57,7 +57,7 @@ public void onFrameProcessingError_callsListener() { chainingGlTextureProcessorListener.onFrameProcessingError(exception); - verify(mockFrameProcessorChainListener, times(1)).onFrameProcessingError(exception); + verify(mockframeProcessorListener, times(1)).onFrameProcessingError(exception); } @Test From 1d2ad39a4d4778124a6b87c3d3a7a4415eeb8865 Mon Sep 17 00:00:00 2001 From: olly Date: Thu, 23 Jun 2022 14:31:27 +0100 Subject: [PATCH 40/73] Inform ProgressiveMediaPeriod of known length earlier PiperOrigin-RevId: 456753343 --- .../source/ProgressiveMediaPeriod.java | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/ProgressiveMediaPeriod.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/ProgressiveMediaPeriod.java index 026917b9a0..1f83a065fc 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/ProgressiveMediaPeriod.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/ProgressiveMediaPeriod.java @@ -135,7 +135,7 @@ interface Listener { private boolean seenFirstTrackSelection; private boolean notifyDiscontinuity; private int enabledTrackCount; - private long length; + private boolean isLengthKnown; private long lastSeekPositionUs; private long pendingResetPositionUs; @@ -201,7 +201,6 @@ public ProgressiveMediaPeriod( sampleQueueTrackIds = new TrackId[0]; sampleQueues = new SampleQueue[0]; pendingResetPositionUs = C.TIME_UNSET; - length = C.LENGTH_UNSET; durationUs = C.TIME_UNSET; dataType = C.DATA_TYPE_MEDIA; } @@ -578,7 +577,6 @@ public void onLoadCompleted( /* trackSelectionData= */ null, /* mediaStartTimeUs= */ loadable.seekTimeUs, durationUs); - copyLengthFromLoader(loadable); loadingFinished = true; Assertions.checkNotNull(callback).onContinueLoadingRequested(this); } @@ -607,7 +605,6 @@ public void onLoadCanceled( /* mediaStartTimeUs= */ loadable.seekTimeUs, durationUs); if (!released) { - copyLengthFromLoader(loadable); for (SampleQueue sampleQueue : sampleQueues) { sampleQueue.reset(); } @@ -624,7 +621,6 @@ public LoadErrorAction onLoadError( long loadDurationMs, IOException error, int errorCount) { - copyLengthFromLoader(loadable); StatsDataSource dataSource = loadable.dataSource; LoadEventInfo loadEventInfo = new LoadEventInfo( @@ -710,6 +706,10 @@ public void onUpstreamFormatChanged(Format format) { // Internal methods. + private void onLengthKnown() { + handler.post(() -> isLengthKnown = true); + } + private TrackOutput prepareTrackOutput(TrackId id) { int trackCount = sampleQueues.length; for (int i = 0; i < trackCount; i++) { @@ -733,7 +733,7 @@ private TrackOutput prepareTrackOutput(TrackId id) { private void setSeekMap(SeekMap seekMap) { this.seekMap = icyHeaders == null ? seekMap : new Unseekable(/* durationUs= */ C.TIME_UNSET); durationUs = seekMap.getDurationUs(); - isLive = length == C.LENGTH_UNSET && seekMap.getDurationUs() == C.TIME_UNSET; + isLive = !isLengthKnown && seekMap.getDurationUs() == C.TIME_UNSET; dataType = isLive ? C.DATA_TYPE_MEDIA_PROGRESSIVE_LIVE : C.DATA_TYPE_MEDIA; listener.onSourceInfoRefreshed(durationUs, seekMap.isSeekable(), isLive); if (!prepared) { @@ -789,12 +789,6 @@ private void maybeFinishPrepare() { Assertions.checkNotNull(callback).onPrepared(this); } - private void copyLengthFromLoader(ExtractingLoadable loadable) { - if (length == C.LENGTH_UNSET) { - length = loadable.length; - } - } - private void startLoading() { ExtractingLoadable loadable = new ExtractingLoadable( @@ -840,7 +834,7 @@ private void startLoading() { * retry. */ private boolean configureRetry(ExtractingLoadable loadable, int currentExtractedSampleCount) { - if (length != C.LENGTH_UNSET || (seekMap != null && seekMap.getDurationUs() != C.TIME_UNSET)) { + if (isLengthKnown || (seekMap != null && seekMap.getDurationUs() != C.TIME_UNSET)) { // We're playing an on-demand stream. Resume the current loadable, which will // request data starting from the point it left off. extractedSamplesCountAtStartOfLoad = currentExtractedSampleCount; @@ -970,7 +964,6 @@ public int skipData(long positionUs) { private boolean pendingExtractorSeek; private long seekTimeUs; private DataSpec dataSpec; - private long length; @Nullable private TrackOutput icyTrackOutput; private boolean seenIcyMetadata; @@ -988,7 +981,6 @@ public ExtractingLoadable( this.loadCondition = loadCondition; this.positionHolder = new PositionHolder(); this.pendingExtractorSeek = true; - this.length = C.LENGTH_UNSET; loadTaskId = LoadEventInfo.getNewId(); dataSpec = buildDataSpec(/* position= */ 0); } @@ -1007,9 +999,10 @@ public void load() throws IOException { try { long position = positionHolder.position; dataSpec = buildDataSpec(position); - length = dataSource.open(dataSpec); + long length = dataSource.open(dataSpec); if (length != C.LENGTH_UNSET) { length += position; + onLengthKnown(); } icyHeaders = IcyHeaders.parse(dataSource.getResponseHeaders()); DataSource extractorDataSource = dataSource; From 938d3c2e5b6f016f7075a3d2d162d37c1951d825 Mon Sep 17 00:00:00 2001 From: hschlueter Date: Thu, 23 Jun 2022 15:44:02 +0100 Subject: [PATCH 41/73] Disable flaky transformer emulator test on API 31. videoEncoderFormatUnsupported_completesWithError() has recently been flaky on API 31 emulators on presubmit because a different exception than the expected exception is thrown. This disables it on those emulators to reduce testing noise until the underlying problem is investigated and resolved. PiperOrigin-RevId: 456765512 --- .../media3/transformer/TransformerEndToEndTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java index c7e3cb4766..0fe2991479 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java @@ -24,6 +24,7 @@ import android.net.Uri; import androidx.media3.common.Format; import androidx.media3.common.MediaItem; +import androidx.media3.common.util.Util; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import java.util.List; @@ -109,6 +110,11 @@ public void clippedMedia_completesWithClippedDuration() throws Exception { @Test public void videoEncoderFormatUnsupported_completesWithError() { + // TODO(b/236943611): Re-enable this test after investigating flakiness. + if (Util.SDK_INT == 31) { + return; + } + Transformer transformer = new Transformer.Builder(context) .setEncoderFactory(new VideoUnsupportedEncoderFactory(context)) From f3893c146d5e4521b84af45551ea5fda4d9c66bd Mon Sep 17 00:00:00 2001 From: hschlueter Date: Thu, 23 Jun 2022 19:00:01 +0100 Subject: [PATCH 42/73] Extract FrameProcessor interface from GlEffectsFrameProcessor. PiperOrigin-RevId: 456814150 --- .../GlEffectsFrameProcessorPixelTest.java | 2 +- .../ChainingGlTextureProcessorListener.java | 7 +- ...lMatrixTransformationProcessorWrapper.java | 8 +- .../FrameProcessingTaskExecutor.java | 8 +- .../media3/transformer/FrameProcessor.java | 77 +++++++++++++++++++ .../transformer/GlEffectsFrameProcessor.java | 75 ++++-------------- .../VideoTranscodingSamplePipeline.java | 4 +- ...hainingGlTextureProcessorListenerTest.java | 4 +- 8 files changed, 107 insertions(+), 78 deletions(-) create mode 100644 libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessor.java diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java index 4cc38115bb..e77ae2dfa2 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java @@ -355,7 +355,7 @@ private void setUpAndPrepareFirstFrame(float pixelWidthHeightRatio, List> pendingFrames; /** @@ -45,14 +45,13 @@ * OpenGL calls. All calls to the previous/next {@link GlTextureProcessor} will be executed by * the {@link FrameProcessingTaskExecutor}. The caller is responsible for releasing the {@link * FrameProcessingTaskExecutor}. - * @param frameProcessorListener The {@link GlEffectsFrameProcessor.Listener} to forward - * exceptions to. + * @param frameProcessorListener The {@link FrameProcessor.Listener} to forward exceptions to. */ public ChainingGlTextureProcessorListener( @Nullable GlTextureProcessor previousGlTextureProcessor, @Nullable GlTextureProcessor nextGlTextureProcessor, FrameProcessingTaskExecutor frameProcessingTaskExecutor, - GlEffectsFrameProcessor.Listener frameProcessorListener) { + FrameProcessor.Listener frameProcessorListener) { this.previousGlTextureProcessor = previousGlTextureProcessor; this.nextGlTextureProcessor = nextGlTextureProcessor; this.frameProcessingTaskExecutor = frameProcessingTaskExecutor; diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java index e936495398..996fce157b 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java @@ -47,7 +47,7 @@ * dimensions specified by the provided {@link SurfaceInfo}. * *

    This wrapper is used for the final {@link GlTextureProcessor} instance in the chain of {@link - * GlTextureProcessor} instances used by {@link GlEffectsFrameProcessor}. + * GlTextureProcessor} instances used by {@link FrameProcessor}. */ /* package */ final class FinalMatrixTransformationProcessorWrapper implements GlTextureProcessor { @@ -60,7 +60,7 @@ private final SurfaceInfo.Provider outputSurfaceProvider; private final long streamOffsetUs; private final Transformer.DebugViewProvider debugViewProvider; - private final GlEffectsFrameProcessor.Listener frameProcessorListener; + private final FrameProcessor.Listener frameProcessorListener; private final boolean enableExperimentalHdrEditing; private int inputWidth; @@ -78,7 +78,7 @@ public FinalMatrixTransformationProcessorWrapper( ImmutableList matrixTransformations, SurfaceInfo.Provider outputSurfaceProvider, long streamOffsetUs, - GlEffectsFrameProcessor.Listener frameProcessorListener, + FrameProcessor.Listener frameProcessorListener, Transformer.DebugViewProvider debugViewProvider, boolean enableExperimentalHdrEditing) { this.context = context; @@ -97,7 +97,7 @@ public FinalMatrixTransformationProcessorWrapper( * *

    The {@code FinalMatrixTransformationProcessorWrapper} will only call {@link * Listener#onInputFrameProcessed(TextureInfo)}. Other events are handled via the {@link - * GlEffectsFrameProcessor.Listener} passed to the constructor. + * FrameProcessor.Listener} passed to the constructor. */ @Override public void setListener(Listener listener) { diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessingTaskExecutor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessingTaskExecutor.java index 7f3399532c..86e03bd132 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessingTaskExecutor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessingTaskExecutor.java @@ -30,19 +30,19 @@ * instances. * *

    The wrapper handles calling {@link - * GlEffectsFrameProcessor.Listener#onFrameProcessingError(FrameProcessingException)} for errors - * that occur during these tasks. + * FrameProcessor.Listener#onFrameProcessingError(FrameProcessingException)} for errors that occur + * during these tasks. */ /* package */ final class FrameProcessingTaskExecutor { private final ExecutorService singleThreadExecutorService; - private final GlEffectsFrameProcessor.Listener listener; + private final FrameProcessor.Listener listener; private final ConcurrentLinkedQueue> futures; private final AtomicBoolean shouldCancelTasks; /** Creates a new instance. */ public FrameProcessingTaskExecutor( - ExecutorService singleThreadExecutorService, GlEffectsFrameProcessor.Listener listener) { + ExecutorService singleThreadExecutorService, FrameProcessor.Listener listener) { this.singleThreadExecutorService = singleThreadExecutorService; this.listener = listener; diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessor.java new file mode 100644 index 0000000000..a4338cd6a2 --- /dev/null +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessor.java @@ -0,0 +1,77 @@ +/* + * Copyright 2022 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 androidx.media3.transformer; + +import android.view.Surface; + +/** Interface for a frame processor that applies changes to individual video frames. */ +/* package */ interface FrameProcessor { + /** + * Listener for asynchronous frame processing events. + * + *

    All listener methods must be called from the same thread. + */ + interface Listener { + + /** + * Called when an exception occurs during asynchronous frame processing. + * + *

    If an error occurred, consuming and producing further frames will not work as expected and + * the {@link FrameProcessor} should be released. + */ + void onFrameProcessingError(FrameProcessingException exception); + + /** Called after the {@link FrameProcessor} has produced its final output frame. */ + void onFrameProcessingEnded(); + } + + /** Returns the input {@link Surface}. */ + Surface getInputSurface(); + + /** + * Informs the {@code FrameProcessor} that a frame will be queued to its input surface. + * + *

    Must be called before rendering a frame to the frame processor's input surface. + * + * @throws IllegalStateException If called after {@link #signalEndOfInputStream()}. + */ + void registerInputFrame(); + + /** + * Returns the number of input frames that have been {@linkplain #registerInputFrame() registered} + * but not processed off the {@linkplain #getInputSurface() input surface} yet. + */ + int getPendingInputFrameCount(); + + /** + * Informs the {@code FrameProcessor} that no further input frames should be accepted. + * + * @throws IllegalStateException If called more than once. + */ + void signalEndOfInputStream(); + + /** + * Releases all resources. + * + *

    If the frame processor is released before it has {@linkplain + * Listener#onFrameProcessingEnded() ended}, it will attempt to cancel processing any input frames + * that have already become available. Input frames that become available after release are + * ignored. + * + *

    This method blocks until all resources are released or releasing times out. + */ + void release(); +} diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java index 38917b99b5..fc73daeb36 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java @@ -37,37 +37,12 @@ import java.util.concurrent.atomic.AtomicInteger; /** - * {@code GlEffectsFrameProcessor} applies changes to individual video frames. - * - *

    Input becomes available on its {@linkplain #getInputSurface() input surface} asynchronously - * and is processed on a background thread as it becomes available. All input frames should be - * {@linkplain #registerInputFrame() registered} before they are rendered to the input surface. - * {@link #getPendingInputFrameCount()} can be used to check whether there are frames that have not - * been fully processed yet. Output is written to the provided {@linkplain #create(Context, - * Listener, float, int, int, long, List, SurfaceInfo.Provider, Transformer.DebugViewProvider, - * boolean) output surface}. + * A {@link FrameProcessor} implementation that applies {@link GlEffect} instances using OpenGL on a + * background thread. */ -// TODO(b/227625423): Factor out FrameProcessor interface -/* package */ final class GlEffectsFrameProcessor { - - /** - * Listener for asynchronous frame processing events. - * - *

    This listener is only called from the {@link GlEffectsFrameProcessor} instance's background - * thread. - */ - public interface Listener { - /** - * Called when an exception occurs during asynchronous frame processing. - * - *

    If an error occurred, consuming and producing further frames will not work as expected and - * the {@link GlEffectsFrameProcessor} should be released. - */ - void onFrameProcessingError(FrameProcessingException exception); - - /** Called after the frame processor has produced its final output frame. */ - void onFrameProcessingEnded(); - } +/* package */ final class GlEffectsFrameProcessor implements FrameProcessor { + // TODO(b/227625423): Replace factory method with setters once output surface and effects can be + // replaced. /** * Creates a new instance. @@ -89,7 +64,7 @@ public interface Listener { */ public static GlEffectsFrameProcessor create( Context context, - GlEffectsFrameProcessor.Listener listener, + FrameProcessor.Listener listener, float pixelWidthHeightRatio, int inputWidth, int inputHeight, @@ -141,7 +116,7 @@ public static GlEffectsFrameProcessor create( @WorkerThread private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( Context context, - GlEffectsFrameProcessor.Listener listener, + FrameProcessor.Listener listener, float pixelWidthHeightRatio, int inputWidth, int inputHeight, @@ -245,7 +220,7 @@ private static ImmutableList getGlTextureProcessorsForGlEffe ImmutableList.Builder matrixTransformationListBuilder, SurfaceInfo.Provider outputSurfaceProvider, long streamOffsetUs, - GlEffectsFrameProcessor.Listener listener, + FrameProcessor.Listener listener, Transformer.DebugViewProvider debugViewProvider, boolean enableExperimentalHdrEditing) throws FrameProcessingException { @@ -290,7 +265,7 @@ private static void chainTextureProcessorsWithListeners( ExternalTextureProcessor externalTextureProcessor, ImmutableList textureProcessors, FrameProcessingTaskExecutor frameProcessingTaskExecutor, - GlEffectsFrameProcessor.Listener listener) { + FrameProcessor.Listener listener) { externalTextureProcessor.setListener( new ChainingGlTextureProcessorListener( /* previousGlTextureProcessor= */ null, @@ -366,7 +341,7 @@ private GlEffectsFrameProcessor( inputSurfaceTextureTransformMatrix = new float[16]; } - /** Returns the input {@link Surface}. */ + @Override public Surface getInputSurface() { // TODO(b/227625423): Allow input surface to be recreated for input size change. inputSurfaceTexture.setOnFrameAvailableListener( @@ -374,47 +349,25 @@ public Surface getInputSurface() { return inputSurface; } - /** - * Informs the {@code GlEffectsFrameProcessor} that a frame will be queued to its input surface. - * - *

    Must be called before rendering a frame to the frame processor's input surface. - * - * @throws IllegalStateException If called after {@link #signalEndOfInputStream()}. - */ + @Override public void registerInputFrame() { checkState(!inputStreamEnded); pendingInputFrameCount.incrementAndGet(); } - /** - * Returns the number of input frames that have been {@linkplain #registerInputFrame() registered} - * but not processed off the {@linkplain #getInputSurface() input surface} yet. - */ + @Override public int getPendingInputFrameCount() { return pendingInputFrameCount.get(); } - /** - * Informs the {@code GlEffectsFrameProcessor} that no further input frames should be accepted. - * - * @throws IllegalStateException If called more than once. - */ + @Override public void signalEndOfInputStream() { checkState(!inputStreamEnded); inputStreamEnded = true; frameProcessingTaskExecutor.submit(this::processEndOfInputStream); } - /** - * Releases all resources. - * - *

    If the frame processor is released before it has {@linkplain - * Listener#onFrameProcessingEnded() ended}, it will attempt to cancel processing any input frames - * that have already become available. Input frames that become available after release are - * ignored. - * - *

    This method blocks until all resources are released or releasing times out. - */ + @Override public void release() { try { frameProcessingTaskExecutor.release( diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java index 99703bc8c1..aab980b4a5 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java @@ -44,7 +44,7 @@ private final Codec decoder; private final ArrayList decodeOnlyPresentationTimestamps; - private final GlEffectsFrameProcessor frameProcessor; + private final FrameProcessor frameProcessor; private final EncoderWrapper encoderWrapper; private final DecoderInputBuffer encoderOutputBuffer; @@ -102,7 +102,7 @@ public VideoTranscodingSamplePipeline( frameProcessor = GlEffectsFrameProcessor.create( context, - new GlEffectsFrameProcessor.Listener() { + new FrameProcessor.Listener() { @Override public void onFrameProcessingError(FrameProcessingException exception) { asyncErrorListener.onTransformationException( diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/ChainingGlTextureProcessorListenerTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/ChainingGlTextureProcessorListenerTest.java index 39bbf1b3d4..c48ca303bf 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/ChainingGlTextureProcessorListenerTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/ChainingGlTextureProcessorListenerTest.java @@ -31,8 +31,8 @@ public final class ChainingGlTextureProcessorListenerTest { private static final long EXECUTOR_WAIT_TIME_MS = 100; - private final GlEffectsFrameProcessor.Listener mockframeProcessorListener = - mock(GlEffectsFrameProcessor.Listener.class); + private final FrameProcessor.Listener mockframeProcessorListener = + mock(FrameProcessor.Listener.class); private final FrameProcessingTaskExecutor frameProcessingTaskExecutor = new FrameProcessingTaskExecutor( Util.newSingleThreadExecutor("Test"), mockframeProcessorListener); From 638c7587219103f19f5f54a157e455660b4de8f4 Mon Sep 17 00:00:00 2001 From: hmzh Date: Fri, 24 Jun 2022 10:50:27 +0100 Subject: [PATCH 43/73] Fix MIDI event array traversal in TrackChunk.java and TrackEvent.java - Corrected trackEventBytes traversal in TrackChunk where the array position marker was not incremented properly, leading to duplicate sample output. - Amended TrackEvent "Meta Event" parsing to account for the length of variable length bytes. - Fixed a bug with TrackEvent message parsing where message data was parsed incorrectly due to miscalculated length. PiperOrigin-RevId: 456967968 --- .../extractordumps/midi/Twinkle.mid.0.dump | 332 +++--------------- .../midi/Twinkle.mid.unknown_length.dump | 332 +++--------------- 2 files changed, 108 insertions(+), 556 deletions(-) diff --git a/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.0.dump b/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.0.dump index 9bbb94438c..5d1ded9a59 100644 --- a/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.0.dump @@ -4,8 +4,8 @@ seekMap: getPosition(0) = [[timeUs=0, position=0]] numberOfTracks = 1 track 0: - total output bytes = 264 - sample count = 86 + total output bytes = 96 + sample count = 30 format 0: sampleMimeType = audio/midi sample 0: @@ -21,335 +21,111 @@ track 0: flags = 1 data = length 3, hash FFFED75B sample 3: - time = 2108 + time = 128 flags = 1 - data = length 3, hash FFFED448 + data = length 3, hash FFFED733 sample 4: - time = 2148 + time = 128 flags = 1 - data = length 3, hash FFFE9730 + data = length 3, hash FFFED751 sample 5: - time = 2276 + time = 256 flags = 1 data = length 3, hash FFFED733 sample 6: - time = 4384 - flags = 1 - data = length 3, hash FFFECFEF - sample 7: - time = 4384 - flags = 1 - data = length 3, hash FFFECF7F - sample 8: - time = 4384 - flags = 1 - data = length 3, hash FFFED751 - sample 9: - time = 6492 - flags = 1 - data = length 3, hash FFFED312 - sample 10: - time = 6522 - flags = 1 - data = length 3, hash FFFE9730 - sample 11: - time = 6650 - flags = 1 - data = length 3, hash FFFED733 - sample 12: - time = 8758 - flags = 1 - data = length 3, hash FFFECFEF - sample 13: - time = 8758 - flags = 1 - data = length 3, hash FFFECF7F - sample 14: - time = 8758 + time = 256 flags = 1 data = length 3, hash FFFED839 - sample 15: - time = 10873 - flags = 1 - data = length 3, hash FFFED4E3 - sample 16: - time = 10918 - flags = 1 - data = length 3, hash FFFE9730 - sample 17: - time = 11046 + sample 7: + time = 384 flags = 1 data = length 3, hash FFFED80C - sample 18: - time = 13161 - flags = 1 - data = length 3, hash FFFECFEF - sample 19: - time = 13161 - flags = 1 - data = length 3, hash FFFECF7F - sample 20: - time = 13161 + sample 8: + time = 384 flags = 1 data = length 3, hash FFFED83E - sample 21: - time = 15276 - flags = 1 - data = length 3, hash FFFED57E - sample 22: - time = 15326 - flags = 1 - data = length 3, hash FFFE9730 - sample 23: - time = 15454 + sample 9: + time = 512 flags = 1 data = length 3, hash FFFED80C - sample 24: - time = 17569 - flags = 1 - data = length 3, hash FFFECFEF - sample 25: - time = 17569 - flags = 1 - data = length 3, hash FFFECF7F - sample 26: - time = 17569 + sample 10: + time = 512 flags = 1 data = length 3, hash FFFED877 - sample 27: - time = 19686 - flags = 1 - data = length 3, hash FFFED4E3 - sample 28: - time = 19731 - flags = 1 - data = length 3, hash FFFE9730 - sample 29: - time = 19859 + sample 11: + time = 640 flags = 1 data = length 3, hash FFFED84A - sample 30: - time = 21976 - flags = 1 - data = length 3, hash FFFECFEF - sample 31: - time = 21976 - flags = 1 - data = length 3, hash FFFECF7F - sample 32: - time = 21976 + sample 12: + time = 640 flags = 1 data = length 3, hash FFFED87C - sample 33: - time = 24093 - flags = 1 - data = length 3, hash FFFED57E - sample 34: - time = 24143 - flags = 1 - data = length 3, hash FFFE9730 - sample 35: - time = 24271 + sample 13: + time = 768 flags = 1 data = length 3, hash FFFED84A - sample 36: - time = 26388 - flags = 1 - data = length 3, hash FFFECFEF - sample 37: - time = 26388 - flags = 1 - data = length 3, hash FFFECF7F - sample 38: - time = 26388 + sample 14: + time = 768 flags = 1 data = length 3, hash FFFED82F - sample 39: - time = 28503 - flags = 1 - data = length 3, hash FFFED3AE - sample 40: - time = 28538 - flags = 1 - data = length 3, hash FFFE9AF1 - sample 41: - time = 28794 + sample 15: + time = 1024 flags = 1 data = length 3, hash FFFED80C - sample 42: - time = 30909 - flags = 1 - data = length 3, hash FFFECFEF - sample 43: - time = 30909 - flags = 1 - data = length 3, hash FFFECF7F - sample 44: - time = 30909 + sample 16: + time = 1024 flags = 1 data = length 3, hash FFFED800 - sample 45: - time = 33022 - flags = 1 - data = length 3, hash FFFED57E - sample 46: - time = 33072 - flags = 1 - data = length 3, hash FFFE9730 - sample 47: - time = 33200 + sample 17: + time = 1152 flags = 1 data = length 3, hash FFFED7CE - sample 48: - time = 35313 - flags = 1 - data = length 3, hash FFFECFEF - sample 49: - time = 35313 - flags = 1 - data = length 3, hash FFFECF7F - sample 50: - time = 35313 + sample 18: + time = 1152 flags = 1 data = length 3, hash FFFED7FB - sample 51: - time = 37426 - flags = 1 - data = length 3, hash FFFED4E3 - sample 52: - time = 37471 - flags = 1 - data = length 3, hash FFFE9730 - sample 53: - time = 37599 + sample 19: + time = 1280 flags = 1 data = length 3, hash FFFED7CE - sample 54: - time = 39712 - flags = 1 - data = length 3, hash FFFECFEF - sample 55: - time = 39712 - flags = 1 - data = length 3, hash FFFECF7F - sample 56: - time = 39712 + sample 20: + time = 1280 flags = 1 data = length 3, hash FFFED7E1 - sample 57: - time = 41824 - flags = 1 - data = length 3, hash FFFED63D - sample 58: - time = 41874 - flags = 1 - data = length 3, hash FFFED73F - sample 59: - time = 41938 + sample 21: + time = 1344 flags = 1 data = length 3, hash FFFED7AF - sample 60: - time = 44050 - flags = 1 - data = length 3, hash FFFED02F - sample 61: - time = 44050 - flags = 1 - data = length 3, hash FFFED73F - sample 62: - time = 44114 + sample 22: + time = 1408 flags = 1 data = length 3, hash FFFED7D7 - sample 63: - time = 46226 - flags = 1 - data = length 3, hash FFFED507 - sample 64: - time = 46266 - flags = 1 - data = length 3, hash FFFED73F - sample 65: - time = 46330 + sample 23: + time = 1472 flags = 1 data = length 3, hash FFFED7AF - sample 66: - time = 48442 - flags = 1 - data = length 3, hash FFFED02F - sample 67: - time = 48442 - flags = 1 - data = length 3, hash FFFED73F - sample 68: - time = 48506 + sample 24: + time = 1536 flags = 1 data = length 3, hash FFFED79E - sample 69: - time = 50616 - flags = 1 - data = length 3, hash FFFED5A2 - sample 70: - time = 50661 - flags = 1 - data = length 3, hash FFFED73F - sample 71: - time = 50725 + sample 25: + time = 1600 flags = 1 data = length 3, hash FFFED771 - sample 72: - time = 52835 - flags = 1 - data = length 3, hash FFFED02F - sample 73: - time = 52835 - flags = 1 - data = length 3, hash FFFED73F - sample 74: - time = 52899 + sample 26: + time = 1664 flags = 1 data = length 3, hash FFFED7A3 - sample 75: - time = 55009 - flags = 1 - data = length 3, hash FFFED63D - sample 76: - time = 55059 - flags = 1 - data = length 3, hash FFFED73F - sample 77: - time = 55123 + sample 27: + time = 1728 flags = 1 data = length 3, hash FFFED771 - sample 78: - time = 57233 - flags = 1 - data = length 3, hash FFFED02F - sample 79: - time = 57233 - flags = 1 - data = length 3, hash FFFED73F - sample 80: - time = 57297 + sample 28: + time = 1792 flags = 1 data = length 3, hash FFFED751 - sample 81: - time = 59405 - flags = 1 - data = length 3, hash FFFED313 - sample 82: - time = 59435 - flags = 1 - data = length 3, hash FFFE9AF1 - sample 83: - time = 59691 + sample 29: + time = 2048 flags = 1 data = length 3, hash FFFED733 - sample 84: - time = 61799 - flags = 1 - data = length 3, hash FFFECFEF - sample 85: - time = 61799 - flags = 1 - data = length 3, hash FFFECFEE tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.unknown_length.dump index 9bbb94438c..5d1ded9a59 100644 --- a/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.unknown_length.dump @@ -4,8 +4,8 @@ seekMap: getPosition(0) = [[timeUs=0, position=0]] numberOfTracks = 1 track 0: - total output bytes = 264 - sample count = 86 + total output bytes = 96 + sample count = 30 format 0: sampleMimeType = audio/midi sample 0: @@ -21,335 +21,111 @@ track 0: flags = 1 data = length 3, hash FFFED75B sample 3: - time = 2108 + time = 128 flags = 1 - data = length 3, hash FFFED448 + data = length 3, hash FFFED733 sample 4: - time = 2148 + time = 128 flags = 1 - data = length 3, hash FFFE9730 + data = length 3, hash FFFED751 sample 5: - time = 2276 + time = 256 flags = 1 data = length 3, hash FFFED733 sample 6: - time = 4384 - flags = 1 - data = length 3, hash FFFECFEF - sample 7: - time = 4384 - flags = 1 - data = length 3, hash FFFECF7F - sample 8: - time = 4384 - flags = 1 - data = length 3, hash FFFED751 - sample 9: - time = 6492 - flags = 1 - data = length 3, hash FFFED312 - sample 10: - time = 6522 - flags = 1 - data = length 3, hash FFFE9730 - sample 11: - time = 6650 - flags = 1 - data = length 3, hash FFFED733 - sample 12: - time = 8758 - flags = 1 - data = length 3, hash FFFECFEF - sample 13: - time = 8758 - flags = 1 - data = length 3, hash FFFECF7F - sample 14: - time = 8758 + time = 256 flags = 1 data = length 3, hash FFFED839 - sample 15: - time = 10873 - flags = 1 - data = length 3, hash FFFED4E3 - sample 16: - time = 10918 - flags = 1 - data = length 3, hash FFFE9730 - sample 17: - time = 11046 + sample 7: + time = 384 flags = 1 data = length 3, hash FFFED80C - sample 18: - time = 13161 - flags = 1 - data = length 3, hash FFFECFEF - sample 19: - time = 13161 - flags = 1 - data = length 3, hash FFFECF7F - sample 20: - time = 13161 + sample 8: + time = 384 flags = 1 data = length 3, hash FFFED83E - sample 21: - time = 15276 - flags = 1 - data = length 3, hash FFFED57E - sample 22: - time = 15326 - flags = 1 - data = length 3, hash FFFE9730 - sample 23: - time = 15454 + sample 9: + time = 512 flags = 1 data = length 3, hash FFFED80C - sample 24: - time = 17569 - flags = 1 - data = length 3, hash FFFECFEF - sample 25: - time = 17569 - flags = 1 - data = length 3, hash FFFECF7F - sample 26: - time = 17569 + sample 10: + time = 512 flags = 1 data = length 3, hash FFFED877 - sample 27: - time = 19686 - flags = 1 - data = length 3, hash FFFED4E3 - sample 28: - time = 19731 - flags = 1 - data = length 3, hash FFFE9730 - sample 29: - time = 19859 + sample 11: + time = 640 flags = 1 data = length 3, hash FFFED84A - sample 30: - time = 21976 - flags = 1 - data = length 3, hash FFFECFEF - sample 31: - time = 21976 - flags = 1 - data = length 3, hash FFFECF7F - sample 32: - time = 21976 + sample 12: + time = 640 flags = 1 data = length 3, hash FFFED87C - sample 33: - time = 24093 - flags = 1 - data = length 3, hash FFFED57E - sample 34: - time = 24143 - flags = 1 - data = length 3, hash FFFE9730 - sample 35: - time = 24271 + sample 13: + time = 768 flags = 1 data = length 3, hash FFFED84A - sample 36: - time = 26388 - flags = 1 - data = length 3, hash FFFECFEF - sample 37: - time = 26388 - flags = 1 - data = length 3, hash FFFECF7F - sample 38: - time = 26388 + sample 14: + time = 768 flags = 1 data = length 3, hash FFFED82F - sample 39: - time = 28503 - flags = 1 - data = length 3, hash FFFED3AE - sample 40: - time = 28538 - flags = 1 - data = length 3, hash FFFE9AF1 - sample 41: - time = 28794 + sample 15: + time = 1024 flags = 1 data = length 3, hash FFFED80C - sample 42: - time = 30909 - flags = 1 - data = length 3, hash FFFECFEF - sample 43: - time = 30909 - flags = 1 - data = length 3, hash FFFECF7F - sample 44: - time = 30909 + sample 16: + time = 1024 flags = 1 data = length 3, hash FFFED800 - sample 45: - time = 33022 - flags = 1 - data = length 3, hash FFFED57E - sample 46: - time = 33072 - flags = 1 - data = length 3, hash FFFE9730 - sample 47: - time = 33200 + sample 17: + time = 1152 flags = 1 data = length 3, hash FFFED7CE - sample 48: - time = 35313 - flags = 1 - data = length 3, hash FFFECFEF - sample 49: - time = 35313 - flags = 1 - data = length 3, hash FFFECF7F - sample 50: - time = 35313 + sample 18: + time = 1152 flags = 1 data = length 3, hash FFFED7FB - sample 51: - time = 37426 - flags = 1 - data = length 3, hash FFFED4E3 - sample 52: - time = 37471 - flags = 1 - data = length 3, hash FFFE9730 - sample 53: - time = 37599 + sample 19: + time = 1280 flags = 1 data = length 3, hash FFFED7CE - sample 54: - time = 39712 - flags = 1 - data = length 3, hash FFFECFEF - sample 55: - time = 39712 - flags = 1 - data = length 3, hash FFFECF7F - sample 56: - time = 39712 + sample 20: + time = 1280 flags = 1 data = length 3, hash FFFED7E1 - sample 57: - time = 41824 - flags = 1 - data = length 3, hash FFFED63D - sample 58: - time = 41874 - flags = 1 - data = length 3, hash FFFED73F - sample 59: - time = 41938 + sample 21: + time = 1344 flags = 1 data = length 3, hash FFFED7AF - sample 60: - time = 44050 - flags = 1 - data = length 3, hash FFFED02F - sample 61: - time = 44050 - flags = 1 - data = length 3, hash FFFED73F - sample 62: - time = 44114 + sample 22: + time = 1408 flags = 1 data = length 3, hash FFFED7D7 - sample 63: - time = 46226 - flags = 1 - data = length 3, hash FFFED507 - sample 64: - time = 46266 - flags = 1 - data = length 3, hash FFFED73F - sample 65: - time = 46330 + sample 23: + time = 1472 flags = 1 data = length 3, hash FFFED7AF - sample 66: - time = 48442 - flags = 1 - data = length 3, hash FFFED02F - sample 67: - time = 48442 - flags = 1 - data = length 3, hash FFFED73F - sample 68: - time = 48506 + sample 24: + time = 1536 flags = 1 data = length 3, hash FFFED79E - sample 69: - time = 50616 - flags = 1 - data = length 3, hash FFFED5A2 - sample 70: - time = 50661 - flags = 1 - data = length 3, hash FFFED73F - sample 71: - time = 50725 + sample 25: + time = 1600 flags = 1 data = length 3, hash FFFED771 - sample 72: - time = 52835 - flags = 1 - data = length 3, hash FFFED02F - sample 73: - time = 52835 - flags = 1 - data = length 3, hash FFFED73F - sample 74: - time = 52899 + sample 26: + time = 1664 flags = 1 data = length 3, hash FFFED7A3 - sample 75: - time = 55009 - flags = 1 - data = length 3, hash FFFED63D - sample 76: - time = 55059 - flags = 1 - data = length 3, hash FFFED73F - sample 77: - time = 55123 + sample 27: + time = 1728 flags = 1 data = length 3, hash FFFED771 - sample 78: - time = 57233 - flags = 1 - data = length 3, hash FFFED02F - sample 79: - time = 57233 - flags = 1 - data = length 3, hash FFFED73F - sample 80: - time = 57297 + sample 28: + time = 1792 flags = 1 data = length 3, hash FFFED751 - sample 81: - time = 59405 - flags = 1 - data = length 3, hash FFFED313 - sample 82: - time = 59435 - flags = 1 - data = length 3, hash FFFE9AF1 - sample 83: - time = 59691 + sample 29: + time = 2048 flags = 1 data = length 3, hash FFFED733 - sample 84: - time = 61799 - flags = 1 - data = length 3, hash FFFECFEF - sample 85: - time = 61799 - flags = 1 - data = length 3, hash FFFECFEE tracksEnded = true From 30c52c58f0772e43ca4e4639120d95f41ea8a9b5 Mon Sep 17 00:00:00 2001 From: hschlueter Date: Fri, 24 Jun 2022 16:31:31 +0100 Subject: [PATCH 44/73] Allow FrameProcessor input surface size changes. This will be useful for downgrading to a lower resolution during a slow preview and for processing slide-shows once sequential multi-asset editing is supported. PiperOrigin-RevId: 457017255 --- .../GlEffectsFrameProcessorPixelTest.java | 3 +- .../media3/transformer/FrameInfo.java | 37 ++++++++++++ .../media3/transformer/FrameProcessor.java | 11 +++- .../transformer/GlEffectsFrameProcessor.java | 58 +++++++++---------- .../VideoTranscodingSamplePipeline.java | 3 +- 5 files changed, 78 insertions(+), 34 deletions(-) create mode 100644 libraries/transformer/src/main/java/androidx/media3/transformer/FrameInfo.java diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java index e77ae2dfa2..910e724981 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java @@ -367,8 +367,6 @@ public void onFrameProcessingEnded() { } }, pixelWidthHeightRatio, - inputWidth, - inputHeight, /* streamOffsetUs= */ 0L, effects, /* outputSurfaceProvider= */ (requestedWidth, requestedHeight) -> { @@ -383,6 +381,7 @@ public void onFrameProcessingEnded() { }, Transformer.DebugViewProvider.NONE, /* enableExperimentalHdrEditing= */ false)); + glEffectsFrameProcessor.setInputFrameInfo(new FrameInfo(inputWidth, inputHeight)); glEffectsFrameProcessor.registerInputFrame(); // Queue the first video frame from the extractor. diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameInfo.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameInfo.java new file mode 100644 index 0000000000..0b0af7821b --- /dev/null +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameInfo.java @@ -0,0 +1,37 @@ +/* + * Copyright 2022 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 androidx.media3.transformer; + +import static androidx.media3.common.util.Assertions.checkArgument; + +/** Value class specifying information about a decoded video frame. */ +/* package */ class FrameInfo { + /** The width of the frame, in pixels. */ + public final int width; + /** The height of the frame, in pixels. */ + public final int height; + + // TODO(b/227625423): Add pixelWidthHeightRatio. + // TODO(b/227624622): Add color space information for HDR. + + public FrameInfo(int width, int height) { + checkArgument(width > 0, "width must be positive, but is: " + width); + checkArgument(height > 0, "height must be positive, but is: " + height); + + this.width = width; + this.height = height; + } +} diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessor.java index a4338cd6a2..db0a3bec7b 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessor.java @@ -41,12 +41,21 @@ interface Listener { /** Returns the input {@link Surface}. */ Surface getInputSurface(); + /** + * Sets information about the input frames. + * + *

    The new input information is applied from the next frame {@linkplain #registerInputFrame() + * registered} onwards. + */ + void setInputFrameInfo(FrameInfo inputFrameInfo); + /** * Informs the {@code FrameProcessor} that a frame will be queued to its input surface. * *

    Must be called before rendering a frame to the frame processor's input surface. * - * @throws IllegalStateException If called after {@link #signalEndOfInputStream()}. + * @throws IllegalStateException If called after {@link #signalEndOfInputStream()} or before + * {@link #setInputFrameInfo(FrameInfo)}. */ void registerInputFrame(); diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java index fc73daeb36..75b9b80d25 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java @@ -15,8 +15,8 @@ */ package androidx.media3.transformer; -import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkState; +import static androidx.media3.common.util.Assertions.checkStateNotNull; import android.content.Context; import android.graphics.SurfaceTexture; @@ -31,10 +31,11 @@ import androidx.media3.common.util.Util; import com.google.common.collect.ImmutableList; import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicInteger; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** * A {@link FrameProcessor} implementation that applies {@link GlEffect} instances using OpenGL on a @@ -51,8 +52,6 @@ * @param listener A {@link Listener}. * @param pixelWidthHeightRatio The ratio of width over height for each pixel. Pixels are expanded * by this ratio so that the output frame's pixels have a ratio of 1. - * @param inputWidth The input frame width, in pixels. - * @param inputHeight The input frame height, in pixels. * @param effects The {@link GlEffect GlEffects} to apply to each frame. * @param outputSurfaceProvider A {@link SurfaceInfo.Provider} managing the output {@link * Surface}. @@ -66,16 +65,12 @@ public static GlEffectsFrameProcessor create( Context context, FrameProcessor.Listener listener, float pixelWidthHeightRatio, - int inputWidth, - int inputHeight, long streamOffsetUs, List effects, SurfaceInfo.Provider outputSurfaceProvider, Transformer.DebugViewProvider debugViewProvider, boolean enableExperimentalHdrEditing) throws FrameProcessingException { - checkArgument(inputWidth > 0, "inputWidth must be positive"); - checkArgument(inputHeight > 0, "inputHeight must be positive"); ExecutorService singleThreadExecutorService = Util.newSingleThreadExecutor(THREAD_NAME); @@ -86,8 +81,6 @@ public static GlEffectsFrameProcessor create( context, listener, pixelWidthHeightRatio, - inputWidth, - inputHeight, streamOffsetUs, effects, outputSurfaceProvider, @@ -118,8 +111,6 @@ private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( Context context, FrameProcessor.Listener listener, float pixelWidthHeightRatio, - int inputWidth, - int inputHeight, long streamOffsetUs, List effects, SurfaceInfo.Provider outputSurfaceProvider, @@ -177,8 +168,7 @@ private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( eglContext, frameProcessingTaskExecutor, streamOffsetUs, - /* inputExternalTexture= */ new TextureInfo( - GlUtil.createExternalTexture(), /* fboId= */ C.INDEX_UNSET, inputWidth, inputHeight), + /* inputExternalTextureId= */ GlUtil.createExternalTexture(), externalTextureProcessor, textureProcessors); } @@ -300,21 +290,19 @@ private static void chainTextureProcessorsWithListeners( * timestamps, in microseconds. */ private final long streamOffsetUs; - /** - * Number of frames {@linkplain #registerInputFrame() registered} but not processed off the {@link - * #inputSurfaceTexture} yet. - */ - private final AtomicInteger pendingInputFrameCount; + /** Associated with an OpenGL external texture. */ private final SurfaceTexture inputSurfaceTexture; /** Wraps the {@link #inputSurfaceTexture}. */ private final Surface inputSurface; private final float[] inputSurfaceTextureTransformMatrix; - private final TextureInfo inputExternalTexture; + private final int inputExternalTextureId; private final ExternalTextureProcessor inputExternalTextureProcessor; private final ImmutableList textureProcessors; + private final ConcurrentLinkedQueue pendingInputFrames; + private @MonotonicNonNull FrameInfo nextInputFrameInfo; private boolean inputStreamEnded; private GlEffectsFrameProcessor( @@ -322,7 +310,7 @@ private GlEffectsFrameProcessor( EGLContext eglContext, FrameProcessingTaskExecutor frameProcessingTaskExecutor, long streamOffsetUs, - TextureInfo inputExternalTexture, + int inputExternalTextureId, ExternalTextureProcessor inputExternalTextureProcessor, ImmutableList textureProcessors) { checkState(!textureProcessors.isEmpty()); @@ -331,33 +319,40 @@ private GlEffectsFrameProcessor( this.eglContext = eglContext; this.frameProcessingTaskExecutor = frameProcessingTaskExecutor; this.streamOffsetUs = streamOffsetUs; - this.inputExternalTexture = inputExternalTexture; + this.inputExternalTextureId = inputExternalTextureId; this.inputExternalTextureProcessor = inputExternalTextureProcessor; this.textureProcessors = textureProcessors; - pendingInputFrameCount = new AtomicInteger(); - inputSurfaceTexture = new SurfaceTexture(inputExternalTexture.texId); + inputSurfaceTexture = new SurfaceTexture(inputExternalTextureId); inputSurface = new Surface(inputSurfaceTexture); inputSurfaceTextureTransformMatrix = new float[16]; + pendingInputFrames = new ConcurrentLinkedQueue<>(); } @Override public Surface getInputSurface() { - // TODO(b/227625423): Allow input surface to be recreated for input size change. inputSurfaceTexture.setOnFrameAvailableListener( surfaceTexture -> frameProcessingTaskExecutor.submit(this::processInputFrame)); return inputSurface; } + @Override + public void setInputFrameInfo(FrameInfo inputFrameInfo) { + nextInputFrameInfo = inputFrameInfo; + } + @Override public void registerInputFrame() { checkState(!inputStreamEnded); - pendingInputFrameCount.incrementAndGet(); + checkStateNotNull( + nextInputFrameInfo, "setInputFrameInfo must be called before registering input frames"); + + pendingInputFrames.add(nextInputFrameInfo); } @Override public int getPendingInputFrameCount() { - return pendingInputFrameCount.get(); + return pendingInputFrames.size(); } @Override @@ -401,10 +396,15 @@ private void processInputFrame() { long presentationTimeUs = inputFrameTimeNs / 1000 - streamOffsetUs; inputSurfaceTexture.getTransformMatrix(inputSurfaceTextureTransformMatrix); inputExternalTextureProcessor.setTextureTransformMatrix(inputSurfaceTextureTransformMatrix); + FrameInfo inputFrameInfo = pendingInputFrames.remove(); checkState( inputExternalTextureProcessor.maybeQueueInputFrame( - inputExternalTexture, presentationTimeUs)); - checkState(pendingInputFrameCount.getAndDecrement() > 0); + new TextureInfo( + inputExternalTextureId, + /* fboId= */ C.INDEX_UNSET, + inputFrameInfo.width, + inputFrameInfo.height), + presentationTimeUs)); // After the inputExternalTextureProcessor has produced an output frame, it is processed // asynchronously by the texture processors chained after it. } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java index aab980b4a5..5454e35147 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java @@ -120,8 +120,6 @@ public void onFrameProcessingEnded() { } }, inputFormat.pixelWidthHeightRatio, - /* inputWidth= */ decodedWidth, - /* inputHeight= */ decodedHeight, streamOffsetUs, effectsListBuilder.build(), /* outputSurfaceProvider= */ encoderWrapper, @@ -131,6 +129,7 @@ public void onFrameProcessingEnded() { throw TransformationException.createForFrameProcessingException( e, TransformationException.ERROR_CODE_GL_INIT_FAILED); } + frameProcessor.setInputFrameInfo(new FrameInfo(decodedWidth, decodedHeight)); decoder = decoderFactory.createForVideoDecoding( From 4819b28587c41e75c716ba3fa84fa84a8934c78e Mon Sep 17 00:00:00 2001 From: hschlueter Date: Fri, 24 Jun 2022 17:04:45 +0100 Subject: [PATCH 45/73] Rename setVideoFrameEffects to setVideoEffects. PiperOrigin-RevId: 457023382 --- .../demo/transformer/TransformerActivity.java | 2 +- .../media3/transformer/Transformer.java | 28 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java index 3e969ff938..2532d7fc7f 100644 --- a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java +++ b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java @@ -316,7 +316,7 @@ private Transformer createTransformer(@Nullable Bundle bundle, String filePath) if (selectedEffects[5]) { effects.add(MatrixTransformationFactory.createZoomInTransition()); } - transformerBuilder.setVideoFrameEffects(effects.build()); + transformerBuilder.setVideoEffects(effects.build()); } if (bundle.getBoolean(ConfigurationActivity.ENABLE_DEBUG_PREVIEW)) { diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java b/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java index 433b777a75..7c3036437f 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java @@ -103,7 +103,7 @@ public static final class Builder { private boolean removeVideo; private String containerMimeType; private TransformationRequest transformationRequest; - private ImmutableList videoFrameEffects; + private ImmutableList videoEffects; private ListenerSet listeners; private DebugViewProvider debugViewProvider; private Looper looper; @@ -127,7 +127,7 @@ public Builder(Context context) { debugViewProvider = DebugViewProvider.NONE; containerMimeType = MimeTypes.VIDEO_MP4; transformationRequest = new TransformationRequest.Builder().build(); - videoFrameEffects = ImmutableList.of(); + videoEffects = ImmutableList.of(); } /** Creates a builder with the values of the provided {@link Transformer}. */ @@ -139,7 +139,7 @@ private Builder(Transformer transformer) { this.removeVideo = transformer.removeVideo; this.containerMimeType = transformer.containerMimeType; this.transformationRequest = transformer.transformationRequest; - this.videoFrameEffects = transformer.videoFrameEffects; + this.videoEffects = transformer.videoEffects; this.listeners = transformer.listeners; this.looper = transformer.looper; this.encoderFactory = transformer.encoderFactory; @@ -176,8 +176,8 @@ public Builder setTransformationRequest(TransformationRequest transformationRequ * @param effects The {@linkplain GlEffect effects} to apply to each video frame. * @return This builder. */ - public Builder setVideoFrameEffects(List effects) { - this.videoFrameEffects = ImmutableList.copyOf(effects); + public Builder setVideoEffects(List effects) { + this.videoEffects = ImmutableList.copyOf(effects); return this; } @@ -422,7 +422,7 @@ public Transformer build() { removeVideo, containerMimeType, transformationRequest, - videoFrameEffects, + videoEffects, listeners, looper, clock, @@ -546,7 +546,7 @@ public interface DebugViewProvider { private final boolean removeVideo; private final String containerMimeType; private final TransformationRequest transformationRequest; - private final ImmutableList videoFrameEffects; + private final ImmutableList videoEffects; private final Looper looper; private final Clock clock; private final Transformer.DebugViewProvider debugViewProvider; @@ -567,7 +567,7 @@ private Transformer( boolean removeVideo, String containerMimeType, TransformationRequest transformationRequest, - ImmutableList videoFrameEffects, + ImmutableList videoEffects, ListenerSet listeners, Looper looper, Clock clock, @@ -582,7 +582,7 @@ private Transformer( this.removeVideo = removeVideo; this.containerMimeType = containerMimeType; this.transformationRequest = transformationRequest; - this.videoFrameEffects = videoFrameEffects; + this.videoEffects = videoEffects; this.listeners = listeners; this.looper = looper; this.clock = clock; @@ -731,7 +731,7 @@ private void startTransformation(MediaItem mediaItem, Muxer muxer) { removeVideo, transformationRequest, mediaItem.clippingConfiguration.startsAtKeyFrame, - videoFrameEffects, + videoEffects, encoderFactory, decoderFactory, new FallbackListener(mediaItem, listeners, transformationRequest), @@ -845,7 +845,7 @@ private static final class TransformerRenderersFactory implements RenderersFacto private final boolean removeVideo; private final TransformationRequest transformationRequest; private final boolean clippingStartsAtKeyFrame; - private final ImmutableList videoFrameEffects; + private final ImmutableList videoEffects; private final Codec.EncoderFactory encoderFactory; private final Codec.DecoderFactory decoderFactory; private final FallbackListener fallbackListener; @@ -859,7 +859,7 @@ public TransformerRenderersFactory( boolean removeVideo, TransformationRequest transformationRequest, boolean clippingStartsAtKeyFrame, - ImmutableList videoFrameEffects, + ImmutableList videoEffects, Codec.EncoderFactory encoderFactory, Codec.DecoderFactory decoderFactory, FallbackListener fallbackListener, @@ -871,7 +871,7 @@ public TransformerRenderersFactory( this.removeVideo = removeVideo; this.transformationRequest = transformationRequest; this.clippingStartsAtKeyFrame = clippingStartsAtKeyFrame; - this.videoFrameEffects = videoFrameEffects; + this.videoEffects = videoEffects; this.encoderFactory = encoderFactory; this.decoderFactory = decoderFactory; this.fallbackListener = fallbackListener; @@ -910,7 +910,7 @@ public Renderer[] createRenderers( mediaClock, transformationRequest, clippingStartsAtKeyFrame, - videoFrameEffects, + videoEffects, encoderFactory, decoderFactory, asyncErrorListener, From 8e716d6804e4c5b3417a19e1ef3c07cf2810aefd Mon Sep 17 00:00:00 2001 From: tonihei Date: Mon, 27 Jun 2022 10:04:19 +0100 Subject: [PATCH 46/73] Rename shouldUseDummySurface to shouldUsePlaceholderSurface This was likely missed in https://github.com/androidx/media/commit/33373d0d0a159ad9c9c3590c838098c4c1530910. PiperOrigin-RevId: 457422574 --- .../media3/exoplayer/video/MediaCodecVideoRenderer.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/MediaCodecVideoRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/MediaCodecVideoRenderer.java index 7773fa039e..073f60fa2b 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/MediaCodecVideoRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/MediaCodecVideoRenderer.java @@ -629,7 +629,7 @@ private void setOutput(@Nullable Object output) throws ExoPlaybackException { surface = placeholderSurface; } else { MediaCodecInfo codecInfo = getCodecInfo(); - if (codecInfo != null && shouldUseDummySurface(codecInfo)) { + if (codecInfo != null && shouldUsePlaceholderSurface(codecInfo)) { placeholderSurface = PlaceholderSurface.newInstanceV17(context, codecInfo.secure); surface = placeholderSurface; } @@ -675,7 +675,7 @@ private void setOutput(@Nullable Object output) throws ExoPlaybackException { @Override protected boolean shouldInitCodec(MediaCodecInfo codecInfo) { - return surface != null || shouldUseDummySurface(codecInfo); + return surface != null || shouldUsePlaceholderSurface(codecInfo); } @Override @@ -706,7 +706,7 @@ protected MediaCodecAdapter.Configuration getMediaCodecConfiguration( deviceNeedsNoPostProcessWorkaround, tunneling ? tunnelingAudioSessionId : C.AUDIO_SESSION_ID_UNSET); if (surface == null) { - if (!shouldUseDummySurface(codecInfo)) { + if (!shouldUsePlaceholderSurface(codecInfo)) { throw new IllegalStateException(); } if (placeholderSurface == null) { @@ -1333,7 +1333,7 @@ protected void renderOutputBufferV21( maybeNotifyRenderedFirstFrame(); } - private boolean shouldUseDummySurface(MediaCodecInfo codecInfo) { + private boolean shouldUsePlaceholderSurface(MediaCodecInfo codecInfo) { return Util.SDK_INT >= 23 && !tunneling && !codecNeedsSetOutputSurfaceWorkaround(codecInfo.name) From 5c2752b4a92a076babc0bc1ff5651a306c20e693 Mon Sep 17 00:00:00 2001 From: tonihei Date: Mon, 27 Jun 2022 09:34:56 +0000 Subject: [PATCH 47/73] Clean up offload state tracking 1. The offloadSchedulingEnabled value doesn't need to be in PlaybackInfo because it's never updated in EPII. 2. The sleepingForOffload value in EPII wasn't updated explicitly (just via the return value of a method). It was also only meant to be enabled while the player is actively playing, but confusingly triggered from a path where the player may theoretically be buffering as well. 3. The offload sleeping (=not scheduling doSomeWork) was interwoven into the actual scheduling code making it slightly hard to follow. This can be improved slightly by keeping the offload sleeping decision and the scheduling separate. PiperOrigin-RevId: 457427293 --- .../media3/exoplayer/ExoPlayerImpl.java | 9 ++-- .../exoplayer/ExoPlayerImplInternal.java | 40 ++++++---------- .../media3/exoplayer/PlaybackInfo.java | 46 ------------------- .../media3/exoplayer/ExoPlayerTest.java | 42 ++--------------- .../exoplayer/MediaPeriodQueueTest.java | 1 - .../robolectric/TestPlayerRunHelper.java | 35 -------------- 6 files changed, 23 insertions(+), 150 deletions(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java index a8587da565..de4f574764 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java @@ -433,6 +433,9 @@ public DeviceComponent getDeviceComponent() { public void experimentalSetOffloadSchedulingEnabled(boolean offloadSchedulingEnabled) { verifyApplicationThread(); internalPlayer.experimentalSetOffloadSchedulingEnabled(offloadSchedulingEnabled); + for (AudioOffloadListener listener : audioOffloadListeners) { + listener.onExperimentalOffloadSchedulingEnabledChanged(offloadSchedulingEnabled); + } } @Override @@ -1962,12 +1965,6 @@ private void updatePlaybackInfo( updateAvailableCommands(); listeners.flushEvents(); - if (previousPlaybackInfo.offloadSchedulingEnabled != newPlaybackInfo.offloadSchedulingEnabled) { - for (AudioOffloadListener listener : audioOffloadListeners) { - listener.onExperimentalOffloadSchedulingEnabledChanged( - newPlaybackInfo.offloadSchedulingEnabled); - } - } if (previousPlaybackInfo.sleepingForOffload != newPlaybackInfo.sleepingForOffload) { for (AudioOffloadListener listener : audioOffloadListeners) { listener.onExperimentalSleepingForOffloadChanged(newPlaybackInfo.sleepingForOffload); diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java index 0b37727ecf..a9f0af6111 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java @@ -817,10 +817,8 @@ private void setOffloadSchedulingEnabledInternal(boolean offloadSchedulingEnable return; } this.offloadSchedulingEnabled = offloadSchedulingEnabled; - @Player.State int state = playbackInfo.playbackState; - if (offloadSchedulingEnabled || state == Player.STATE_ENDED || state == Player.STATE_IDLE) { - playbackInfo = playbackInfo.copyWithOffloadSchedulingEnabled(offloadSchedulingEnabled); - } else { + if (!offloadSchedulingEnabled && playbackInfo.sleepingForOffload) { + // We need to wake the player up if offload scheduling is disabled and we are sleeping. handler.sendEmptyMessage(MSG_DO_SOME_WORK); } } @@ -1080,22 +1078,24 @@ && isLoadingPossible()) { throw new IllegalStateException("Playback stuck buffering and not loading"); } - if (offloadSchedulingEnabled != playbackInfo.offloadSchedulingEnabled) { - playbackInfo = playbackInfo.copyWithOffloadSchedulingEnabled(offloadSchedulingEnabled); - } - - boolean sleepingForOffload = false; - if ((shouldPlayWhenReady() && playbackInfo.playbackState == Player.STATE_READY) - || playbackInfo.playbackState == Player.STATE_BUFFERING) { - sleepingForOffload = !maybeScheduleWakeup(operationStartTimeMs, ACTIVE_INTERVAL_MS); - } else if (enabledRendererCount != 0 && playbackInfo.playbackState != Player.STATE_ENDED) { - scheduleNextWork(operationStartTimeMs, IDLE_INTERVAL_MS); - } + boolean isPlaying = shouldPlayWhenReady() && playbackInfo.playbackState == Player.STATE_READY; + boolean sleepingForOffload = offloadSchedulingEnabled && requestForRendererSleep && isPlaying; if (playbackInfo.sleepingForOffload != sleepingForOffload) { playbackInfo = playbackInfo.copyWithSleepingForOffload(sleepingForOffload); } requestForRendererSleep = false; // A sleep request is only valid for the current doSomeWork. + if (sleepingForOffload || playbackInfo.playbackState == Player.STATE_ENDED) { + // No need to schedule next work. + return; + } else if (isPlaying || playbackInfo.playbackState == Player.STATE_BUFFERING) { + // We are actively playing or waiting for data to be ready. Schedule next work quickly. + scheduleNextWork(operationStartTimeMs, ACTIVE_INTERVAL_MS); + } else if (playbackInfo.playbackState == Player.STATE_READY && enabledRendererCount != 0) { + // We are ready, but not playing. Schedule next work less often to handle non-urgent updates. + scheduleNextWork(operationStartTimeMs, IDLE_INTERVAL_MS); + } + TraceUtil.endSection(); } @@ -1128,15 +1128,6 @@ private void scheduleNextWork(long thisOperationStartTimeMs, long intervalMs) { handler.sendEmptyMessageAtTime(MSG_DO_SOME_WORK, thisOperationStartTimeMs + intervalMs); } - private boolean maybeScheduleWakeup(long operationStartTimeMs, long intervalMs) { - if (offloadSchedulingEnabled && requestForRendererSleep) { - return false; - } - - scheduleNextWork(operationStartTimeMs, intervalMs); - return true; - } - private void seekToInternal(SeekPosition seekPosition) throws ExoPlaybackException { playbackInfoUpdate.incrementPendingOperationAcks(/* operationAcks= */ 1); @@ -1467,7 +1458,6 @@ private void resetInternal( /* bufferedPositionUs= */ startPositionUs, /* totalBufferedDurationUs= */ 0, /* positionUs= */ startPositionUs, - offloadSchedulingEnabled, /* sleepingForOffload= */ false); if (releaseMediaSourceList) { mediaSourceList.release(); diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/PlaybackInfo.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/PlaybackInfo.java index f0e104a75a..9ea9b0e971 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/PlaybackInfo.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/PlaybackInfo.java @@ -74,8 +74,6 @@ public final @PlaybackSuppressionReason int playbackSuppressionReason; /** The playback parameters. */ public final PlaybackParameters playbackParameters; - /** Whether offload scheduling is enabled for the main player loop. */ - public final boolean offloadSchedulingEnabled; /** Whether the main player loop is sleeping, while using offload scheduling. */ public final boolean sleepingForOffload; @@ -122,7 +120,6 @@ public static PlaybackInfo createDummy(TrackSelectorResult emptyTrackSelectorRes /* bufferedPositionUs= */ 0, /* totalBufferedDurationUs= */ 0, /* positionUs= */ 0, - /* offloadSchedulingEnabled= */ false, /* sleepingForOffload= */ false); } @@ -145,7 +142,6 @@ public static PlaybackInfo createDummy(TrackSelectorResult emptyTrackSelectorRes * @param bufferedPositionUs See {@link #bufferedPositionUs}. * @param totalBufferedDurationUs See {@link #totalBufferedDurationUs}. * @param positionUs See {@link #positionUs}. - * @param offloadSchedulingEnabled See {@link #offloadSchedulingEnabled}. * @param sleepingForOffload See {@link #sleepingForOffload}. */ public PlaybackInfo( @@ -166,7 +162,6 @@ public PlaybackInfo( long bufferedPositionUs, long totalBufferedDurationUs, long positionUs, - boolean offloadSchedulingEnabled, boolean sleepingForOffload) { this.timeline = timeline; this.periodId = periodId; @@ -185,7 +180,6 @@ public PlaybackInfo( this.bufferedPositionUs = bufferedPositionUs; this.totalBufferedDurationUs = totalBufferedDurationUs; this.positionUs = positionUs; - this.offloadSchedulingEnabled = offloadSchedulingEnabled; this.sleepingForOffload = sleepingForOffload; } @@ -237,7 +231,6 @@ public PlaybackInfo copyWithNewPosition( bufferedPositionUs, totalBufferedDurationUs, positionUs, - offloadSchedulingEnabled, sleepingForOffload); } @@ -267,7 +260,6 @@ public PlaybackInfo copyWithTimeline(Timeline timeline) { bufferedPositionUs, totalBufferedDurationUs, positionUs, - offloadSchedulingEnabled, sleepingForOffload); } @@ -297,7 +289,6 @@ public PlaybackInfo copyWithPlaybackState(int playbackState) { bufferedPositionUs, totalBufferedDurationUs, positionUs, - offloadSchedulingEnabled, sleepingForOffload); } @@ -327,7 +318,6 @@ public PlaybackInfo copyWithPlaybackError(@Nullable ExoPlaybackException playbac bufferedPositionUs, totalBufferedDurationUs, positionUs, - offloadSchedulingEnabled, sleepingForOffload); } @@ -357,7 +347,6 @@ public PlaybackInfo copyWithIsLoading(boolean isLoading) { bufferedPositionUs, totalBufferedDurationUs, positionUs, - offloadSchedulingEnabled, sleepingForOffload); } @@ -387,7 +376,6 @@ public PlaybackInfo copyWithLoadingMediaPeriodId(MediaPeriodId loadingMediaPerio bufferedPositionUs, totalBufferedDurationUs, positionUs, - offloadSchedulingEnabled, sleepingForOffload); } @@ -421,7 +409,6 @@ public PlaybackInfo copyWithPlayWhenReady( bufferedPositionUs, totalBufferedDurationUs, positionUs, - offloadSchedulingEnabled, sleepingForOffload); } @@ -451,38 +438,6 @@ public PlaybackInfo copyWithPlaybackParameters(PlaybackParameters playbackParame bufferedPositionUs, totalBufferedDurationUs, positionUs, - offloadSchedulingEnabled, - sleepingForOffload); - } - - /** - * Copies playback info with new offloadSchedulingEnabled. - * - * @param offloadSchedulingEnabled New offloadSchedulingEnabled state. See {@link - * #offloadSchedulingEnabled}. - * @return Copied playback info with new offload scheduling state. - */ - @CheckResult - public PlaybackInfo copyWithOffloadSchedulingEnabled(boolean offloadSchedulingEnabled) { - return new PlaybackInfo( - timeline, - periodId, - requestedContentPositionUs, - discontinuityStartPositionUs, - playbackState, - playbackError, - isLoading, - trackGroups, - trackSelectorResult, - staticMetadata, - loadingMediaPeriodId, - playWhenReady, - playbackSuppressionReason, - playbackParameters, - bufferedPositionUs, - totalBufferedDurationUs, - positionUs, - offloadSchedulingEnabled, sleepingForOffload); } @@ -512,7 +467,6 @@ public PlaybackInfo copyWithSleepingForOffload(boolean sleepingForOffload) { bufferedPositionUs, totalBufferedDurationUs, positionUs, - offloadSchedulingEnabled, sleepingForOffload); } } diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java index c41f46941a..a6d9d4b6ff 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java @@ -59,7 +59,6 @@ import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUntilPendingCommandsAreFullyHandled; import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUntilPlaybackState; import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUntilPositionDiscontinuity; -import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUntilReceiveOffloadSchedulingEnabledNewState; import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUntilSleepingForOffload; import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUntilTimelineChanged; import static com.google.common.truth.Truth.assertThat; @@ -9641,47 +9640,16 @@ protected void onEnabled(boolean joining, boolean mayRenderStartOfStream) } @Test - public void enableOffloadSchedulingWhileIdle_isToggled_isReported() throws Exception { + public void enableOffloadScheduling_isReported() throws Exception { ExoPlayer player = new TestExoPlayerBuilder(context).build(); + ExoPlayer.AudioOffloadListener mockListener = mock(ExoPlayer.AudioOffloadListener.class); + player.addAudioOffloadListener(mockListener); player.experimentalSetOffloadSchedulingEnabled(true); - assertThat(runUntilReceiveOffloadSchedulingEnabledNewState(player)).isTrue(); + verify(mockListener).onExperimentalOffloadSchedulingEnabledChanged(true); player.experimentalSetOffloadSchedulingEnabled(false); - assertThat(runUntilReceiveOffloadSchedulingEnabledNewState(player)).isFalse(); - } - - @Test - public void enableOffloadSchedulingWhilePlaying_isToggled_isReported() throws Exception { - FakeSleepRenderer sleepRenderer = new FakeSleepRenderer(C.TRACK_TYPE_AUDIO).sleepOnNextRender(); - ExoPlayer player = new TestExoPlayerBuilder(context).setRenderers(sleepRenderer).build(); - Timeline timeline = new FakeTimeline(); - player.setMediaSource(new FakeMediaSource(timeline, ExoPlayerTestRunner.AUDIO_FORMAT)); - player.prepare(); - player.play(); - - player.experimentalSetOffloadSchedulingEnabled(true); - assertThat(runUntilReceiveOffloadSchedulingEnabledNewState(player)).isTrue(); - - player.experimentalSetOffloadSchedulingEnabled(false); - assertThat(runUntilReceiveOffloadSchedulingEnabledNewState(player)).isFalse(); - } - - @Test - public void enableOffloadSchedulingWhileSleepingForOffload_isDisabled_isReported() - throws Exception { - FakeSleepRenderer sleepRenderer = new FakeSleepRenderer(C.TRACK_TYPE_AUDIO).sleepOnNextRender(); - ExoPlayer player = new TestExoPlayerBuilder(context).setRenderers(sleepRenderer).build(); - Timeline timeline = new FakeTimeline(); - player.setMediaSource(new FakeMediaSource(timeline, ExoPlayerTestRunner.AUDIO_FORMAT)); - player.experimentalSetOffloadSchedulingEnabled(true); - player.prepare(); - player.play(); - runUntilSleepingForOffload(player, /* expectedSleepForOffload= */ true); - - player.experimentalSetOffloadSchedulingEnabled(false); - - assertThat(runUntilReceiveOffloadSchedulingEnabledNewState(player)).isFalse(); + verify(mockListener).onExperimentalOffloadSchedulingEnabledChanged(false); } @Test diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/MediaPeriodQueueTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/MediaPeriodQueueTest.java index 155450ec7e..cb059bc241 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/MediaPeriodQueueTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/MediaPeriodQueueTest.java @@ -1112,7 +1112,6 @@ private void setupTimeline(Timeline timeline) { /* bufferedPositionUs= */ 0, /* totalBufferedDurationUs= */ 0, /* positionUs= */ 0, - /* offloadSchedulingEnabled= */ false, /* sleepingForOffload= */ false); } diff --git a/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.java b/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.java index 29c3d09c57..658e9f56be 100644 --- a/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.java +++ b/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.java @@ -184,41 +184,6 @@ public static ExoPlaybackException runUntilError(ExoPlayer player) throws Timeou return checkNotNull(player.getPlayerError()); } - /** - * Runs tasks of the main {@link Looper} until {@link - * ExoPlayer.AudioOffloadListener#onExperimentalOffloadSchedulingEnabledChanged} is called or a - * playback error occurs. - * - *

    If a playback error occurs it will be thrown wrapped in an {@link IllegalStateException}. - * - * @param player The {@link Player}. - * @return The new offloadSchedulingEnabled state. - * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is - * exceeded. - */ - public static boolean runUntilReceiveOffloadSchedulingEnabledNewState(ExoPlayer player) - throws TimeoutException { - verifyMainTestThread(player); - AtomicReference<@NullableType Boolean> offloadSchedulingEnabledReceiver = - new AtomicReference<>(); - ExoPlayer.AudioOffloadListener listener = - new ExoPlayer.AudioOffloadListener() { - @Override - public void onExperimentalOffloadSchedulingEnabledChanged( - boolean offloadSchedulingEnabled) { - offloadSchedulingEnabledReceiver.set(offloadSchedulingEnabled); - } - }; - player.addAudioOffloadListener(listener); - runMainLooperUntil( - () -> offloadSchedulingEnabledReceiver.get() != null || player.getPlayerError() != null); - player.removeAudioOffloadListener(listener); - if (player.getPlayerError() != null) { - throw new IllegalStateException(player.getPlayerError()); - } - return checkNotNull(offloadSchedulingEnabledReceiver.get()); - } - /** * Runs tasks of the main {@link Looper} until {@link * ExoPlayer.AudioOffloadListener#onExperimentalSleepingForOffloadChanged(boolean)} is called or a From b2831d8559713b757feb3f15a2c828db0e5ecd7c Mon Sep 17 00:00:00 2001 From: rohks Date: Mon, 27 Jun 2022 11:31:10 +0000 Subject: [PATCH 48/73] Add timestamp to `Metadata` `MetadataRenderer` is updated to output `Metadata` with its presentation time, in microseconds. PiperOrigin-RevId: 457444718 --- .../java/androidx/media3/common/Metadata.java | 43 ++++++++++++++++--- .../androidx/media3/common/text/CueGroup.java | 2 +- .../androidx/media3/common/MetadataTest.java | 5 ++- .../exoplayer/metadata/MetadataRenderer.java | 26 +++++++---- .../test/assets/playbackdumps/dash/emsg.dump | 3 ++ .../playbackdumps/ts/sample_ait.ts.dump | 3 ++ .../playbackdumps/ts/sample_scte35.ts.dump | 3 ++ .../ts/sample_with_id3.adts.dump | 2 + .../utils/robolectric/PlaybackOutput.java | 1 + 9 files changed, 73 insertions(+), 15 deletions(-) diff --git a/libraries/common/src/main/java/androidx/media3/common/Metadata.java b/libraries/common/src/main/java/androidx/media3/common/Metadata.java index 1af08378f7..eadf456c18 100644 --- a/libraries/common/src/main/java/androidx/media3/common/Metadata.java +++ b/libraries/common/src/main/java/androidx/media3/common/Metadata.java @@ -20,6 +20,7 @@ import androidx.annotation.Nullable; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; +import com.google.common.primitives.Longs; import java.util.Arrays; import java.util.List; @@ -61,11 +62,28 @@ default void populateMediaMetadata(MediaMetadata.Builder builder) {} } private final Entry[] entries; + /** + * The presentation time of the metadata, in microseconds. + * + *

    This time is an offset from the start of the current {@link Timeline.Period}. + * + *

    This time is {@link C#TIME_UNSET} when not known or undefined. + */ + public final long presentationTimeUs; /** * @param entries The metadata entries. */ public Metadata(Entry... entries) { + this(/* presentationTimeUs= */ C.TIME_UNSET, entries); + } + + /** + * @param presentationTimeUs The presentation time for the metadata entries. + * @param entries The metadata entries. + */ + public Metadata(long presentationTimeUs, Entry... entries) { + this.presentationTimeUs = presentationTimeUs; this.entries = entries; } @@ -73,7 +91,15 @@ public Metadata(Entry... entries) { * @param entries The metadata entries. */ public Metadata(List entries) { - this.entries = entries.toArray(new Entry[0]); + this(entries.toArray(new Entry[0])); + } + + /** + * @param presentationTimeUs The presentation time for the metadata entries. + * @param entries The metadata entries. + */ + public Metadata(long presentationTimeUs, List entries) { + this(presentationTimeUs, entries.toArray(new Entry[0])); } /* package */ Metadata(Parcel in) { @@ -81,6 +107,7 @@ public Metadata(List entries) { for (int i = 0; i < entries.length; i++) { entries[i] = in.readParcelable(Entry.class.getClassLoader()); } + presentationTimeUs = in.readLong(); } /** Returns the number of metadata entries. */ @@ -123,7 +150,8 @@ public Metadata copyWithAppendedEntries(Entry... entriesToAppend) { if (entriesToAppend.length == 0) { return this; } - return new Metadata(Util.nullSafeArrayConcatenation(entries, entriesToAppend)); + return new Metadata( + presentationTimeUs, Util.nullSafeArrayConcatenation(entries, entriesToAppend)); } @Override @@ -135,17 +163,21 @@ public boolean equals(@Nullable Object obj) { return false; } Metadata other = (Metadata) obj; - return Arrays.equals(entries, other.entries); + return Arrays.equals(entries, other.entries) && presentationTimeUs == other.presentationTimeUs; } @Override public int hashCode() { - return Arrays.hashCode(entries); + int result = Arrays.hashCode(entries); + result = 31 * result + Longs.hashCode(presentationTimeUs); + return result; } @Override public String toString() { - return "entries=" + Arrays.toString(entries); + return "entries=" + + Arrays.toString(entries) + + (presentationTimeUs == C.TIME_UNSET ? "" : ", presentationTimeUs=" + presentationTimeUs); } // Parcelable implementation. @@ -161,6 +193,7 @@ public void writeToParcel(Parcel dest, int flags) { for (Entry entry : entries) { dest.writeParcelable(entry, 0); } + dest.writeLong(presentationTimeUs); } public static final Parcelable.Creator CREATOR = diff --git a/libraries/common/src/main/java/androidx/media3/common/text/CueGroup.java b/libraries/common/src/main/java/androidx/media3/common/text/CueGroup.java index 3d1f1bec20..67e58eb065 100644 --- a/libraries/common/src/main/java/androidx/media3/common/text/CueGroup.java +++ b/libraries/common/src/main/java/androidx/media3/common/text/CueGroup.java @@ -47,7 +47,7 @@ public final class CueGroup implements Bundleable { /** * The presentation time of the {@link #cues}, in microseconds. * - *

    This time is an offset from the start of the current {@link Timeline.Period} + *

    This time is an offset from the start of the current {@link Timeline.Period}. */ @UnstableApi public final long presentationTimeUs; diff --git a/libraries/common/src/test/java/androidx/media3/common/MetadataTest.java b/libraries/common/src/test/java/androidx/media3/common/MetadataTest.java index 31ad83244a..0aa869aaad 100644 --- a/libraries/common/src/test/java/androidx/media3/common/MetadataTest.java +++ b/libraries/common/src/test/java/androidx/media3/common/MetadataTest.java @@ -30,7 +30,10 @@ public class MetadataTest { @Test public void parcelable() { Metadata metadataToParcel = - new Metadata(new FakeMetadataEntry("id1"), new FakeMetadataEntry("id2")); + new Metadata( + /* presentationTimeUs= */ 1_230_000, + new FakeMetadataEntry("id1"), + new FakeMetadataEntry("id2")); Parcel parcel = Parcel.obtain(); metadataToParcel.writeToParcel(parcel, 0); diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/metadata/MetadataRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/metadata/MetadataRenderer.java index 4aca3b8164..0c7b16f8f3 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/metadata/MetadataRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/metadata/MetadataRenderer.java @@ -15,6 +15,7 @@ */ package androidx.media3.exoplayer.metadata; +import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Util.castNonNull; import android.os.Handler; @@ -36,6 +37,7 @@ import androidx.media3.extractor.metadata.MetadataInputBuffer; import java.util.ArrayList; import java.util.List; +import org.checkerframework.dataflow.qual.SideEffectFree; /** A renderer for metadata. */ @UnstableApi @@ -53,8 +55,8 @@ public final class MetadataRenderer extends BaseRenderer implements Callback { private boolean inputStreamEnded; private boolean outputStreamEnded; private long subsampleOffsetUs; - private long pendingMetadataTimestampUs; @Nullable private Metadata pendingMetadata; + private long outputStreamOffsetUs; /** * @param output The output. @@ -85,7 +87,7 @@ public MetadataRenderer( outputLooper == null ? null : Util.createHandler(outputLooper, /* callback= */ this); this.decoderFactory = Assertions.checkNotNull(decoderFactory); buffer = new MetadataInputBuffer(); - pendingMetadataTimestampUs = C.TIME_UNSET; + outputStreamOffsetUs = C.TIME_UNSET; } @Override @@ -106,12 +108,12 @@ public String getName() { @Override protected void onStreamChanged(Format[] formats, long startPositionUs, long offsetUs) { decoder = decoderFactory.createDecoder(formats[0]); + outputStreamOffsetUs = offsetUs; } @Override protected void onPositionReset(long positionUs, boolean joining) { pendingMetadata = null; - pendingMetadataTimestampUs = C.TIME_UNSET; inputStreamEnded = false; outputStreamEnded = false; } @@ -158,8 +160,8 @@ private void decodeWrappedMetadata(Metadata metadata, List decod @Override protected void onDisabled() { pendingMetadata = null; - pendingMetadataTimestampUs = C.TIME_UNSET; decoder = null; + outputStreamOffsetUs = C.TIME_UNSET; } @Override @@ -200,9 +202,9 @@ private void readMetadata() { List entries = new ArrayList<>(metadata.length()); decodeWrappedMetadata(metadata, entries); if (!entries.isEmpty()) { - Metadata expandedMetadata = new Metadata(entries); + Metadata expandedMetadata = + new Metadata(getPresentationTimeUs(buffer.timeUs), entries); pendingMetadata = expandedMetadata; - pendingMetadataTimestampUs = buffer.timeUs; } } } @@ -214,10 +216,10 @@ private void readMetadata() { private boolean outputMetadata(long positionUs) { boolean didOutput = false; - if (pendingMetadata != null && pendingMetadataTimestampUs <= positionUs) { + if (pendingMetadata != null + && pendingMetadata.presentationTimeUs <= getPresentationTimeUs(positionUs)) { invokeRenderer(pendingMetadata); pendingMetadata = null; - pendingMetadataTimestampUs = C.TIME_UNSET; didOutput = true; } if (inputStreamEnded && pendingMetadata == null) { @@ -237,4 +239,12 @@ private void invokeRenderer(Metadata metadata) { private void invokeRendererInternal(Metadata metadata) { output.onMetadata(metadata); } + + @SideEffectFree + private long getPresentationTimeUs(long positionUs) { + checkState(positionUs != C.TIME_UNSET); + checkState(outputStreamOffsetUs != C.TIME_UNSET); + + return positionUs - outputStreamOffsetUs; + } } diff --git a/libraries/test_data/src/test/assets/playbackdumps/dash/emsg.dump b/libraries/test_data/src/test/assets/playbackdumps/dash/emsg.dump index 4a3c7b2e0e..2bc2f0c2b9 100644 --- a/libraries/test_data/src/test/assets/playbackdumps/dash/emsg.dump +++ b/libraries/test_data/src/test/assets/playbackdumps/dash/emsg.dump @@ -94,8 +94,11 @@ MediaCodecAdapter (exotest.audio.aac): buffers[91] = length 0, hash 1 MetadataOutput: Metadata[0]: + presentationTimeUs = 100000 entry[0] = EMSG: scheme=urn:mpeg:dash:event:callback:2015, id=0, durationMs=1000, value=1 Metadata[1]: + presentationTimeUs = 100000 entry[0] = EMSG: scheme=urn:mpeg:dash:event:callback:2015, id=1, durationMs=1000, value=1 Metadata[2]: + presentationTimeUs = 1000000 entry[0] = EMSG: scheme=urn:mpeg:dash:event:callback:2015, id=2, durationMs=1000, value=1 diff --git a/libraries/test_data/src/test/assets/playbackdumps/ts/sample_ait.ts.dump b/libraries/test_data/src/test/assets/playbackdumps/ts/sample_ait.ts.dump index 75a33b8c24..c94ca1b2c6 100644 --- a/libraries/test_data/src/test/assets/playbackdumps/ts/sample_ait.ts.dump +++ b/libraries/test_data/src/test/assets/playbackdumps/ts/sample_ait.ts.dump @@ -22,11 +22,14 @@ MediaCodecAdapter (exotest.audio.eac3): buffers[19] = length 0, hash 1 MetadataOutput: Metadata[0]: + presentationTimeUs = 0 entry[0] = Ait(controlCode=1,url=http://static-cdn.arte.tv/redbutton/index_fr.html) entry[1] = Ait(controlCode=2,url=http://www.arte.tv/hbbtvv2/index.html?lang=fr_FR&page=PLUS7) Metadata[1]: + presentationTimeUs = 192000 entry[0] = Ait(controlCode=1,url=http://static-cdn.arte.tv/redbutton/index_fr.html) entry[1] = Ait(controlCode=2,url=http://www.arte.tv/hbbtvv2/index.html?lang=fr_FR&page=PLUS7) Metadata[2]: + presentationTimeUs = 384000 entry[0] = Ait(controlCode=1,url=http://static-cdn.arte.tv/redbutton/index_fr.html) entry[1] = Ait(controlCode=2,url=http://www.arte.tv/hbbtvv2/index.html?lang=fr_FR&page=PLUS7) diff --git a/libraries/test_data/src/test/assets/playbackdumps/ts/sample_scte35.ts.dump b/libraries/test_data/src/test/assets/playbackdumps/ts/sample_scte35.ts.dump index d57c3ed9df..03a95ad04a 100644 --- a/libraries/test_data/src/test/assets/playbackdumps/ts/sample_scte35.ts.dump +++ b/libraries/test_data/src/test/assets/playbackdumps/ts/sample_scte35.ts.dump @@ -12,8 +12,11 @@ MediaCodecAdapter (exotest.video.mpeg2): buffers[2] = length 0, hash 1 MetadataOutput: Metadata[0]: + presentationTimeUs = 33366 entry[0] = SCTE-35 splice command: type=SpliceInsertCommand Metadata[1]: + presentationTimeUs = 33366 entry[0] = SCTE-35 splice command: type=SpliceInsertCommand Metadata[2]: + presentationTimeUs = 33366 entry[0] = SCTE-35 splice command: type=SpliceInsertCommand diff --git a/libraries/test_data/src/test/assets/playbackdumps/ts/sample_with_id3.adts.dump b/libraries/test_data/src/test/assets/playbackdumps/ts/sample_with_id3.adts.dump index 0434d23c38..f272f7f348 100644 --- a/libraries/test_data/src/test/assets/playbackdumps/ts/sample_with_id3.adts.dump +++ b/libraries/test_data/src/test/assets/playbackdumps/ts/sample_with_id3.adts.dump @@ -147,7 +147,9 @@ MediaCodecAdapter (exotest.audio.aac): buffers[144] = length 0, hash 1 MetadataOutput: Metadata[0]: + presentationTimeUs = 0 entry[0] = APIC: mimeType=image/jpeg, description=Hello World Metadata[1]: + presentationTimeUs = 23219 entry[0] = COMM: language=eng, description=description entry[1] = APIC: mimeType=image/jpeg, description=Hello World diff --git a/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/PlaybackOutput.java b/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/PlaybackOutput.java index 8fc015fc9c..f5f1bfb8ec 100644 --- a/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/PlaybackOutput.java +++ b/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/PlaybackOutput.java @@ -122,6 +122,7 @@ private void dumpMetadata(Dumper dumper) { for (int i = 0; i < metadatas.size(); i++) { dumper.startBlock("Metadata[" + i + "]"); Metadata metadata = metadatas.get(i); + dumper.add("presentationTimeUs", metadata.presentationTimeUs); for (int j = 0; j < metadata.length(); j++) { dumper.add("entry[" + j + "]", getEntryAsString(metadata.get(j))); } From a67db3140947ec42e27bca516147483969cf1a01 Mon Sep 17 00:00:00 2001 From: ibaker Date: Tue, 28 Jun 2022 09:30:11 +0000 Subject: [PATCH 49/73] Fix release notes related to track selection renames and deletions Issue: google/ExoPlayer#10363 PiperOrigin-RevId: 457679928 --- RELEASENOTES.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 3672fcb9fd..5b1dfaa1dd 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -48,7 +48,9 @@ This release corresponds to the * Rename `TracksInfo` to `Tracks` and `TracksInfo.TrackGroupInfo` to `Tracks.Group`. `Player.getCurrentTracksInfo` and `Player.Listener.onTracksInfoChanged` have also been renamed to - `Player.getCurrentTracks` and `Player.Listener.onTracksChanged`. + `Player.getCurrentTracks` and `Player.Listener.onTracksChanged`. This + includes 'un-deprecating' the `Player.Listener.onTracksChanged` method + name, but with different parameter types. * Change `DefaultTrackSelector.buildUponParameters` and `DefaultTrackSelector.Parameters.buildUpon` to return `DefaultTrackSelector.Parameters.Builder` instead of the deprecated @@ -213,10 +215,11 @@ This release corresponds to the AndroidStudio's gradle sync to fail ([#9933](https://github.com/google/ExoPlayer/issues/9933)). * Remove deprecated symbols: - * Remove `Player.Listener.onTracksChanged`. Use - `Player.Listener.onTracksInfoChanged` instead. + * Remove `Player.Listener.onTracksChanged(TrackGroupArray, + TrackSelectionArray)`. Use `Player.Listener.onTracksChanged(Tracks)` + instead. * Remove `Player.getCurrentTrackGroups` and - `Player.getCurrentTrackSelections`. Use `Player.getCurrentTracksInfo` + `Player.getCurrentTrackSelections`. Use `Player.getCurrentTracks` instead. You can also continue to use `ExoPlayer.getCurrentTrackGroups` and `ExoPlayer.getCurrentTrackSelections`, although these methods remain deprecated. From b7241d4eb32fc049b2c6765a356ff5f18717f825 Mon Sep 17 00:00:00 2001 From: ibaker Date: Tue, 28 Jun 2022 09:33:29 +0000 Subject: [PATCH 50/73] Fix typo in the media3 1.0.0-alpha02 / ExoPlayer 2.17.0 release notes PiperOrigin-RevId: 457680579 --- RELEASENOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5b1dfaa1dd..e5d9d9a4b4 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -431,7 +431,7 @@ This release corresponds to the when creating `PendingIntent`s ([#9528](https://github.com/google/ExoPlayer/issues/9528)). * Remove deprecated symbols: - * Remove `Player.EventLister`. Use `Player.Listener` instead. + * Remove `Player.EventListener`. Use `Player.Listener` instead. * Remove `MediaSourceFactory.setDrmSessionManager`, `MediaSourceFactory.setDrmHttpDataSourceFactory`, and `MediaSourceFactory.setDrmUserAgent`. Use From b7b5f20e592bee772772eb1b009c7f5a96077520 Mon Sep 17 00:00:00 2001 From: hschlueter Date: Tue, 28 Jun 2022 11:22:45 +0000 Subject: [PATCH 51/73] Allow changing input pixelWidthHeightRatio for GlEffectsFrameProcessor. pixelWidthHeightRatio is now passed to setInputFrameInfo instead of the factory. PiperOrigin-RevId: 457696703 --- .../GlEffectsFrameProcessorPixelTest.java | 4 +- .../media3/transformer/FrameInfo.java | 6 +- .../media3/transformer/FrameProcessor.java | 3 + .../transformer/GlEffectsFrameProcessor.java | 59 ++++++++----------- .../VideoTranscodingSamplePipeline.java | 4 +- 5 files changed, 35 insertions(+), 41 deletions(-) diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java index 910e724981..d5e4f7c96e 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java @@ -366,7 +366,6 @@ public void onFrameProcessingEnded() { frameProcessingEnded = true; } }, - pixelWidthHeightRatio, /* streamOffsetUs= */ 0L, effects, /* outputSurfaceProvider= */ (requestedWidth, requestedHeight) -> { @@ -381,7 +380,8 @@ public void onFrameProcessingEnded() { }, Transformer.DebugViewProvider.NONE, /* enableExperimentalHdrEditing= */ false)); - glEffectsFrameProcessor.setInputFrameInfo(new FrameInfo(inputWidth, inputHeight)); + glEffectsFrameProcessor.setInputFrameInfo( + new FrameInfo(inputWidth, inputHeight, pixelWidthHeightRatio)); glEffectsFrameProcessor.registerInputFrame(); // Queue the first video frame from the extractor. diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameInfo.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameInfo.java index 0b0af7821b..8975f93383 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameInfo.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameInfo.java @@ -23,15 +23,17 @@ public final int width; /** The height of the frame, in pixels. */ public final int height; + /** The ratio of width over height for each pixel. */ + public final float pixelWidthHeightRatio; - // TODO(b/227625423): Add pixelWidthHeightRatio. // TODO(b/227624622): Add color space information for HDR. - public FrameInfo(int width, int height) { + public FrameInfo(int width, int height, float pixelWidthHeightRatio) { checkArgument(width > 0, "width must be positive, but is: " + width); checkArgument(height > 0, "height must be positive, but is: " + height); this.width = width; this.height = height; + this.pixelWidthHeightRatio = pixelWidthHeightRatio; } } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessor.java index db0a3bec7b..17c60e801d 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessor.java @@ -46,6 +46,9 @@ interface Listener { * *

    The new input information is applied from the next frame {@linkplain #registerInputFrame() * registered} onwards. + * + *

    Pixels are expanded using the {@link FrameInfo#pixelWidthHeightRatio} so that the output + * frames' pixels have a ratio of 1. */ void setInputFrameInfo(FrameInfo inputFrameInfo); diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java index 75b9b80d25..9823b57153 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java @@ -50,8 +50,6 @@ * * @param context A {@link Context}. * @param listener A {@link Listener}. - * @param pixelWidthHeightRatio The ratio of width over height for each pixel. Pixels are expanded - * by this ratio so that the output frame's pixels have a ratio of 1. * @param effects The {@link GlEffect GlEffects} to apply to each frame. * @param outputSurfaceProvider A {@link SurfaceInfo.Provider} managing the output {@link * Surface}. @@ -64,7 +62,6 @@ public static GlEffectsFrameProcessor create( Context context, FrameProcessor.Listener listener, - float pixelWidthHeightRatio, long streamOffsetUs, List effects, SurfaceInfo.Provider outputSurfaceProvider, @@ -80,7 +77,6 @@ public static GlEffectsFrameProcessor create( createOpenGlObjectsAndFrameProcessor( context, listener, - pixelWidthHeightRatio, streamOffsetUs, effects, outputSurfaceProvider, @@ -110,7 +106,6 @@ public static GlEffectsFrameProcessor create( private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( Context context, FrameProcessor.Listener listener, - float pixelWidthHeightRatio, long streamOffsetUs, List effects, SurfaceInfo.Provider outputSurfaceProvider, @@ -136,20 +131,12 @@ private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( GlUtil.focusPlaceholderEglSurface(eglContext, eglDisplay); } - ImmutableList.Builder matrixTransformationListBuilder = - new ImmutableList.Builder<>(); - if (pixelWidthHeightRatio != 1f) { - matrixTransformationListBuilder.add( - createPixelWidthHeightRatioTransformation(pixelWidthHeightRatio)); - } - ImmutableList textureProcessors = getGlTextureProcessorsForGlEffects( context, effects, eglDisplay, eglContext, - matrixTransformationListBuilder, outputSurfaceProvider, streamOffsetUs, listener, @@ -173,26 +160,6 @@ private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( textureProcessors); } - /** - * Returns a new {@link GlMatrixTransformation} to expand or shrink the frame based on the {@code - * pixelWidthHeightRatio}. - * - *

    If {@code pixelWidthHeightRatio} is 1, this method returns an identity transformation that - * can be ignored. - */ - private static GlMatrixTransformation createPixelWidthHeightRatioTransformation( - float pixelWidthHeightRatio) { - if (pixelWidthHeightRatio > 1f) { - return new ScaleToFitTransformation.Builder() - .setScale(/* scaleX= */ pixelWidthHeightRatio, /* scaleY= */ 1f) - .build(); - } else { - return new ScaleToFitTransformation.Builder() - .setScale(/* scaleX= */ 1f, /* scaleY= */ 1f / pixelWidthHeightRatio) - .build(); - } - } - /** * Combines consecutive {@link GlMatrixTransformation} instances into a single {@link * MatrixTransformationProcessor} and converts all other {@link GlEffect} instances to separate @@ -207,7 +174,6 @@ private static ImmutableList getGlTextureProcessorsForGlEffe List effects, EGLDisplay eglDisplay, EGLContext eglContext, - ImmutableList.Builder matrixTransformationListBuilder, SurfaceInfo.Provider outputSurfaceProvider, long streamOffsetUs, FrameProcessor.Listener listener, @@ -216,6 +182,8 @@ private static ImmutableList getGlTextureProcessorsForGlEffe throws FrameProcessingException { ImmutableList.Builder textureProcessorListBuilder = new ImmutableList.Builder<>(); + ImmutableList.Builder matrixTransformationListBuilder = + new ImmutableList.Builder<>(); for (int i = 0; i < effects.size(); i++) { GlEffect effect = effects.get(i); if (effect instanceof GlMatrixTransformation) { @@ -396,7 +364,7 @@ private void processInputFrame() { long presentationTimeUs = inputFrameTimeNs / 1000 - streamOffsetUs; inputSurfaceTexture.getTransformMatrix(inputSurfaceTextureTransformMatrix); inputExternalTextureProcessor.setTextureTransformMatrix(inputSurfaceTextureTransformMatrix); - FrameInfo inputFrameInfo = pendingInputFrames.remove(); + FrameInfo inputFrameInfo = adjustForPixelWidthHeightRatio(pendingInputFrames.remove()); checkState( inputExternalTextureProcessor.maybeQueueInputFrame( new TextureInfo( @@ -409,6 +377,27 @@ private void processInputFrame() { // asynchronously by the texture processors chained after it. } + /** + * Expands or shrinks the frame based on the {@link FrameInfo#pixelWidthHeightRatio} and returns a + * new {@link FrameInfo} instance with scaled dimensions and {@link + * FrameInfo#pixelWidthHeightRatio} 1. + */ + private FrameInfo adjustForPixelWidthHeightRatio(FrameInfo frameInfo) { + if (frameInfo.pixelWidthHeightRatio > 1f) { + return new FrameInfo( + (int) (frameInfo.width * frameInfo.pixelWidthHeightRatio), + frameInfo.height, + /* pixelWidthHeightRatio= */ 1); + } else if (frameInfo.pixelWidthHeightRatio < 1f) { + return new FrameInfo( + frameInfo.width, + (int) (frameInfo.height / frameInfo.pixelWidthHeightRatio), + /* pixelWidthHeightRatio= */ 1); + } else { + return frameInfo; + } + } + /** * Propagates the end-of-stream signal through the texture processors once no more input frames * are pending. diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java index 5454e35147..4304f3483a 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java @@ -119,7 +119,6 @@ public void onFrameProcessingEnded() { } } }, - inputFormat.pixelWidthHeightRatio, streamOffsetUs, effectsListBuilder.build(), /* outputSurfaceProvider= */ encoderWrapper, @@ -129,7 +128,8 @@ public void onFrameProcessingEnded() { throw TransformationException.createForFrameProcessingException( e, TransformationException.ERROR_CODE_GL_INIT_FAILED); } - frameProcessor.setInputFrameInfo(new FrameInfo(decodedWidth, decodedHeight)); + frameProcessor.setInputFrameInfo( + new FrameInfo(decodedWidth, decodedHeight, inputFormat.pixelWidthHeightRatio)); decoder = decoderFactory.createForVideoDecoding( From 2a2d9e360baa6e1a44be53c39fbcd69079f34dcc Mon Sep 17 00:00:00 2001 From: ibaker Date: Tue, 28 Jun 2022 12:15:03 +0000 Subject: [PATCH 52/73] Use a helper function and Truth Correspondence instead of NoUidTimeline NoUidTimeline still exists as a private detail of TestUtil, but it no longer extends ForwardingTimeline because the interactions are quite hard to reason about. #minor-release PiperOrigin-RevId: 457703593 --- .../media3/exoplayer/ExoPlayerTest.java | 4 +- .../androidx/media3/test/utils/Action.java | 10 +-- .../test/utils/ExoPlayerTestRunner.java | 8 +-- .../media3/test/utils/NoUidTimeline.java | 51 --------------- .../androidx/media3/test/utils/TestUtil.java | 63 +++++++++++++++++-- 5 files changed, 69 insertions(+), 67 deletions(-) delete mode 100644 libraries/test_utils/src/main/java/androidx/media3/test/utils/NoUidTimeline.java diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java index a6d9d4b6ff..dbbb47fc69 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java @@ -53,6 +53,7 @@ import static androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition.DEFAULT_WINDOW_DURATION_US; import static androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US; import static androidx.media3.test.utils.TestUtil.assertTimelinesSame; +import static androidx.media3.test.utils.TestUtil.timelinesAreSame; import static androidx.media3.test.utils.robolectric.RobolectricUtil.runMainLooperUntil; import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.playUntilPosition; import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.playUntilStartOfMediaItem; @@ -156,7 +157,6 @@ import androidx.media3.test.utils.FakeTrackSelection; import androidx.media3.test.utils.FakeTrackSelector; import androidx.media3.test.utils.FakeVideoRenderer; -import androidx.media3.test.utils.NoUidTimeline; import androidx.media3.test.utils.TestExoPlayerBuilder; import androidx.media3.test.utils.robolectric.TestPlayerRunHelper; import androidx.test.core.app.ApplicationProvider; @@ -12257,6 +12257,6 @@ public Loader.LoadErrorAction onLoadError( * Returns an argument matcher for {@link Timeline} instances that ignores period and window uids. */ private static ArgumentMatcher noUid(Timeline timeline) { - return argument -> new NoUidTimeline(timeline).equals(new NoUidTimeline(argument)); + return argument -> timelinesAreSame(argument, timeline); } } diff --git a/libraries/test_utils/src/main/java/androidx/media3/test/utils/Action.java b/libraries/test_utils/src/main/java/androidx/media3/test/utils/Action.java index f025836ba2..cf5f420c6a 100644 --- a/libraries/test_utils/src/main/java/androidx/media3/test/utils/Action.java +++ b/libraries/test_utils/src/main/java/androidx/media3/test/utils/Action.java @@ -15,6 +15,8 @@ */ package androidx.media3.test.utils; +import static androidx.media3.test.utils.TestUtil.timelinesAreSame; + import android.os.Looper; import android.view.Surface; import androidx.annotation.Nullable; @@ -765,7 +767,7 @@ public WaitForTimelineChanged( @Nullable Timeline expectedTimeline, @Player.TimelineChangeReason int expectedReason) { super(tag, "WaitForTimelineChanged"); - this.expectedTimeline = expectedTimeline != null ? new NoUidTimeline(expectedTimeline) : null; + this.expectedTimeline = expectedTimeline; this.ignoreExpectedReason = false; this.expectedReason = expectedReason; } @@ -797,7 +799,7 @@ protected void doActionAndScheduleNextImpl( @Override public void onTimelineChanged( Timeline timeline, @Player.TimelineChangeReason int reason) { - if ((expectedTimeline == null || new NoUidTimeline(timeline).equals(expectedTimeline)) + if ((expectedTimeline == null || timelinesAreSame(timeline, expectedTimeline)) && (ignoreExpectedReason || expectedReason == reason)) { player.removeListener(this); nextAction.schedule(player, trackSelector, surface, handler); @@ -805,8 +807,8 @@ public void onTimelineChanged( } }; player.addListener(listener); - Timeline currentTimeline = new NoUidTimeline(player.getCurrentTimeline()); - if (currentTimeline.equals(expectedTimeline)) { + if (expectedTimeline != null + && timelinesAreSame(player.getCurrentTimeline(), expectedTimeline)) { player.removeListener(listener); nextAction.schedule(player, trackSelector, surface, handler); } diff --git a/libraries/test_utils/src/main/java/androidx/media3/test/utils/ExoPlayerTestRunner.java b/libraries/test_utils/src/main/java/androidx/media3/test/utils/ExoPlayerTestRunner.java index 3bf7bc3866..0cb7b4d935 100644 --- a/libraries/test_utils/src/main/java/androidx/media3/test/utils/ExoPlayerTestRunner.java +++ b/libraries/test_utils/src/main/java/androidx/media3/test/utils/ExoPlayerTestRunner.java @@ -43,6 +43,7 @@ import androidx.media3.exoplayer.source.MediaSource; import androidx.media3.exoplayer.trackselection.DefaultTrackSelector; import androidx.media3.exoplayer.upstream.BandwidthMeter; +import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -536,11 +537,8 @@ public ExoPlayerTestRunner blockUntilActionScheduleFinished(long timeoutMs) * @param timelines A list of expected {@link Timeline}s. */ public void assertTimelinesSame(Timeline... timelines) { - assertThat(this.timelines).hasSize(timelines.length); - for (int i = 0; i < timelines.length; i++) { - assertThat(new NoUidTimeline(timelines[i])) - .isEqualTo(new NoUidTimeline(this.timelines.get(i))); - } + TestUtil.assertTimelinesSame( + ImmutableList.copyOf(this.timelines), ImmutableList.copyOf(timelines)); } /** diff --git a/libraries/test_utils/src/main/java/androidx/media3/test/utils/NoUidTimeline.java b/libraries/test_utils/src/main/java/androidx/media3/test/utils/NoUidTimeline.java deleted file mode 100644 index 5cd0adad0c..0000000000 --- a/libraries/test_utils/src/main/java/androidx/media3/test/utils/NoUidTimeline.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2019 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 androidx.media3.test.utils; - -import androidx.media3.common.Timeline; -import androidx.media3.common.util.UnstableApi; -import androidx.media3.exoplayer.source.ForwardingTimeline; - -/** - * A timeline which wraps another timeline and overrides all window and period uids to 0. This is - * useful for testing timeline equality without taking uids into account. - */ -@UnstableApi -public class NoUidTimeline extends ForwardingTimeline { - - /** - * Creates an instance. - * - * @param timeline The underlying timeline. - */ - public NoUidTimeline(Timeline timeline) { - super(timeline); - } - - @Override - public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) { - timeline.getWindow(windowIndex, window, defaultPositionProjectionUs); - window.uid = 0; - return window; - } - - @Override - public Period getPeriod(int periodIndex, Period period, boolean setIds) { - timeline.getPeriod(periodIndex, period, setIds); - period.uid = 0; - return period; - } -} diff --git a/libraries/test_utils/src/main/java/androidx/media3/test/utils/TestUtil.java b/libraries/test_utils/src/main/java/androidx/media3/test/utils/TestUtil.java index a59377c27d..f6ac5ecb99 100644 --- a/libraries/test_utils/src/main/java/androidx/media3/test/utils/TestUtil.java +++ b/libraries/test_utils/src/main/java/androidx/media3/test/utils/TestUtil.java @@ -44,6 +44,7 @@ import androidx.media3.extractor.metadata.MetadataInputBuffer; import com.google.common.collect.ImmutableList; import com.google.common.primitives.Bytes; +import com.google.common.truth.Correspondence; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -207,11 +208,20 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { */ public static void assertTimelinesSame( List actualTimelines, List expectedTimelines) { - assertThat(actualTimelines).hasSize(expectedTimelines.size()); - for (int i = 0; i < actualTimelines.size(); i++) { - assertThat(new NoUidTimeline(actualTimelines.get(i))) - .isEqualTo(new NoUidTimeline(expectedTimelines.get(i))); - } + assertThat(actualTimelines) + .comparingElementsUsing( + Correspondence.from( + TestUtil::timelinesAreSame, "is equal to (ignoring Window.uid and Period.uid)")) + .containsExactlyElementsIn(expectedTimelines) + .inOrder(); + } + + /** + * Returns true if {@code thisTimeline} is equal to {@code thatTimeline}, ignoring {@link + * Timeline.Window#uid} and {@link Timeline.Period#uid} values. + */ + public static boolean timelinesAreSame(Timeline thisTimeline, Timeline thatTimeline) { + return new NoUidTimeline(thisTimeline).equals(new NoUidTimeline(thatTimeline)); } /** @@ -494,4 +504,47 @@ public static List getPublicMethods(Class clazz) { return list; } + + private static final class NoUidTimeline extends Timeline { + + private final Timeline delegate; + + public NoUidTimeline(Timeline timeline) { + this.delegate = timeline; + } + + @Override + public int getWindowCount() { + return delegate.getWindowCount(); + } + + @Override + public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) { + delegate.getWindow(windowIndex, window, defaultPositionProjectionUs); + window.uid = 0; + return window; + } + + @Override + public int getPeriodCount() { + return delegate.getPeriodCount(); + } + + @Override + public Period getPeriod(int periodIndex, Period period, boolean setIds) { + delegate.getPeriod(periodIndex, period, setIds); + period.uid = 0; + return period; + } + + @Override + public int getIndexOfPeriod(Object uid) { + return delegate.getIndexOfPeriod(uid); + } + + @Override + public Object getUidOfPeriod(int periodIndex) { + return 0; + } + } } From 6f9ce4056cc427076ba48189ab192e65234da4d8 Mon Sep 17 00:00:00 2001 From: ibaker Date: Tue, 28 Jun 2022 12:15:54 +0000 Subject: [PATCH 53/73] Consider shuffle order in Timeline.equals() Previously two timelines that differed only in shuffle order were considered equal, which resulted in no call to Player.Listener.onTimelineChanged when calling ExoPlayer.setShuffleOrder. This in turn resulted in no call to MediaControllerCompat.Callback.onQueueChanged. Also make a small fix inside ExoPlayerImpl.setShuffleOrder, to ensure that the new shuffle order is used when constructing the masked timeline. Issue: google/ExoPlayer#9889 #minor-release PiperOrigin-RevId: 457703727 --- RELEASENOTES.md | 5 ++ libraries/common/build.gradle | 1 + .../java/androidx/media3/common/Timeline.java | 28 +++++++++++ .../androidx/media3/common/TimelineTest.java | 45 +++++++++++++++++ .../media3/exoplayer/ExoPlayerImpl.java | 2 +- .../media3/exoplayer/ExoPlayerTest.java | 48 +++++++++++++++++++ .../media3/test/utils/FakeTimeline.java | 26 +++++++--- .../androidx/media3/test/utils/TestUtil.java | 38 ++++++++++++--- 8 files changed, 180 insertions(+), 13 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e5d9d9a4b4..87f187075f 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -2,6 +2,11 @@ ### Unreleased changes +* Core library: + * Ensure that changing the `ShuffleOrder` with `ExoPlayer.setShuffleOrder` + results in a call to `Player.Listener#onTimelineChanged` with + `reason=Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED` + ([#9889](https://github.com/google/ExoPlayer/issues/9889)). * Extractors: * Add support for AVI ([#2092](https://github.com/google/ExoPlayer/issues/2092)). diff --git a/libraries/common/build.gradle b/libraries/common/build.gradle index 048fe60f41..85169e2ec8 100644 --- a/libraries/common/build.gradle +++ b/libraries/common/build.gradle @@ -75,6 +75,7 @@ dependencies { testImplementation 'junit:junit:' + junitVersion testImplementation 'com.google.truth:truth:' + truthVersion testImplementation 'org.robolectric:robolectric:' + robolectricVersion + testImplementation project(modulePrefix + 'lib-exoplayer') testImplementation project(modulePrefix + 'test-utils') } diff --git a/libraries/common/src/main/java/androidx/media3/common/Timeline.java b/libraries/common/src/main/java/androidx/media3/common/Timeline.java index 3f665f8bfc..14b04065f5 100644 --- a/libraries/common/src/main/java/androidx/media3/common/Timeline.java +++ b/libraries/common/src/main/java/androidx/media3/common/Timeline.java @@ -1351,6 +1351,27 @@ public boolean equals(@Nullable Object obj) { return false; } } + + // Check shuffled order + int windowIndex = getFirstWindowIndex(/* shuffleModeEnabled= */ true); + if (windowIndex != other.getFirstWindowIndex(/* shuffleModeEnabled= */ true)) { + return false; + } + int lastWindowIndex = getLastWindowIndex(/* shuffleModeEnabled= */ true); + if (lastWindowIndex != other.getLastWindowIndex(/* shuffleModeEnabled= */ true)) { + return false; + } + while (windowIndex != lastWindowIndex) { + int nextWindowIndex = + getNextWindowIndex(windowIndex, Player.REPEAT_MODE_OFF, /* shuffleModeEnabled= */ true); + if (nextWindowIndex + != other.getNextWindowIndex( + windowIndex, Player.REPEAT_MODE_OFF, /* shuffleModeEnabled= */ true)) { + return false; + } + windowIndex = nextWindowIndex; + } + return true; } @@ -1367,6 +1388,13 @@ public int hashCode() { for (int i = 0; i < getPeriodCount(); i++) { result = 31 * result + getPeriod(i, period, /* setIds= */ true).hashCode(); } + + for (int windowIndex = getFirstWindowIndex(true); + windowIndex != C.INDEX_UNSET; + windowIndex = getNextWindowIndex(windowIndex, Player.REPEAT_MODE_OFF, true)) { + result = 31 * result + windowIndex; + } + return result; } diff --git a/libraries/common/src/test/java/androidx/media3/common/TimelineTest.java b/libraries/common/src/test/java/androidx/media3/common/TimelineTest.java index f2de751193..6844330e14 100644 --- a/libraries/common/src/test/java/androidx/media3/common/TimelineTest.java +++ b/libraries/common/src/test/java/androidx/media3/common/TimelineTest.java @@ -19,6 +19,7 @@ import androidx.annotation.Nullable; import androidx.media3.common.MediaItem.LiveConfiguration; +import androidx.media3.exoplayer.source.ShuffleOrder.DefaultShuffleOrder; import androidx.media3.test.utils.FakeTimeline; import androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition; import androidx.media3.test.utils.TimelineAsserts; @@ -64,6 +65,50 @@ public void multiPeriodTimeline() { TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ALL, false, 0); } + @Test + public void timelineEquals() { + ImmutableList timelineWindowDefinitions = + ImmutableList.of( + new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ 111), + new TimelineWindowDefinition(/* periodCount= */ 2, /* id= */ 222), + new TimelineWindowDefinition(/* periodCount= */ 3, /* id= */ 333)); + Timeline timeline1 = + new FakeTimeline(timelineWindowDefinitions.toArray(new TimelineWindowDefinition[0])); + Timeline timeline2 = + new FakeTimeline(timelineWindowDefinitions.toArray(new TimelineWindowDefinition[0])); + + assertThat(timeline1).isEqualTo(timeline2); + assertThat(timeline1.hashCode()).isEqualTo(timeline2.hashCode()); + } + + @Test + public void timelineEquals_includesShuffleOrder() { + ImmutableList timelineWindowDefinitions = + ImmutableList.of( + new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ 111), + new TimelineWindowDefinition(/* periodCount= */ 2, /* id= */ 222), + new TimelineWindowDefinition(/* periodCount= */ 3, /* id= */ 333)); + Timeline timeline = + new FakeTimeline( + new Object[0], + new DefaultShuffleOrder(timelineWindowDefinitions.size(), /* randomSeed= */ 5), + timelineWindowDefinitions.toArray(new TimelineWindowDefinition[0])); + Timeline timelineWithEquivalentShuffleOrder = + new FakeTimeline( + new Object[0], + new DefaultShuffleOrder(timelineWindowDefinitions.size(), /* randomSeed= */ 5), + timelineWindowDefinitions.toArray(new TimelineWindowDefinition[0])); + Timeline timelineWithDifferentShuffleOrder = + new FakeTimeline( + new Object[0], + new DefaultShuffleOrder(timelineWindowDefinitions.size(), /* randomSeed= */ 3), + timelineWindowDefinitions.toArray(new TimelineWindowDefinition[0])); + + assertThat(timeline).isEqualTo(timelineWithEquivalentShuffleOrder); + assertThat(timeline.hashCode()).isEqualTo(timelineWithEquivalentShuffleOrder.hashCode()); + assertThat(timeline).isNotEqualTo(timelineWithDifferentShuffleOrder); + } + @Test public void windowEquals() { MediaItem mediaItem = new MediaItem.Builder().setUri("uri").setTag(new Object()).build(); diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java index de4f574764..5bd1058641 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java @@ -710,6 +710,7 @@ public void moveMediaItems(int fromIndex, int toIndex, int newFromIndex) { @Override public void setShuffleOrder(ShuffleOrder shuffleOrder) { verifyApplicationThread(); + this.shuffleOrder = shuffleOrder; Timeline timeline = createMaskingTimeline(); PlaybackInfo newPlaybackInfo = maskTimelineAndPosition( @@ -718,7 +719,6 @@ public void setShuffleOrder(ShuffleOrder shuffleOrder) { maskWindowPositionMsOrGetPeriodPositionUs( timeline, getCurrentMediaItemIndex(), getCurrentPosition())); pendingOperationAcks++; - this.shuffleOrder = shuffleOrder; internalPlayer.setShuffleOrder(shuffleOrder); updatePlaybackInfo( newPlaybackInfo, diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java index dbbb47fc69..1e0b0338ba 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java @@ -125,6 +125,7 @@ import androidx.media3.exoplayer.source.MediaSource; import androidx.media3.exoplayer.source.MediaSource.MediaPeriodId; import androidx.media3.exoplayer.source.MediaSourceEventListener; +import androidx.media3.exoplayer.source.ShuffleOrder; import androidx.media3.exoplayer.source.SinglePeriodTimeline; import androidx.media3.exoplayer.source.TrackGroupArray; import androidx.media3.exoplayer.source.ads.ServerSideAdInsertionMediaSource; @@ -6517,6 +6518,53 @@ public void run(ExoPlayer player) { assertThat(positionAfterSetShuffleOrder.get()).isAtLeast(5000); } + @Test + public void setShuffleOrder_notifiesTimelineChanged() throws Exception { + ExoPlayer player = + new TestExoPlayerBuilder(context) + .setClock(new FakeClock(/* isAutoAdvancing= */ true)) + .build(); + // No callback expected for this call, because the (empty) timeline doesn't change. We start + // with a deterministic shuffle order, to ensure when we call setShuffleOrder again below the + // order is definitely different (otherwise the test is flaky when the existing shuffle order + // matches the shuffle order passed in below). + player.setShuffleOrder(new FakeShuffleOrder(0)); + player.setMediaSources( + ImmutableList.of(new FakeMediaSource(), new FakeMediaSource(), new FakeMediaSource())); + Player.Listener mockListener = mock(Player.Listener.class); + player.addListener(mockListener); + player.prepare(); + TestPlayerRunHelper.playUntilPosition(player, /* mediaItemIndex= */ 0, /* positionMs= */ 5000); + player.play(); + ShuffleOrder.DefaultShuffleOrder newShuffleOrder = + new ShuffleOrder.DefaultShuffleOrder(player.getMediaItemCount(), /* randomSeed= */ 5); + player.setShuffleOrder(newShuffleOrder); + TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_ENDED); + player.release(); + + ArgumentCaptor timelineCaptor = ArgumentCaptor.forClass(Timeline.class); + verify(mockListener) + .onTimelineChanged( + timelineCaptor.capture(), eq(Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED)); + + Timeline capturedTimeline = Iterables.getOnlyElement(timelineCaptor.getAllValues()); + List newShuffleOrderIndexes = new ArrayList<>(newShuffleOrder.getLength()); + for (int i = newShuffleOrder.getFirstIndex(); + i != C.INDEX_UNSET; + i = newShuffleOrder.getNextIndex(i)) { + newShuffleOrderIndexes.add(i); + } + List capturedTimelineShuffleIndexes = new ArrayList<>(newShuffleOrder.getLength()); + for (int i = capturedTimeline.getFirstWindowIndex(/* shuffleModeEnabled= */ true); + i != C.INDEX_UNSET; + i = + capturedTimeline.getNextWindowIndex( + i, Player.REPEAT_MODE_OFF, /* shuffleModeEnabled= */ true)) { + capturedTimelineShuffleIndexes.add(i); + } + assertThat(capturedTimelineShuffleIndexes).isEqualTo(newShuffleOrderIndexes); + } + @Test public void setMediaSources_empty_whenEmpty_correctMaskingMediaItemIndex() throws Exception { final int[] currentMediaItemIndices = {C.INDEX_UNSET, C.INDEX_UNSET, C.INDEX_UNSET}; diff --git a/libraries/test_utils/src/main/java/androidx/media3/test/utils/FakeTimeline.java b/libraries/test_utils/src/main/java/androidx/media3/test/utils/FakeTimeline.java index 75e3d26e7b..9aad788a7a 100644 --- a/libraries/test_utils/src/main/java/androidx/media3/test/utils/FakeTimeline.java +++ b/libraries/test_utils/src/main/java/androidx/media3/test/utils/FakeTimeline.java @@ -29,6 +29,7 @@ import androidx.media3.common.util.Assertions; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; +import androidx.media3.exoplayer.source.ShuffleOrder; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import java.util.ArrayList; @@ -275,7 +276,7 @@ public TimelineWindowDefinition( private final TimelineWindowDefinition[] windowDefinitions; private final Object[] manifests; private final int[] periodOffsets; - private final FakeShuffleOrder fakeShuffleOrder; + private final ShuffleOrder shuffleOrder; /** * Returns an ad playback state with the specified number of ads in each of the specified ad @@ -395,6 +396,19 @@ public FakeTimeline(TimelineWindowDefinition... windowDefinitions) { * @param windowDefinitions A list of {@link TimelineWindowDefinition}s. */ public FakeTimeline(Object[] manifests, TimelineWindowDefinition... windowDefinitions) { + this(manifests, new FakeShuffleOrder(windowDefinitions.length), windowDefinitions); + } + + /** + * Creates a fake timeline with the given window definitions and {@link + * androidx.media3.exoplayer.source.ShuffleOrder}. + * + * @param windowDefinitions A list of {@link TimelineWindowDefinition}s. + */ + public FakeTimeline( + Object[] manifests, + ShuffleOrder shuffleOrder, + TimelineWindowDefinition... windowDefinitions) { this.manifests = new Object[windowDefinitions.length]; System.arraycopy(manifests, 0, this.manifests, 0, min(this.manifests.length, manifests.length)); this.windowDefinitions = windowDefinitions; @@ -403,7 +417,7 @@ public FakeTimeline(Object[] manifests, TimelineWindowDefinition... windowDefini for (int i = 0; i < windowDefinitions.length; i++) { periodOffsets[i + 1] = periodOffsets[i] + windowDefinitions[i].periodCount; } - fakeShuffleOrder = new FakeShuffleOrder(windowDefinitions.length); + this.shuffleOrder = shuffleOrder; } @Override @@ -422,7 +436,7 @@ public int getNextWindowIndex( ? getFirstWindowIndex(shuffleModeEnabled) : C.INDEX_UNSET; } - return shuffleModeEnabled ? fakeShuffleOrder.getNextIndex(windowIndex) : windowIndex + 1; + return shuffleModeEnabled ? shuffleOrder.getNextIndex(windowIndex) : windowIndex + 1; } @Override @@ -436,20 +450,20 @@ public int getPreviousWindowIndex( ? getLastWindowIndex(shuffleModeEnabled) : C.INDEX_UNSET; } - return shuffleModeEnabled ? fakeShuffleOrder.getPreviousIndex(windowIndex) : windowIndex - 1; + return shuffleModeEnabled ? shuffleOrder.getPreviousIndex(windowIndex) : windowIndex - 1; } @Override public int getLastWindowIndex(boolean shuffleModeEnabled) { return shuffleModeEnabled - ? fakeShuffleOrder.getLastIndex() + ? shuffleOrder.getLastIndex() : super.getLastWindowIndex(/* shuffleModeEnabled= */ false); } @Override public int getFirstWindowIndex(boolean shuffleModeEnabled) { return shuffleModeEnabled - ? fakeShuffleOrder.getFirstIndex() + ? shuffleOrder.getFirstIndex() : super.getFirstWindowIndex(/* shuffleModeEnabled= */ false); } diff --git a/libraries/test_utils/src/main/java/androidx/media3/test/utils/TestUtil.java b/libraries/test_utils/src/main/java/androidx/media3/test/utils/TestUtil.java index f6ac5ecb99..27872827fa 100644 --- a/libraries/test_utils/src/main/java/androidx/media3/test/utils/TestUtil.java +++ b/libraries/test_utils/src/main/java/androidx/media3/test/utils/TestUtil.java @@ -200,8 +200,12 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { /** * Asserts that the actual timelines are the same to the expected timelines. This assert differs - * from testing equality by not comparing period ids which may be different due to id mapping of - * child source period ids. + * from testing equality by not comparing: + * + *

    * * @param actualTimelines A list of actual {@link Timeline timelines}. * @param expectedTimelines A list of expected {@link Timeline timelines}. @@ -218,10 +222,11 @@ public static void assertTimelinesSame( /** * Returns true if {@code thisTimeline} is equal to {@code thatTimeline}, ignoring {@link - * Timeline.Window#uid} and {@link Timeline.Period#uid} values. + * Timeline.Window#uid} and {@link Timeline.Period#uid} values, and shuffle order. */ public static boolean timelinesAreSame(Timeline thisTimeline, Timeline thatTimeline) { - return new NoUidTimeline(thisTimeline).equals(new NoUidTimeline(thatTimeline)); + return new NoUidOrShufflingTimeline(thisTimeline) + .equals(new NoUidOrShufflingTimeline(thatTimeline)); } /** @@ -505,11 +510,11 @@ public static List getPublicMethods(Class clazz) { return list; } - private static final class NoUidTimeline extends Timeline { + private static final class NoUidOrShufflingTimeline extends Timeline { private final Timeline delegate; - public NoUidTimeline(Timeline timeline) { + public NoUidOrShufflingTimeline(Timeline timeline) { this.delegate = timeline; } @@ -518,6 +523,27 @@ public int getWindowCount() { return delegate.getWindowCount(); } + @Override + public int getNextWindowIndex(int windowIndex, int repeatMode, boolean shuffleModeEnabled) { + return delegate.getNextWindowIndex(windowIndex, repeatMode, /* shuffleModeEnabled= */ false); + } + + @Override + public int getPreviousWindowIndex(int windowIndex, int repeatMode, boolean shuffleModeEnabled) { + return delegate.getPreviousWindowIndex( + windowIndex, repeatMode, /* shuffleModeEnabled= */ false); + } + + @Override + public int getLastWindowIndex(boolean shuffleModeEnabled) { + return delegate.getLastWindowIndex(/* shuffleModeEnabled= */ false); + } + + @Override + public int getFirstWindowIndex(boolean shuffleModeEnabled) { + return delegate.getFirstWindowIndex(/* shuffleModeEnabled= */ false); + } + @Override public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) { delegate.getWindow(windowIndex, window, defaultPositionProjectionUs); From 87beb273e464d291423ccb4129c83f36195343f1 Mon Sep 17 00:00:00 2001 From: hschlueter Date: Wed, 29 Jun 2022 10:28:54 +0000 Subject: [PATCH 54/73] Fix outputHeight pass-through condition. The outputHeight in the TransformationRequest is the height of the frame as it would be displayed (i.e., after applying any rotation specified in the format). So pass-through should only be used if the requested outputHeight matches the input format's height after applying the rotation. PiperOrigin-RevId: 457934867 --- .../media3/transformer/TransformerVideoRenderer.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerVideoRenderer.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerVideoRenderer.java index b97b14c57e..03902a400d 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerVideoRenderer.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerVideoRenderer.java @@ -148,8 +148,11 @@ private boolean shouldPassthrough(Format inputFormat) { if (transformationRequest.scaleY != 1f) { return false; } + // The decoder rotates encoded frames for display by inputFormat.rotationDegrees. + int decodedHeight = + (inputFormat.rotationDegrees % 180 == 0) ? inputFormat.height : inputFormat.width; if (transformationRequest.outputHeight != C.LENGTH_UNSET - && transformationRequest.outputHeight != inputFormat.height) { + && transformationRequest.outputHeight != decodedHeight) { return false; } if (!effects.isEmpty()) { From 621617f98103f67082e47bf585460d90c00ea32f Mon Sep 17 00:00:00 2001 From: rohks Date: Wed, 29 Jun 2022 14:47:12 +0000 Subject: [PATCH 55/73] Make `MetadataRenderer` configurable to output metadata early. PiperOrigin-RevId: 457974611 --- RELEASENOTES.md | 6 ++ .../exoplayer/metadata/MetadataRenderer.java | 39 +++++++- .../metadata/MetadataRendererTest.java | 94 +++++++++++++++++-- .../dash/e2etest/DashPlaybackTest.java | 70 ++++++++++++++ .../dash/metadata_from_early_output.dump | 10 ++ .../dash/metadata_from_timely_output.dump | 7 ++ 6 files changed, 218 insertions(+), 8 deletions(-) create mode 100644 libraries/test_data/src/test/assets/playbackdumps/dash/metadata_from_early_output.dump create mode 100644 libraries/test_data/src/test/assets/playbackdumps/dash/metadata_from_timely_output.dump diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 87f187075f..e0a6694d68 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -12,6 +12,12 @@ ([#2092](https://github.com/google/ExoPlayer/issues/2092)). * Fix parsing of H265 short term reference picture sets ([#10316](https://github.com/google/ExoPlayer/issues/10316)). +* Metadata: + * `MetadataRenderer` can now be configured to render metadata as soon as + they are available. Create an instance with + `MetadataRenderer(MetadataOutput, Looper, + MetadataDecoderFactory, boolean)` to specify whether the renderer will + output metadata early or in sync with the player position. * RTSP: * Add RTP reader for H263 ([#63](https://github.com/androidx/media/pull/63)). diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/metadata/MetadataRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/metadata/MetadataRenderer.java index 0c7b16f8f3..edaa2d0c5c 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/metadata/MetadataRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/metadata/MetadataRenderer.java @@ -39,7 +39,12 @@ import java.util.List; import org.checkerframework.dataflow.qual.SideEffectFree; -/** A renderer for metadata. */ +/** + * A renderer for metadata. + * + *

    The renderer can be configured to render metadata as soon as they are available using {@link + * #MetadataRenderer(MetadataOutput, Looper, MetadataDecoderFactory, boolean)}. + */ @UnstableApi public final class MetadataRenderer extends BaseRenderer implements Callback { @@ -50,6 +55,7 @@ public final class MetadataRenderer extends BaseRenderer implements Callback { private final MetadataOutput output; @Nullable private final Handler outputHandler; private final MetadataInputBuffer buffer; + private final boolean outputMetadataEarly; @Nullable private MetadataDecoder decoder; private boolean inputStreamEnded; @@ -59,6 +65,9 @@ public final class MetadataRenderer extends BaseRenderer implements Callback { private long outputStreamOffsetUs; /** + * Creates an instance that uses {@link MetadataDecoderFactory#DEFAULT} to create {@link + * MetadataDecoder} instances. + * * @param output The output. * @param outputLooper The looper associated with the thread on which the output should be called. * If the output makes use of standard Android UI components, then this should normally be the @@ -71,6 +80,8 @@ public MetadataRenderer(MetadataOutput output, @Nullable Looper outputLooper) { } /** + * Creates an instance. + * * @param output The output. * @param outputLooper The looper associated with the thread on which the output should be called. * If the output makes use of standard Android UI components, then this should normally be the @@ -81,11 +92,34 @@ public MetadataRenderer(MetadataOutput output, @Nullable Looper outputLooper) { */ public MetadataRenderer( MetadataOutput output, @Nullable Looper outputLooper, MetadataDecoderFactory decoderFactory) { + this(output, outputLooper, decoderFactory, /* outputMetadataEarly= */ false); + } + + /** + * Creates an instance. + * + * @param output The output. + * @param outputLooper The looper associated with the thread on which the output should be called. + * If the output makes use of standard Android UI components, then this should normally be the + * looper associated with the application's main thread, which can be obtained using {@link + * android.app.Activity#getMainLooper()}. Null may be passed if the output should be called + * directly on the player's internal rendering thread. + * @param decoderFactory A factory from which to obtain {@link MetadataDecoder} instances. + * @param outputMetadataEarly Whether the renderer outputs metadata early. When {@code true}, + * {@link #render} will output metadata as soon as they are available to the renderer, + * otherwise {@link #render} will output metadata in sync with the rendering position. + */ + public MetadataRenderer( + MetadataOutput output, + @Nullable Looper outputLooper, + MetadataDecoderFactory decoderFactory, + boolean outputMetadataEarly) { super(C.TRACK_TYPE_METADATA); this.output = Assertions.checkNotNull(output); this.outputHandler = outputLooper == null ? null : Util.createHandler(outputLooper, /* callback= */ this); this.decoderFactory = Assertions.checkNotNull(decoderFactory); + this.outputMetadataEarly = outputMetadataEarly; buffer = new MetadataInputBuffer(); outputStreamOffsetUs = C.TIME_UNSET; } @@ -217,7 +251,8 @@ private void readMetadata() { private boolean outputMetadata(long positionUs) { boolean didOutput = false; if (pendingMetadata != null - && pendingMetadata.presentationTimeUs <= getPresentationTimeUs(positionUs)) { + && (outputMetadataEarly + || pendingMetadata.presentationTimeUs <= getPresentationTimeUs(positionUs))) { invokeRenderer(pendingMetadata); pendingMetadata = null; didOutput = true; diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/metadata/MetadataRendererTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/metadata/MetadataRendererTest.java index 3e77274924..f4d5b34c6e 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/metadata/MetadataRendererTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/metadata/MetadataRendererTest.java @@ -145,16 +145,87 @@ public void decodeMetadata_skipsMalformedWrappedMetadata() throws Exception { assertThat(metadata).isEmpty(); } + @Test + public void renderMetadata_withTimelyOutput() throws Exception { + EventMessage emsg = + new EventMessage( + "urn:test-scheme-id", + /* value= */ "", + /* durationMs= */ 1, + /* id= */ 0, + "Test data".getBytes(UTF_8)); + byte[] encodedEmsg = eventMessageEncoder.encode(emsg); + List metadata = new ArrayList<>(); + MetadataRenderer renderer = + new MetadataRenderer(/* output= */ metadata::add, /* outputLooper= */ null); + FakeSampleStream fakeSampleStream = + createFakeSampleStream( + ImmutableList.of( + sample(/* timeUs= */ 100_000, C.BUFFER_FLAG_KEY_FRAME, encodedEmsg), + sample(/* timeUs= */ 1_000_000, C.BUFFER_FLAG_KEY_FRAME, encodedEmsg), + END_OF_STREAM_ITEM)); + fakeSampleStream.writeData(/* startPositionUs= */ 0); + renderer.replaceStream( + new Format[] {EMSG_FORMAT}, + fakeSampleStream, + /* startPositionUs= */ 0L, + /* offsetUs= */ 0L); + + // Call render() twice, the first call is to read the format and the second call will read the + // metadata. + renderer.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0); + renderer.render(/* positionUs= */ 500_000, /* elapsedRealtimeUs= */ 0); + + assertThat(metadata).hasSize(1); + assertThat(metadata.get(0).presentationTimeUs).isEqualTo(100_000); + } + + @Test + public void renderMetadata_withEarlyOutput() throws Exception { + EventMessage emsg = + new EventMessage( + "urn:test-scheme-id", + /* value= */ "", + /* durationMs= */ 1, + /* id= */ 0, + "Test data".getBytes(UTF_8)); + byte[] encodedEmsg = eventMessageEncoder.encode(emsg); + List metadata = new ArrayList<>(); + MetadataRenderer renderer = + new MetadataRenderer( + /* output= */ metadata::add, + /* outputLooper= */ null, + MetadataDecoderFactory.DEFAULT, + /* outputMetadataEarly= */ true); + FakeSampleStream fakeSampleStream = + createFakeSampleStream( + ImmutableList.of( + sample(/* timeUs= */ 100_000, C.BUFFER_FLAG_KEY_FRAME, encodedEmsg), + sample(/* timeUs= */ 1_000_000, C.BUFFER_FLAG_KEY_FRAME, encodedEmsg), + END_OF_STREAM_ITEM)); + fakeSampleStream.writeData(/* startPositionUs= */ 0); + renderer.replaceStream( + new Format[] {EMSG_FORMAT}, + fakeSampleStream, + /* startPositionUs= */ 0L, + /* offsetUs= */ 0L); + + // Call render() twice, the first call is to read the format and the second call will read the + // metadata. + renderer.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0); + renderer.render(/* positionUs= */ 500_000, /* elapsedRealtimeUs= */ 0); + + // The renderer outputs metadata early. + assertThat(metadata).hasSize(2); + assertThat(metadata.get(0).presentationTimeUs).isEqualTo(100_000); + assertThat(metadata.get(1).presentationTimeUs).isEqualTo(1_000_000); + } + private static List runRenderer(byte[] input) throws ExoPlaybackException { List metadata = new ArrayList<>(); MetadataRenderer renderer = new MetadataRenderer(metadata::add, /* outputLooper= */ null); FakeSampleStream fakeSampleStream = - new FakeSampleStream( - new DefaultAllocator(/* trimOnReset= */ true, /* individualAllocationSize= */ 1024), - /* mediaSourceEventDispatcher= */ null, - DrmSessionManager.DRM_UNSUPPORTED, - new DrmSessionEventListener.EventDispatcher(), - EMSG_FORMAT, + createFakeSampleStream( ImmutableList.of( sample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME, input), END_OF_STREAM_ITEM)); fakeSampleStream.writeData(/* startPositionUs= */ 0); @@ -169,6 +240,17 @@ private static List runRenderer(byte[] input) throws ExoPlaybackExcept return Collections.unmodifiableList(metadata); } + private static FakeSampleStream createFakeSampleStream( + ImmutableList samples) { + return new FakeSampleStream( + new DefaultAllocator(/* trimOnReset= */ true, /* individualAllocationSize= */ 1024), + /* mediaSourceEventDispatcher= */ null, + DrmSessionManager.DRM_UNSUPPORTED, + new DrmSessionEventListener.EventDispatcher(), + EMSG_FORMAT, + samples); + } + /** * Builds an ID3v2 tag containing a single 'user defined text information frame' (id='TXXX') with * {@code description} and {@code value}. diff --git a/libraries/exoplayer_dash/src/test/java/androidx/media3/exoplayer/dash/e2etest/DashPlaybackTest.java b/libraries/exoplayer_dash/src/test/java/androidx/media3/exoplayer/dash/e2etest/DashPlaybackTest.java index 762eefc28f..ce9d2cc779 100644 --- a/libraries/exoplayer_dash/src/test/java/androidx/media3/exoplayer/dash/e2etest/DashPlaybackTest.java +++ b/libraries/exoplayer_dash/src/test/java/androidx/media3/exoplayer/dash/e2etest/DashPlaybackTest.java @@ -23,6 +23,10 @@ import androidx.media3.common.MediaItem; import androidx.media3.common.Player; import androidx.media3.exoplayer.ExoPlayer; +import androidx.media3.exoplayer.Renderer; +import androidx.media3.exoplayer.RenderersFactory; +import androidx.media3.exoplayer.metadata.MetadataDecoderFactory; +import androidx.media3.exoplayer.metadata.MetadataRenderer; import androidx.media3.exoplayer.trackselection.DefaultTrackSelector; import androidx.media3.test.utils.CapturingRenderersFactory; import androidx.media3.test.utils.DumpFileAsserts; @@ -96,4 +100,70 @@ public void emsgNearToPeriodBoundary() throws Exception { DumpFileAsserts.assertOutput( applicationContext, playbackOutput, "playbackdumps/dash/emsg.dump"); } + + @Test + public void renderMetadata_withTimelyOutput() throws Exception { + Context applicationContext = ApplicationProvider.getApplicationContext(); + RenderersFactory renderersFactory = + (eventHandler, + videoRendererEventListener, + audioRendererEventListener, + textRendererOutput, + metadataRendererOutput) -> + new Renderer[] {new MetadataRenderer(metadataRendererOutput, eventHandler.getLooper())}; + ExoPlayer player = + new ExoPlayer.Builder(applicationContext, renderersFactory) + .setClock(new FakeClock(/* isAutoAdvancing= */ true)) + .build(); + player.setVideoSurface(new Surface(new SurfaceTexture(/* texName= */ 1))); + CapturingRenderersFactory capturingRenderersFactory = + new CapturingRenderersFactory(applicationContext); + PlaybackOutput playbackOutput = PlaybackOutput.register(player, capturingRenderersFactory); + + player.setMediaItem(MediaItem.fromUri("asset:///media/dash/emsg/sample.mpd")); + player.prepare(); + player.play(); + TestPlayerRunHelper.playUntilPosition(player, /* mediaItemIndex= */ 0, /* positionMs= */ 500); + player.release(); + + // Ensure output contains metadata up to the playback position. + DumpFileAsserts.assertOutput( + applicationContext, playbackOutput, "playbackdumps/dash/metadata_from_timely_output.dump"); + } + + @Test + public void renderMetadata_withEarlyOutput() throws Exception { + Context applicationContext = ApplicationProvider.getApplicationContext(); + RenderersFactory renderersFactory = + (eventHandler, + videoRendererEventListener, + audioRendererEventListener, + textRendererOutput, + metadataRendererOutput) -> + new Renderer[] { + new MetadataRenderer( + metadataRendererOutput, + eventHandler.getLooper(), + MetadataDecoderFactory.DEFAULT, + /* outputMetadataEarly= */ true) + }; + ExoPlayer player = + new ExoPlayer.Builder(applicationContext, renderersFactory) + .setClock(new FakeClock(/* isAutoAdvancing= */ true)) + .build(); + player.setVideoSurface(new Surface(new SurfaceTexture(/* texName= */ 1))); + CapturingRenderersFactory capturingRenderersFactory = + new CapturingRenderersFactory(applicationContext); + PlaybackOutput playbackOutput = PlaybackOutput.register(player, capturingRenderersFactory); + + player.setMediaItem(MediaItem.fromUri("asset:///media/dash/emsg/sample.mpd")); + player.prepare(); + player.play(); + TestPlayerRunHelper.playUntilPosition(player, /* mediaItemIndex= */ 0, /* positionMs= */ 500); + player.release(); + + // Ensure output contains all metadata irrespective of the playback position. + DumpFileAsserts.assertOutput( + applicationContext, playbackOutput, "playbackdumps/dash/metadata_from_early_output.dump"); + } } diff --git a/libraries/test_data/src/test/assets/playbackdumps/dash/metadata_from_early_output.dump b/libraries/test_data/src/test/assets/playbackdumps/dash/metadata_from_early_output.dump new file mode 100644 index 0000000000..e8261bd2df --- /dev/null +++ b/libraries/test_data/src/test/assets/playbackdumps/dash/metadata_from_early_output.dump @@ -0,0 +1,10 @@ +MetadataOutput: + Metadata[0]: + presentationTimeUs = 100000 + entry[0] = EMSG: scheme=urn:mpeg:dash:event:callback:2015, id=0, durationMs=1000, value=1 + Metadata[1]: + presentationTimeUs = 100000 + entry[0] = EMSG: scheme=urn:mpeg:dash:event:callback:2015, id=1, durationMs=1000, value=1 + Metadata[2]: + presentationTimeUs = 1000000 + entry[0] = EMSG: scheme=urn:mpeg:dash:event:callback:2015, id=2, durationMs=1000, value=1 diff --git a/libraries/test_data/src/test/assets/playbackdumps/dash/metadata_from_timely_output.dump b/libraries/test_data/src/test/assets/playbackdumps/dash/metadata_from_timely_output.dump new file mode 100644 index 0000000000..ebbd67120a --- /dev/null +++ b/libraries/test_data/src/test/assets/playbackdumps/dash/metadata_from_timely_output.dump @@ -0,0 +1,7 @@ +MetadataOutput: + Metadata[0]: + presentationTimeUs = 100000 + entry[0] = EMSG: scheme=urn:mpeg:dash:event:callback:2015, id=0, durationMs=1000, value=1 + Metadata[1]: + presentationTimeUs = 100000 + entry[0] = EMSG: scheme=urn:mpeg:dash:event:callback:2015, id=1, durationMs=1000, value=1 From 3fc6a66527c6af940b45dd0d2ce1f3fb19491fa0 Mon Sep 17 00:00:00 2001 From: ibaker Date: Wed, 29 Jun 2022 16:10:11 +0000 Subject: [PATCH 56/73] Ensure TalkBack announces the selected playback speed in the UI menu Issue: google/ExoPlayer#10298 #minor-release PiperOrigin-RevId: 457991028 --- RELEASENOTES.md | 4 ++++ .../main/java/androidx/media3/ui/PlayerControlView.java | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e0a6694d68..1032af35ba 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -18,6 +18,10 @@ `MetadataRenderer(MetadataOutput, Looper, MetadataDecoderFactory, boolean)` to specify whether the renderer will output metadata early or in sync with the player position. +* UI: + * Ensure TalkBack announces the currently active speed option in the + playback controls menu + ([#10298](https://github.com/google/ExoPlayer/issues/10298)). * RTSP: * Add RTP reader for H263 ([#63](https://github.com/androidx/media/pull/63)). diff --git a/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java b/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java index 7ab349bd1d..8ec6d27498 100644 --- a/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java +++ b/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java @@ -1811,7 +1811,13 @@ public void onBindViewHolder(SubSettingViewHolder holder, int position) { if (position < playbackSpeedTexts.length) { holder.textView.setText(playbackSpeedTexts[position]); } - holder.checkView.setVisibility(position == selectedIndex ? VISIBLE : INVISIBLE); + if (position == selectedIndex) { + holder.itemView.setSelected(true); + holder.checkView.setVisibility(VISIBLE); + } else { + holder.itemView.setSelected(false); + holder.checkView.setVisibility(INVISIBLE); + } holder.itemView.setOnClickListener( v -> { if (position != selectedIndex) { From 234015cb952fbdaf274f1fa9005ddc0d2b4ba17a Mon Sep 17 00:00:00 2001 From: hschlueter Date: Wed, 29 Jun 2022 17:27:05 +0000 Subject: [PATCH 57/73] FrameProcessor: Replace SurfaceInfo.Provider with setter. The FinalMatrixTransformationProcessorWrapper ensures that the surface is only replaced when it is not being rendered to and vice versa. PiperOrigin-RevId: 458007639 --- .../GlEffectsFrameProcessorPixelTest.java | 20 +-- ...lMatrixTransformationProcessorWrapper.java | 156 ++++++++++-------- .../media3/transformer/FrameProcessor.java | 26 +++ .../transformer/GlEffectsFrameProcessor.java | 114 +++++++------ .../media3/transformer/SurfaceInfo.java | 33 ++-- .../VideoTranscodingSamplePipeline.java | 34 ++-- .../transformer/VideoEncoderWrapperTest.java | 12 +- 7 files changed, 235 insertions(+), 160 deletions(-) diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java index d5e4f7c96e..06512ca0e9 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java @@ -356,6 +356,16 @@ private void setUpAndPrepareFirstFrame(float pixelWidthHeightRatio, List { - outputImageReader = - ImageReader.newInstance( - requestedWidth, - requestedHeight, - PixelFormat.RGBA_8888, - /* maxImages= */ 1); - return new SurfaceInfo( - outputImageReader.getSurface(), requestedWidth, requestedHeight); - }, Transformer.DebugViewProvider.NONE, /* enableExperimentalHdrEditing= */ false)); glEffectsFrameProcessor.setInputFrameInfo( diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java index 996fce157b..a927c5ce3c 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java @@ -34,6 +34,7 @@ import androidx.media3.common.C; import androidx.media3.common.util.GlUtil; import androidx.media3.common.util.Log; +import androidx.media3.common.util.Util; import com.google.common.collect.ImmutableList; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @@ -57,7 +58,6 @@ private final ImmutableList matrixTransformations; private final EGLDisplay eglDisplay; private final EGLContext eglContext; - private final SurfaceInfo.Provider outputSurfaceProvider; private final long streamOffsetUs; private final Transformer.DebugViewProvider debugViewProvider; private final FrameProcessor.Listener frameProcessorListener; @@ -66,17 +66,23 @@ private int inputWidth; private int inputHeight; @Nullable private MatrixTransformationProcessor matrixTransformationProcessor; - @Nullable private SurfaceInfo outputSurfaceInfo; - @Nullable private EGLSurface outputEglSurface; @Nullable private SurfaceViewWrapper debugSurfaceViewWrapper; private @MonotonicNonNull Listener listener; + private @MonotonicNonNull Size outputSizeBeforeSurfaceTransformation; + + @GuardedBy("this") + @Nullable + private SurfaceInfo outputSurfaceInfo; + + @GuardedBy("this") + @Nullable + private EGLSurface outputEglSurface; public FinalMatrixTransformationProcessorWrapper( Context context, EGLDisplay eglDisplay, EGLContext eglContext, ImmutableList matrixTransformations, - SurfaceInfo.Provider outputSurfaceProvider, long streamOffsetUs, FrameProcessor.Listener frameProcessorListener, Transformer.DebugViewProvider debugViewProvider, @@ -85,7 +91,6 @@ public FinalMatrixTransformationProcessorWrapper( this.matrixTransformations = matrixTransformations; this.eglDisplay = eglDisplay; this.eglContext = eglContext; - this.outputSurfaceProvider = outputSurfaceProvider; this.streamOffsetUs = streamOffsetUs; this.debugViewProvider = debugViewProvider; this.frameProcessorListener = frameProcessorListener; @@ -107,28 +112,30 @@ public void setListener(Listener listener) { @Override public boolean maybeQueueInputFrame(TextureInfo inputTexture, long presentationTimeUs) { try { - if (!ensureConfigured(inputTexture.width, inputTexture.height)) { - return false; - } - - EGLSurface outputEglSurface = this.outputEglSurface; - SurfaceInfo outputSurfaceInfo = this.outputSurfaceInfo; - MatrixTransformationProcessor matrixTransformationProcessor = - this.matrixTransformationProcessor; + synchronized (this) { + if (!ensureConfigured(inputTexture.width, inputTexture.height)) { + return false; + } - GlUtil.focusEglSurface( - eglDisplay, - eglContext, - outputEglSurface, - outputSurfaceInfo.width, - outputSurfaceInfo.height); - GlUtil.clearOutputFrame(); - matrixTransformationProcessor.drawFrame(inputTexture.texId, presentationTimeUs); - EGLExt.eglPresentationTimeANDROID( - eglDisplay, - outputEglSurface, - /* presentationTimeNs= */ (presentationTimeUs + streamOffsetUs) * 1000); - EGL14.eglSwapBuffers(eglDisplay, outputEglSurface); + EGLSurface outputEglSurface = this.outputEglSurface; + SurfaceInfo outputSurfaceInfo = this.outputSurfaceInfo; + MatrixTransformationProcessor matrixTransformationProcessor = + this.matrixTransformationProcessor; + + GlUtil.focusEglSurface( + eglDisplay, + eglContext, + outputEglSurface, + outputSurfaceInfo.width, + outputSurfaceInfo.height); + GlUtil.clearOutputFrame(); + matrixTransformationProcessor.drawFrame(inputTexture.texId, presentationTimeUs); + EGLExt.eglPresentationTimeANDROID( + eglDisplay, + outputEglSurface, + /* presentationTimeNs= */ (presentationTimeUs + streamOffsetUs) * 1000); + EGL14.eglSwapBuffers(eglDisplay, outputEglSurface); + } } catch (FrameProcessingException | GlUtil.GlException e) { frameProcessorListener.onFrameProcessingError( FrameProcessingException.from(e, presentationTimeUs)); @@ -156,24 +163,25 @@ public boolean maybeQueueInputFrame(TextureInfo inputTexture, long presentationT @EnsuresNonNullIf( expression = {"outputSurfaceInfo", "outputEglSurface", "matrixTransformationProcessor"}, result = true) - private boolean ensureConfigured(int inputWidth, int inputHeight) + private synchronized boolean ensureConfigured(int inputWidth, int inputHeight) throws FrameProcessingException, GlUtil.GlException { - if (inputWidth == this.inputWidth - && inputHeight == this.inputHeight - && outputSurfaceInfo != null - && outputEglSurface != null - && matrixTransformationProcessor != null) { - return true; + + if (this.inputWidth != inputWidth + || this.inputHeight != inputHeight + || this.outputSizeBeforeSurfaceTransformation == null) { + this.inputWidth = inputWidth; + this.inputHeight = inputHeight; + Size outputSizeBeforeSurfaceTransformation = + MatrixUtils.configureAndGetOutputSize(inputWidth, inputHeight, matrixTransformations); + if (!Util.areEqual( + this.outputSizeBeforeSurfaceTransformation, outputSizeBeforeSurfaceTransformation)) { + this.outputSizeBeforeSurfaceTransformation = outputSizeBeforeSurfaceTransformation; + frameProcessorListener.onOutputSizeChanged( + outputSizeBeforeSurfaceTransformation.getWidth(), + outputSizeBeforeSurfaceTransformation.getHeight()); + } } - this.inputWidth = inputWidth; - this.inputHeight = inputHeight; - Size requestedOutputSize = - MatrixUtils.configureAndGetOutputSize(inputWidth, inputHeight, matrixTransformations); - @Nullable - SurfaceInfo outputSurfaceInfo = - outputSurfaceProvider.getSurfaceInfo( - requestedOutputSize.getWidth(), requestedOutputSize.getHeight()); if (outputSurfaceInfo == null) { if (matrixTransformationProcessor != null) { matrixTransformationProcessor.release(); @@ -182,32 +190,36 @@ private boolean ensureConfigured(int inputWidth, int inputHeight) outputEglSurface = null; return false; } - if (outputSurfaceInfo == this.outputSurfaceInfo - && outputEglSurface != null - && matrixTransformationProcessor != null) { - return true; - } - EGLSurface outputEglSurface; - if (enableExperimentalHdrEditing) { - // TODO(b/227624622): Don't assume BT.2020 PQ input/output. - outputEglSurface = GlUtil.getEglSurfaceBt2020Pq(eglDisplay, outputSurfaceInfo.surface); - } else { - outputEglSurface = GlUtil.getEglSurface(eglDisplay, outputSurfaceInfo.surface); - } + SurfaceInfo outputSurfaceInfo = this.outputSurfaceInfo; + @Nullable EGLSurface outputEglSurface = this.outputEglSurface; + if (outputEglSurface == null) { // This means that outputSurfaceInfo changed. + if (enableExperimentalHdrEditing) { + // TODO(b/227624622): Don't assume BT.2020 PQ input/output. + outputEglSurface = GlUtil.getEglSurfaceBt2020Pq(eglDisplay, outputSurfaceInfo.surface); + } else { + outputEglSurface = GlUtil.getEglSurface(eglDisplay, outputSurfaceInfo.surface); + } - @Nullable - SurfaceView debugSurfaceView = - debugViewProvider.getDebugPreviewSurfaceView( - outputSurfaceInfo.width, outputSurfaceInfo.height); - if (debugSurfaceView != null) { - debugSurfaceViewWrapper = - new SurfaceViewWrapper( - eglDisplay, eglContext, enableExperimentalHdrEditing, debugSurfaceView); + @Nullable + SurfaceView debugSurfaceView = + debugViewProvider.getDebugPreviewSurfaceView( + outputSurfaceInfo.width, outputSurfaceInfo.height); + if (debugSurfaceView != null) { + debugSurfaceViewWrapper = + new SurfaceViewWrapper( + eglDisplay, eglContext, enableExperimentalHdrEditing, debugSurfaceView); + } + if (matrixTransformationProcessor != null) { + matrixTransformationProcessor.release(); + matrixTransformationProcessor = null; + } } - matrixTransformationProcessor = - createMatrixTransformationProcessorForOutputSurface(requestedOutputSize, outputSurfaceInfo); + if (matrixTransformationProcessor == null) { + matrixTransformationProcessor = + createMatrixTransformationProcessorForOutputSurface(outputSurfaceInfo); + } this.outputSurfaceInfo = outputSurfaceInfo; this.outputEglSurface = outputEglSurface; @@ -215,7 +227,7 @@ private boolean ensureConfigured(int inputWidth, int inputHeight) } private MatrixTransformationProcessor createMatrixTransformationProcessorForOutputSurface( - Size requestedOutputSize, SurfaceInfo outputSurfaceInfo) throws FrameProcessingException { + SurfaceInfo outputSurfaceInfo) throws FrameProcessingException { ImmutableList.Builder matrixTransformationListBuilder = new ImmutableList.Builder().addAll(matrixTransformations); if (outputSurfaceInfo.orientationDegrees != 0) { @@ -224,12 +236,9 @@ private MatrixTransformationProcessor createMatrixTransformationProcessorForOutp .setRotationDegrees(outputSurfaceInfo.orientationDegrees) .build()); } - if (outputSurfaceInfo.width != requestedOutputSize.getWidth() - || outputSurfaceInfo.height != requestedOutputSize.getHeight()) { - matrixTransformationListBuilder.add( - Presentation.createForWidthAndHeight( - outputSurfaceInfo.width, outputSurfaceInfo.height, Presentation.LAYOUT_SCALE_TO_FIT)); - } + matrixTransformationListBuilder.add( + Presentation.createForWidthAndHeight( + outputSurfaceInfo.width, outputSurfaceInfo.height, Presentation.LAYOUT_SCALE_TO_FIT)); MatrixTransformationProcessor matrixTransformationProcessor = new MatrixTransformationProcessor(context, matrixTransformationListBuilder.build()); @@ -258,6 +267,13 @@ public void release() throws FrameProcessingException { } } + public synchronized void setOutputSurfaceInfo(@Nullable SurfaceInfo outputSurfaceInfo) { + if (!Util.areEqual(this.outputSurfaceInfo, outputSurfaceInfo)) { + this.outputSurfaceInfo = outputSurfaceInfo; + this.outputEglSurface = null; + } + } + /** * Wrapper around a {@link SurfaceView} that keeps track of whether the output surface is valid, * and makes rendering a no-op if not. diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessor.java index 17c60e801d..01802199d1 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FrameProcessor.java @@ -16,6 +16,7 @@ package androidx.media3.transformer; import android.view.Surface; +import androidx.annotation.Nullable; /** Interface for a frame processor that applies changes to individual video frames. */ /* package */ interface FrameProcessor { @@ -26,6 +27,14 @@ */ interface Listener { + /** + * Called when the output size after applying the final effect changes. + * + *

    The output size after applying the final effect can differ from the size specified using + * {@link #setOutputSurfaceInfo(SurfaceInfo)}. + */ + void onOutputSizeChanged(int width, int height); + /** * Called when an exception occurs during asynchronous frame processing. * @@ -68,6 +77,23 @@ interface Listener { */ int getPendingInputFrameCount(); + /** + * Sets the output surface and supporting information. + * + *

    The new output {@link SurfaceInfo} is applied from the next output frame rendered onwards. + * If the output {@link SurfaceInfo} is {@code null}, the {@code FrameProcessor} will stop + * rendering and resume rendering pending frames once a non-null {@link SurfaceInfo} is set. + * + *

    If the dimensions given in {@link SurfaceInfo} do not match the {@linkplain + * Listener#onOutputSizeChanged(int,int) output size after applying the final effect} the frames + * are resized before rendering to the surface and letter/pillar-boxing is applied. + * + *

    The caller is responsible for tracking the lifecycle of the {@link SurfaceInfo#surface} + * including calling this method with a new surface if it is destroyed. When this method returns, + * the previous output surface is no longer being used and can safely be released by the caller. + */ + void setOutputSurfaceInfo(@Nullable SurfaceInfo outputSurfaceInfo); + /** * Informs the {@code FrameProcessor} that no further input frames should be accepted. * diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java index 9823b57153..af27f46a9f 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java @@ -23,6 +23,7 @@ import android.opengl.EGL14; import android.opengl.EGLContext; import android.opengl.EGLDisplay; +import android.util.Pair; import android.view.Surface; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; @@ -51,8 +52,6 @@ * @param context A {@link Context}. * @param listener A {@link Listener}. * @param effects The {@link GlEffect GlEffects} to apply to each frame. - * @param outputSurfaceProvider A {@link SurfaceInfo.Provider} managing the output {@link - * Surface}. * @param debugViewProvider A {@link Transformer.DebugViewProvider}. * @param enableExperimentalHdrEditing Whether to attempt to process the input as an HDR signal. * @return A new instance. @@ -64,7 +63,6 @@ public static GlEffectsFrameProcessor create( FrameProcessor.Listener listener, long streamOffsetUs, List effects, - SurfaceInfo.Provider outputSurfaceProvider, Transformer.DebugViewProvider debugViewProvider, boolean enableExperimentalHdrEditing) throws FrameProcessingException { @@ -79,7 +77,6 @@ public static GlEffectsFrameProcessor create( listener, streamOffsetUs, effects, - outputSurfaceProvider, debugViewProvider, enableExperimentalHdrEditing, singleThreadExecutorService)); @@ -108,7 +105,6 @@ private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( FrameProcessor.Listener listener, long streamOffsetUs, List effects, - SurfaceInfo.Provider outputSurfaceProvider, Transformer.DebugViewProvider debugViewProvider, boolean enableExperimentalHdrEditing, ExecutorService singleThreadExecutorService) @@ -131,24 +127,31 @@ private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( GlUtil.focusPlaceholderEglSurface(eglContext, eglDisplay); } - ImmutableList textureProcessors = - getGlTextureProcessorsForGlEffects( - context, - effects, - eglDisplay, - eglContext, - outputSurfaceProvider, - streamOffsetUs, - listener, - debugViewProvider, - enableExperimentalHdrEditing); + Pair, FinalMatrixTransformationProcessorWrapper> + textureProcessors = + getGlTextureProcessorsForGlEffects( + context, + effects, + eglDisplay, + eglContext, + streamOffsetUs, + listener, + debugViewProvider, + enableExperimentalHdrEditing); + ImmutableList intermediateTextureProcessors = textureProcessors.first; + FinalMatrixTransformationProcessorWrapper finalTextureProcessorWrapper = + textureProcessors.second; ExternalTextureProcessor externalTextureProcessor = new ExternalTextureProcessor(context, enableExperimentalHdrEditing); FrameProcessingTaskExecutor frameProcessingTaskExecutor = new FrameProcessingTaskExecutor(singleThreadExecutorService, listener); chainTextureProcessorsWithListeners( - externalTextureProcessor, textureProcessors, frameProcessingTaskExecutor, listener); + externalTextureProcessor, + intermediateTextureProcessors, + finalTextureProcessorWrapper, + frameProcessingTaskExecutor, + listener); return new GlEffectsFrameProcessor( eglDisplay, @@ -157,7 +160,8 @@ private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( streamOffsetUs, /* inputExternalTextureId= */ GlUtil.createExternalTexture(), externalTextureProcessor, - textureProcessors); + intermediateTextureProcessors, + finalTextureProcessorWrapper); } /** @@ -165,21 +169,21 @@ private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( * MatrixTransformationProcessor} and converts all other {@link GlEffect} instances to separate * {@link GlTextureProcessor} instances. * - *

    The final {@link GlTextureProcessor} is wrapped in a {@link - * FinalMatrixTransformationProcessorWrapper} so that it can write directly to the {@linkplain - * SurfaceInfo.Provider provided output surface}. + * @return A {@link Pair} containing a list of {@link GlTextureProcessor} instances to apply in + * the given order and a {@link FinalMatrixTransformationProcessorWrapper} to apply after + * them. */ - private static ImmutableList getGlTextureProcessorsForGlEffects( - Context context, - List effects, - EGLDisplay eglDisplay, - EGLContext eglContext, - SurfaceInfo.Provider outputSurfaceProvider, - long streamOffsetUs, - FrameProcessor.Listener listener, - Transformer.DebugViewProvider debugViewProvider, - boolean enableExperimentalHdrEditing) - throws FrameProcessingException { + private static Pair, FinalMatrixTransformationProcessorWrapper> + getGlTextureProcessorsForGlEffects( + Context context, + List effects, + EGLDisplay eglDisplay, + EGLContext eglContext, + long streamOffsetUs, + FrameProcessor.Listener listener, + Transformer.DebugViewProvider debugViewProvider, + boolean enableExperimentalHdrEditing) + throws FrameProcessingException { ImmutableList.Builder textureProcessorListBuilder = new ImmutableList.Builder<>(); ImmutableList.Builder matrixTransformationListBuilder = @@ -199,18 +203,17 @@ private static ImmutableList getGlTextureProcessorsForGlEffe } textureProcessorListBuilder.add(effect.toGlTextureProcessor(context)); } - textureProcessorListBuilder.add( + return Pair.create( + textureProcessorListBuilder.build(), new FinalMatrixTransformationProcessorWrapper( context, eglDisplay, eglContext, matrixTransformationListBuilder.build(), - outputSurfaceProvider, streamOffsetUs, listener, debugViewProvider, enableExperimentalHdrEditing)); - return textureProcessorListBuilder.build(); } /** @@ -221,21 +224,26 @@ private static ImmutableList getGlTextureProcessorsForGlEffe */ private static void chainTextureProcessorsWithListeners( ExternalTextureProcessor externalTextureProcessor, - ImmutableList textureProcessors, + ImmutableList intermediateTextureProcessors, + FinalMatrixTransformationProcessorWrapper finalTextureProcessorWrapper, FrameProcessingTaskExecutor frameProcessingTaskExecutor, FrameProcessor.Listener listener) { externalTextureProcessor.setListener( new ChainingGlTextureProcessorListener( /* previousGlTextureProcessor= */ null, - textureProcessors.get(0), + /* nextGlTextureProcessor= */ intermediateTextureProcessors.size() > 0 + ? intermediateTextureProcessors.get(0) + : finalTextureProcessorWrapper, frameProcessingTaskExecutor, listener)); GlTextureProcessor previousGlTextureProcessor = externalTextureProcessor; - for (int i = 0; i < textureProcessors.size(); i++) { - GlTextureProcessor glTextureProcessor = textureProcessors.get(i); + for (int i = 0; i < intermediateTextureProcessors.size(); i++) { + GlTextureProcessor glTextureProcessor = intermediateTextureProcessors.get(i); @Nullable GlTextureProcessor nextGlTextureProcessor = - i + 1 < textureProcessors.size() ? textureProcessors.get(i + 1) : null; + i + 1 < intermediateTextureProcessors.size() + ? intermediateTextureProcessors.get(i + 1) + : finalTextureProcessorWrapper; glTextureProcessor.setListener( new ChainingGlTextureProcessorListener( previousGlTextureProcessor, @@ -244,6 +252,12 @@ private static void chainTextureProcessorsWithListeners( listener)); previousGlTextureProcessor = glTextureProcessor; } + finalTextureProcessorWrapper.setListener( + new ChainingGlTextureProcessorListener( + previousGlTextureProcessor, + /* nextGlTextureProcessor= */ null, + frameProcessingTaskExecutor, + listener)); } private static final String TAG = "GlEffectsFrameProcessor"; @@ -267,7 +281,8 @@ private static void chainTextureProcessorsWithListeners( private final float[] inputSurfaceTextureTransformMatrix; private final int inputExternalTextureId; private final ExternalTextureProcessor inputExternalTextureProcessor; - private final ImmutableList textureProcessors; + private final ImmutableList intermediateTextureProcessors; + private final FinalMatrixTransformationProcessorWrapper finalTextureProcessorWrapper; private final ConcurrentLinkedQueue pendingInputFrames; private @MonotonicNonNull FrameInfo nextInputFrameInfo; @@ -280,8 +295,8 @@ private GlEffectsFrameProcessor( long streamOffsetUs, int inputExternalTextureId, ExternalTextureProcessor inputExternalTextureProcessor, - ImmutableList textureProcessors) { - checkState(!textureProcessors.isEmpty()); + ImmutableList intermediateTextureProcessors, + FinalMatrixTransformationProcessorWrapper finalTextureProcessorWrapper) { this.eglDisplay = eglDisplay; this.eglContext = eglContext; @@ -289,7 +304,8 @@ private GlEffectsFrameProcessor( this.streamOffsetUs = streamOffsetUs; this.inputExternalTextureId = inputExternalTextureId; this.inputExternalTextureProcessor = inputExternalTextureProcessor; - this.textureProcessors = textureProcessors; + this.intermediateTextureProcessors = intermediateTextureProcessors; + this.finalTextureProcessorWrapper = finalTextureProcessorWrapper; inputSurfaceTexture = new SurfaceTexture(inputExternalTextureId); inputSurface = new Surface(inputSurfaceTexture); @@ -323,6 +339,11 @@ public int getPendingInputFrameCount() { return pendingInputFrames.size(); } + @Override + public void setOutputSurfaceInfo(@Nullable SurfaceInfo outputSurfaceInfo) { + finalTextureProcessorWrapper.setOutputSurfaceInfo(outputSurfaceInfo); + } + @Override public void signalEndOfInputStream() { checkState(!inputStreamEnded); @@ -423,9 +444,10 @@ private void processEndOfInputStream() { private void releaseTextureProcessorsAndDestroyGlContext() throws GlUtil.GlException, FrameProcessingException { inputExternalTextureProcessor.release(); - for (int i = 0; i < textureProcessors.size(); i++) { - textureProcessors.get(i).release(); + for (int i = 0; i < intermediateTextureProcessors.size(); i++) { + intermediateTextureProcessors.get(i).release(); } + finalTextureProcessorWrapper.release(); GlUtil.destroyEglContext(eglDisplay, eglContext); } } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/SurfaceInfo.java b/libraries/transformer/src/main/java/androidx/media3/transformer/SurfaceInfo.java index 09bc801058..217dd8c75c 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/SurfaceInfo.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/SurfaceInfo.java @@ -55,16 +55,27 @@ public SurfaceInfo(Surface surface, int width, int height, int orientationDegree this.orientationDegrees = orientationDegrees; } - /** A provider for a {@link SurfaceInfo} instance. */ - public interface Provider { - /** - * Provides a {@linkplain SurfaceInfo surface} for the requested dimensions. - * - *

    The dimensions given in the provided {@link SurfaceInfo} may differ from the requested - * dimensions. It is up to the caller to transform frames from the requested dimensions to the - * provided dimensions before rendering them to the {@link SurfaceInfo#surface}. - */ - @Nullable - SurfaceInfo getSurfaceInfo(int requestedWidth, int requestedHeight); + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (!(o instanceof SurfaceInfo)) { + return false; + } + SurfaceInfo that = (SurfaceInfo) o; + return width == that.width + && height == that.height + && orientationDegrees == that.orientationDegrees + && surface.equals(that.surface); + } + + @Override + public int hashCode() { + int result = surface.hashCode(); + result = 31 * result + width; + result = 31 * result + height; + result = 31 * result + orientationDegrees; + return result; } } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java index 4304f3483a..44301842fb 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java @@ -95,14 +95,23 @@ public VideoTranscodingSamplePipeline( inputFormat, allowedOutputMimeTypes, transformationRequest, - fallbackListener, - asyncErrorListener); + fallbackListener); try { frameProcessor = GlEffectsFrameProcessor.create( context, new FrameProcessor.Listener() { + @Override + public void onOutputSizeChanged(int width, int height) { + try { + checkNotNull(frameProcessor) + .setOutputSurfaceInfo(encoderWrapper.getSurfaceInfo(width, height)); + } catch (TransformationException exception) { + asyncErrorListener.onTransformationException(exception); + } + } + @Override public void onFrameProcessingError(FrameProcessingException exception) { asyncErrorListener.onTransformationException( @@ -121,7 +130,6 @@ public void onFrameProcessingEnded() { }, streamOffsetUs, effectsListBuilder.build(), - /* outputSurfaceProvider= */ encoderWrapper, debugViewProvider, transformationRequest.enableHdrEditing); } catch (FrameProcessingException e) { @@ -284,14 +292,13 @@ private boolean isDecodeOnlyBuffer(long presentationTimeUs) { * dimensions, the same encoder is used and the provided dimensions stay fixed. */ @VisibleForTesting - /* package */ static final class EncoderWrapper implements SurfaceInfo.Provider { + /* package */ static final class EncoderWrapper { private final Codec.EncoderFactory encoderFactory; private final Format inputFormat; private final List allowedOutputMimeTypes; private final TransformationRequest transformationRequest; private final FallbackListener fallbackListener; - private final Transformer.AsyncErrorListener asyncErrorListener; private @MonotonicNonNull SurfaceInfo encoderSurfaceInfo; @@ -304,20 +311,18 @@ public EncoderWrapper( Format inputFormat, List allowedOutputMimeTypes, TransformationRequest transformationRequest, - FallbackListener fallbackListener, - Transformer.AsyncErrorListener asyncErrorListener) { + FallbackListener fallbackListener) { this.encoderFactory = encoderFactory; this.inputFormat = inputFormat; this.allowedOutputMimeTypes = allowedOutputMimeTypes; this.transformationRequest = transformationRequest; this.fallbackListener = fallbackListener; - this.asyncErrorListener = asyncErrorListener; } - @Override @Nullable - public SurfaceInfo getSurfaceInfo(int requestedWidth, int requestedHeight) { + public SurfaceInfo getSurfaceInfo(int requestedWidth, int requestedHeight) + throws TransformationException { if (releaseEncoder) { return null; } @@ -349,13 +354,8 @@ public SurfaceInfo getSurfaceInfo(int requestedWidth, int requestedHeight) { : inputFormat.sampleMimeType) .build(); - try { - encoder = - encoderFactory.createForVideoEncoding(requestedEncoderFormat, allowedOutputMimeTypes); - } catch (TransformationException e) { - asyncErrorListener.onTransformationException(e); - return null; - } + encoder = + encoderFactory.createForVideoEncoding(requestedEncoderFormat, allowedOutputMimeTypes); Format encoderSupportedFormat = encoder.getConfigurationFormat(); fallbackListener.onTransformationRequestFinalized( createFallbackTransformationRequest( diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/VideoEncoderWrapperTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/VideoEncoderWrapperTest.java index ac86e370dd..1b8b8b4502 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/VideoEncoderWrapperTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/VideoEncoderWrapperTest.java @@ -50,8 +50,7 @@ public final class VideoEncoderWrapperTest { /* inputFormat= */ new Format.Builder().build(), /* allowedOutputMimeTypes= */ ImmutableList.of(), emptyTransformationRequest, - fallbackListener, - mock(Transformer.AsyncErrorListener.class)); + fallbackListener); @Before public void registerTrack() { @@ -59,7 +58,7 @@ public void registerTrack() { } @Test - public void getSurfaceInfo_landscape_leavesOrientationUnchanged() { + public void getSurfaceInfo_landscape_leavesOrientationUnchanged() throws Exception { int inputWidth = 200; int inputHeight = 150; @@ -71,7 +70,7 @@ public void getSurfaceInfo_landscape_leavesOrientationUnchanged() { } @Test - public void getSurfaceInfo_square_leavesOrientationUnchanged() { + public void getSurfaceInfo_square_leavesOrientationUnchanged() throws Exception { int inputWidth = 150; int inputHeight = 150; @@ -83,7 +82,7 @@ public void getSurfaceInfo_square_leavesOrientationUnchanged() { } @Test - public void getSurfaceInfo_portrait_flipsOrientation() { + public void getSurfaceInfo_portrait_flipsOrientation() throws Exception { int inputWidth = 150; int inputHeight = 200; @@ -95,7 +94,8 @@ public void getSurfaceInfo_portrait_flipsOrientation() { } @Test - public void getSurfaceInfo_withEncoderFallback_usesFallbackResolution() { + public void getSurfaceInfo_withEncoderFallback_usesFallbackResolution() + throws TransformationException { int inputWidth = 200; int inputHeight = 150; int fallbackWidth = 100; From cd0e5b99de9577ff1af0da15a9ea6c9041f38361 Mon Sep 17 00:00:00 2001 From: hschlueter Date: Wed, 29 Jun 2022 17:56:53 +0000 Subject: [PATCH 58/73] Move DebugViewProvider out of Transformer class. The GlEffectsFrameProcessor that will be part of the effects module uses the DebugViewProvider. So it does not make sense for it to be an inner interface of Transformer. PiperOrigin-RevId: 458014932 --- .../demo/transformer/TransformerActivity.java | 3 +- .../GlEffectsFrameProcessorPixelTest.java | 2 +- .../media3/transformer/DebugViewProvider.java | 37 +++++++++++++++++++ ...lMatrixTransformationProcessorWrapper.java | 4 +- .../transformer/GlEffectsFrameProcessor.java | 8 ++-- .../media3/transformer/Transformer.java | 25 ++----------- .../transformer/TransformerVideoRenderer.java | 4 +- .../VideoTranscodingSamplePipeline.java | 2 +- 8 files changed, 53 insertions(+), 32 deletions(-) create mode 100644 libraries/transformer/src/main/java/androidx/media3/transformer/DebugViewProvider.java diff --git a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java index 2532d7fc7f..50d7de6323 100644 --- a/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java +++ b/demos/transformer/src/main/java/androidx/media3/demo/transformer/TransformerActivity.java @@ -41,6 +41,7 @@ import androidx.media3.common.util.Util; import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.util.DebugTextViewHelper; +import androidx.media3.transformer.DebugViewProvider; import androidx.media3.transformer.DefaultEncoderFactory; import androidx.media3.transformer.GlEffect; import androidx.media3.transformer.GlTextureProcessor; @@ -417,7 +418,7 @@ private void showToast(@StringRes int messageResource) { Toast.makeText(getApplicationContext(), getString(messageResource), Toast.LENGTH_LONG).show(); } - private final class DemoDebugViewProvider implements Transformer.DebugViewProvider { + private final class DemoDebugViewProvider implements DebugViewProvider { private @MonotonicNonNull SurfaceView surfaceView; private int width; diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java index 06512ca0e9..c6c9f6fc56 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/GlEffectsFrameProcessorPixelTest.java @@ -378,7 +378,7 @@ public void onFrameProcessingEnded() { }, /* streamOffsetUs= */ 0L, effects, - Transformer.DebugViewProvider.NONE, + DebugViewProvider.NONE, /* enableExperimentalHdrEditing= */ false)); glEffectsFrameProcessor.setInputFrameInfo( new FrameInfo(inputWidth, inputHeight, pixelWidthHeightRatio)); diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/DebugViewProvider.java b/libraries/transformer/src/main/java/androidx/media3/transformer/DebugViewProvider.java new file mode 100644 index 0000000000..9ef2ecb4fb --- /dev/null +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/DebugViewProvider.java @@ -0,0 +1,37 @@ +/* + * Copyright 2022 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 androidx.media3.transformer; + +import android.view.SurfaceView; +import androidx.annotation.Nullable; +import androidx.media3.common.util.UnstableApi; + +/** Provider for views to show diagnostic information during a transformation, for debugging. */ +@UnstableApi +public interface DebugViewProvider { + + /** Debug view provider that doesn't show any debug info. */ + DebugViewProvider NONE = (int width, int height) -> null; + + /** + * Returns a new surface view to show a preview of transformer output with the given width/height + * in pixels, or {@code null} if no debug information should be shown. + * + *

    This method may be called on an arbitrary thread. + */ + @Nullable + SurfaceView getDebugPreviewSurfaceView(int width, int height); +} diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java index a927c5ce3c..44b890d903 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java @@ -59,7 +59,7 @@ private final EGLDisplay eglDisplay; private final EGLContext eglContext; private final long streamOffsetUs; - private final Transformer.DebugViewProvider debugViewProvider; + private final DebugViewProvider debugViewProvider; private final FrameProcessor.Listener frameProcessorListener; private final boolean enableExperimentalHdrEditing; @@ -85,7 +85,7 @@ public FinalMatrixTransformationProcessorWrapper( ImmutableList matrixTransformations, long streamOffsetUs, FrameProcessor.Listener frameProcessorListener, - Transformer.DebugViewProvider debugViewProvider, + DebugViewProvider debugViewProvider, boolean enableExperimentalHdrEditing) { this.context = context; this.matrixTransformations = matrixTransformations; diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java index af27f46a9f..ce418d8281 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java @@ -52,7 +52,7 @@ * @param context A {@link Context}. * @param listener A {@link Listener}. * @param effects The {@link GlEffect GlEffects} to apply to each frame. - * @param debugViewProvider A {@link Transformer.DebugViewProvider}. + * @param debugViewProvider A {@link DebugViewProvider}. * @param enableExperimentalHdrEditing Whether to attempt to process the input as an HDR signal. * @return A new instance. * @throws FrameProcessingException If reading shader files fails, or an OpenGL error occurs while @@ -63,7 +63,7 @@ public static GlEffectsFrameProcessor create( FrameProcessor.Listener listener, long streamOffsetUs, List effects, - Transformer.DebugViewProvider debugViewProvider, + DebugViewProvider debugViewProvider, boolean enableExperimentalHdrEditing) throws FrameProcessingException { @@ -105,7 +105,7 @@ private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( FrameProcessor.Listener listener, long streamOffsetUs, List effects, - Transformer.DebugViewProvider debugViewProvider, + DebugViewProvider debugViewProvider, boolean enableExperimentalHdrEditing, ExecutorService singleThreadExecutorService) throws GlUtil.GlException, FrameProcessingException { @@ -181,7 +181,7 @@ private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( EGLContext eglContext, long streamOffsetUs, FrameProcessor.Listener listener, - Transformer.DebugViewProvider debugViewProvider, + DebugViewProvider debugViewProvider, boolean enableExperimentalHdrEditing) throws FrameProcessingException { ImmutableList.Builder textureProcessorListBuilder = diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java b/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java index 7c3036437f..8332cbc4c5 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java @@ -29,7 +29,6 @@ import android.os.Handler; import android.os.Looper; import android.os.ParcelFileDescriptor; -import android.view.SurfaceView; import androidx.annotation.IntDef; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; @@ -495,22 +494,6 @@ default void onFallbackApplied( TransformationRequest fallbackTransformationRequest) {} } - /** Provider for views to show diagnostic information during transformation, for debugging. */ - public interface DebugViewProvider { - - /** Debug view provider that doesn't show any debug info. */ - DebugViewProvider NONE = (int width, int height) -> null; - - /** - * Returns a new surface view to show a preview of transformer output with the given - * width/height in pixels, or {@code null} if no debug information should be shown. - * - *

    This method may be called on an arbitrary thread. - */ - @Nullable - SurfaceView getDebugPreviewSurfaceView(int width, int height); - } - /** * Progress state. One of {@link #PROGRESS_STATE_WAITING_FOR_AVAILABILITY}, {@link * #PROGRESS_STATE_AVAILABLE}, {@link #PROGRESS_STATE_UNAVAILABLE}, {@link @@ -549,7 +532,7 @@ public interface DebugViewProvider { private final ImmutableList videoEffects; private final Looper looper; private final Clock clock; - private final Transformer.DebugViewProvider debugViewProvider; + private final DebugViewProvider debugViewProvider; private final ListenerSet listeners; @VisibleForTesting /* package */ final Codec.DecoderFactory decoderFactory; @VisibleForTesting /* package */ final Codec.EncoderFactory encoderFactory; @@ -573,7 +556,7 @@ private Transformer( Clock clock, Codec.EncoderFactory encoderFactory, Codec.DecoderFactory decoderFactory, - Transformer.DebugViewProvider debugViewProvider) { + DebugViewProvider debugViewProvider) { checkState(!removeAudio || !removeVideo, "Audio and video cannot both be removed."); this.context = context; this.mediaSourceFactory = mediaSourceFactory; @@ -850,7 +833,7 @@ private static final class TransformerRenderersFactory implements RenderersFacto private final Codec.DecoderFactory decoderFactory; private final FallbackListener fallbackListener; private final AsyncErrorListener asyncErrorListener; - private final Transformer.DebugViewProvider debugViewProvider; + private final DebugViewProvider debugViewProvider; public TransformerRenderersFactory( Context context, @@ -864,7 +847,7 @@ public TransformerRenderersFactory( Codec.DecoderFactory decoderFactory, FallbackListener fallbackListener, AsyncErrorListener asyncErrorListener, - Transformer.DebugViewProvider debugViewProvider) { + DebugViewProvider debugViewProvider) { this.context = context; this.muxerWrapper = muxerWrapper; this.removeAudio = removeAudio; diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerVideoRenderer.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerVideoRenderer.java index 03902a400d..a9ae8307b2 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerVideoRenderer.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerVideoRenderer.java @@ -39,7 +39,7 @@ private final ImmutableList effects; private final Codec.EncoderFactory encoderFactory; private final Codec.DecoderFactory decoderFactory; - private final Transformer.DebugViewProvider debugViewProvider; + private final DebugViewProvider debugViewProvider; private final DecoderInputBuffer decoderInputBuffer; private @MonotonicNonNull SefSlowMotionFlattener sefSlowMotionFlattener; @@ -55,7 +55,7 @@ public TransformerVideoRenderer( Codec.DecoderFactory decoderFactory, Transformer.AsyncErrorListener asyncErrorListener, FallbackListener fallbackListener, - Transformer.DebugViewProvider debugViewProvider) { + DebugViewProvider debugViewProvider) { super( C.TRACK_TYPE_VIDEO, muxerWrapper, diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java index 44301842fb..2bd3311656 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java @@ -60,7 +60,7 @@ public VideoTranscodingSamplePipeline( List allowedOutputMimeTypes, FallbackListener fallbackListener, Transformer.AsyncErrorListener asyncErrorListener, - Transformer.DebugViewProvider debugViewProvider) + DebugViewProvider debugViewProvider) throws TransformationException { decoderInputBuffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED); From c0359cad927bc83e567c39a6107b17028d6cb7c1 Mon Sep 17 00:00:00 2001 From: rohks Date: Thu, 30 Jun 2022 19:10:22 +0000 Subject: [PATCH 59/73] Fix formatting in release notes. PiperOrigin-RevId: 458283415 --- RELEASENOTES.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 1032af35ba..90cd7722ac 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -15,9 +15,9 @@ * Metadata: * `MetadataRenderer` can now be configured to render metadata as soon as they are available. Create an instance with - `MetadataRenderer(MetadataOutput, Looper, - MetadataDecoderFactory, boolean)` to specify whether the renderer will - output metadata early or in sync with the player position. + `MetadataRenderer(MetadataOutput, Looper, MetadataDecoderFactory, + boolean)` to specify whether the renderer will output metadata early or + in sync with the player position. * UI: * Ensure TalkBack announces the currently active speed option in the playback controls menu From 42f13c331f8c7e28505edcd1e033c5525e5c22f2 Mon Sep 17 00:00:00 2001 From: rohks Date: Fri, 1 Jul 2022 09:39:11 +0000 Subject: [PATCH 60/73] Fix MP4 parser issue in reading length of URL array from esds boxes. As per MP4 spec, the length of URL array is a 8 bit number. #minor-release PiperOrigin-RevId: 458421436 --- .../main/java/androidx/media3/extractor/mp4/AtomParsers.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/AtomParsers.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/AtomParsers.java index 05511fc7e5..b26366dae3 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/AtomParsers.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/AtomParsers.java @@ -1659,7 +1659,7 @@ private static EsdsData parseEsdsFromParent(ParsableByteArray parent, int positi parent.skipBytes(2); } if ((flags & 0x40 /* URL_Flag */) != 0) { - parent.skipBytes(parent.readUnsignedShort()); + parent.skipBytes(parent.readUnsignedByte()); } if ((flags & 0x20 /* OCRstreamFlag */) != 0) { parent.skipBytes(2); From 21638fa3784078170af3be545316e062313a30b5 Mon Sep 17 00:00:00 2001 From: rohks Date: Fri, 1 Jul 2022 09:52:45 +0000 Subject: [PATCH 61/73] Fix MP4 parser issue in reading bitrates from esds boxes. As per MP4 spec, bitrates in esds boxes can be a 32 bit number which doesn't fits in Java int type, so now reading it as a long value. Our class for holding media format, only allows bitrates value to be an int as we don't expect the bitrates to be greater than or equal to 2^31. So we're limiting the values for bitrates to Integer.MAX_VALUE. #minor-release PiperOrigin-RevId: 458423162 --- RELEASENOTES.md | 2 ++ .../media3/extractor/mp4/AtomParsers.java | 21 ++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 90cd7722ac..5bc7b29b77 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -12,6 +12,8 @@ ([#2092](https://github.com/google/ExoPlayer/issues/2092)). * Fix parsing of H265 short term reference picture sets ([#10316](https://github.com/google/ExoPlayer/issues/10316)). + * Fix parsing of bitrates from `esds` boxes + ([#10381](https://github.com/google/ExoPlayer/issues/10381)). * Metadata: * `MetadataRenderer` can now be configured to render metadata as soon as they are available. Create an instance with diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/AtomParsers.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/AtomParsers.java index b26366dae3..4543d32819 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/AtomParsers.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/AtomParsers.java @@ -45,6 +45,7 @@ import androidx.media3.extractor.metadata.mp4.SmtaMetadataEntry; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; +import com.google.common.primitives.Ints; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; @@ -1303,7 +1304,9 @@ private static void parseVideoSampleEntry( } if (esdsData != null) { - formatBuilder.setAverageBitrate(esdsData.bitrate).setPeakBitrate(esdsData.peakBitrate); + formatBuilder + .setAverageBitrate(Ints.saturatedCast(esdsData.bitrate)) + .setPeakBitrate(Ints.saturatedCast(esdsData.peakBitrate)); } out.format = formatBuilder.build(); @@ -1609,7 +1612,9 @@ private static void parseAudioSampleEntry( .setLanguage(language); if (esdsData != null) { - formatBuilder.setAverageBitrate(esdsData.bitrate).setPeakBitrate(esdsData.peakBitrate); + formatBuilder + .setAverageBitrate(Ints.saturatedCast(esdsData.bitrate)) + .setPeakBitrate(Ints.saturatedCast(esdsData.peakBitrate)); } out.format = formatBuilder.build(); @@ -1683,8 +1688,8 @@ private static EsdsData parseEsdsFromParent(ParsableByteArray parent, int positi } parent.skipBytes(4); - int peakBitrate = parent.readUnsignedIntToInt(); - int bitrate = parent.readUnsignedIntToInt(); + long peakBitrate = parent.readUnsignedInt(); + long bitrate = parent.readUnsignedInt(); // Start of the DecoderSpecificInfo. parent.skipBytes(1); // DecoderSpecificInfo tag @@ -1943,14 +1948,14 @@ public StsdData(int numberOfEntries) { private static final class EsdsData { private final @NullableType String mimeType; private final byte @NullableType [] initializationData; - private final int bitrate; - private final int peakBitrate; + private final long bitrate; + private final long peakBitrate; public EsdsData( @NullableType String mimeType, byte @NullableType [] initializationData, - int bitrate, - int peakBitrate) { + long bitrate, + long peakBitrate) { this.mimeType = mimeType; this.initializationData = initializationData; this.bitrate = bitrate; From da0a208b89a7914dae577900c990b0f36c23df14 Mon Sep 17 00:00:00 2001 From: hmzh Date: Fri, 1 Jul 2022 10:18:50 +0000 Subject: [PATCH 62/73] Fix MIDI command timestamp calculations and synthesization duration. - Improve variable naming to include time units for clarity - Fix existing timestamp calculations to respect time units as well as track tempo (default values for now) - Ensure the synthesizer produces PCM for the correct amount of time (including gaps between commands). PiperOrigin-RevId: 458428243 --- .../extractordumps/midi/Twinkle.mid.0.dump | 372 +++++++++++++++--- .../midi/Twinkle.mid.unknown_length.dump | 372 +++++++++++++++--- 2 files changed, 636 insertions(+), 108 deletions(-) diff --git a/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.0.dump b/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.0.dump index 5d1ded9a59..449498d92f 100644 --- a/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.0.dump +++ b/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.0.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: total output bytes = 96 - sample count = 30 + sample count = 96 format 0: sampleMimeType = audio/midi sample 0: @@ -21,111 +21,375 @@ track 0: flags = 1 data = length 3, hash FFFED75B sample 3: - time = 128 + time = 100000 flags = 1 - data = length 3, hash FFFED733 + data = length 0, hash 1 sample 4: - time = 128 + time = 200000 flags = 1 - data = length 3, hash FFFED751 + data = length 0, hash 1 sample 5: - time = 256 + time = 300000 flags = 1 - data = length 3, hash FFFED733 + data = length 0, hash 1 sample 6: - time = 256 + time = 400000 flags = 1 - data = length 3, hash FFFED839 + data = length 0, hash 1 sample 7: - time = 384 + time = 500000 flags = 1 - data = length 3, hash FFFED80C + data = length 3, hash FFFED733 sample 8: - time = 384 + time = 500000 flags = 1 - data = length 3, hash FFFED83E + data = length 3, hash FFFED751 sample 9: - time = 512 + time = 600000 flags = 1 - data = length 3, hash FFFED80C + data = length 0, hash 1 sample 10: - time = 512 + time = 700000 flags = 1 - data = length 3, hash FFFED877 + data = length 0, hash 1 sample 11: - time = 640 + time = 800000 flags = 1 - data = length 3, hash FFFED84A + data = length 0, hash 1 sample 12: - time = 640 + time = 900000 flags = 1 - data = length 3, hash FFFED87C + data = length 0, hash 1 sample 13: - time = 768 + time = 1000000 flags = 1 - data = length 3, hash FFFED84A + data = length 3, hash FFFED733 sample 14: - time = 768 + time = 1000000 flags = 1 - data = length 3, hash FFFED82F + data = length 3, hash FFFED839 sample 15: - time = 1024 + time = 1100000 flags = 1 - data = length 3, hash FFFED80C + data = length 0, hash 1 sample 16: - time = 1024 + time = 1200000 flags = 1 - data = length 3, hash FFFED800 + data = length 0, hash 1 sample 17: - time = 1152 + time = 1300000 flags = 1 - data = length 3, hash FFFED7CE + data = length 0, hash 1 sample 18: - time = 1152 + time = 1400000 flags = 1 - data = length 3, hash FFFED7FB + data = length 0, hash 1 sample 19: - time = 1280 + time = 1500000 flags = 1 - data = length 3, hash FFFED7CE + data = length 3, hash FFFED80C sample 20: - time = 1280 + time = 1500000 flags = 1 - data = length 3, hash FFFED7E1 + data = length 3, hash FFFED83E sample 21: - time = 1344 + time = 1600000 flags = 1 - data = length 3, hash FFFED7AF + data = length 0, hash 1 sample 22: - time = 1408 + time = 1700000 flags = 1 - data = length 3, hash FFFED7D7 + data = length 0, hash 1 sample 23: - time = 1472 + time = 1800000 flags = 1 - data = length 3, hash FFFED7AF + data = length 0, hash 1 sample 24: - time = 1536 + time = 1900000 flags = 1 - data = length 3, hash FFFED79E + data = length 0, hash 1 sample 25: - time = 1600 + time = 2000000 flags = 1 - data = length 3, hash FFFED771 + data = length 3, hash FFFED80C sample 26: - time = 1664 + time = 2000000 flags = 1 - data = length 3, hash FFFED7A3 + data = length 3, hash FFFED877 sample 27: - time = 1728 + time = 2100000 flags = 1 - data = length 3, hash FFFED771 + data = length 0, hash 1 sample 28: - time = 1792 + time = 2200000 flags = 1 - data = length 3, hash FFFED751 + data = length 0, hash 1 sample 29: - time = 2048 + time = 2300000 + flags = 1 + data = length 0, hash 1 + sample 30: + time = 2400000 + flags = 1 + data = length 0, hash 1 + sample 31: + time = 2500000 + flags = 1 + data = length 3, hash FFFED84A + sample 32: + time = 2500000 + flags = 1 + data = length 3, hash FFFED87C + sample 33: + time = 2600000 + flags = 1 + data = length 0, hash 1 + sample 34: + time = 2700000 + flags = 1 + data = length 0, hash 1 + sample 35: + time = 2800000 + flags = 1 + data = length 0, hash 1 + sample 36: + time = 2900000 + flags = 1 + data = length 0, hash 1 + sample 37: + time = 3000000 + flags = 1 + data = length 3, hash FFFED84A + sample 38: + time = 3000000 + flags = 1 + data = length 3, hash FFFED82F + sample 39: + time = 3100000 + flags = 1 + data = length 0, hash 1 + sample 40: + time = 3200000 + flags = 1 + data = length 0, hash 1 + sample 41: + time = 3300000 + flags = 1 + data = length 0, hash 1 + sample 42: + time = 3400000 + flags = 1 + data = length 0, hash 1 + sample 43: + time = 3500000 + flags = 1 + data = length 0, hash 1 + sample 44: + time = 3600000 + flags = 1 + data = length 0, hash 1 + sample 45: + time = 3700000 + flags = 1 + data = length 0, hash 1 + sample 46: + time = 3800000 + flags = 1 + data = length 0, hash 1 + sample 47: + time = 3900000 + flags = 1 + data = length 0, hash 1 + sample 48: + time = 4000000 + flags = 1 + data = length 3, hash FFFED80C + sample 49: + time = 4000000 + flags = 1 + data = length 3, hash FFFED800 + sample 50: + time = 4100000 + flags = 1 + data = length 0, hash 1 + sample 51: + time = 4200000 + flags = 1 + data = length 0, hash 1 + sample 52: + time = 4300000 + flags = 1 + data = length 0, hash 1 + sample 53: + time = 4400000 + flags = 1 + data = length 0, hash 1 + sample 54: + time = 4500000 + flags = 1 + data = length 3, hash FFFED7CE + sample 55: + time = 4500000 + flags = 1 + data = length 3, hash FFFED7FB + sample 56: + time = 4600000 + flags = 1 + data = length 0, hash 1 + sample 57: + time = 4700000 + flags = 1 + data = length 0, hash 1 + sample 58: + time = 4800000 + flags = 1 + data = length 0, hash 1 + sample 59: + time = 4900000 + flags = 1 + data = length 0, hash 1 + sample 60: + time = 5000000 + flags = 1 + data = length 3, hash FFFED7CE + sample 61: + time = 5000000 + flags = 1 + data = length 3, hash FFFED7E1 + sample 62: + time = 5100000 + flags = 1 + data = length 0, hash 1 + sample 63: + time = 5200000 + flags = 1 + data = length 0, hash 1 + sample 64: + time = 5250000 + flags = 1 + data = length 3, hash FFFED7AF + sample 65: + time = 5350000 + flags = 1 + data = length 0, hash 1 + sample 66: + time = 5450000 + flags = 1 + data = length 0, hash 1 + sample 67: + time = 5500000 + flags = 1 + data = length 3, hash FFFED7D7 + sample 68: + time = 5600000 + flags = 1 + data = length 0, hash 1 + sample 69: + time = 5700000 + flags = 1 + data = length 0, hash 1 + sample 70: + time = 5750000 + flags = 1 + data = length 3, hash FFFED7AF + sample 71: + time = 5850000 + flags = 1 + data = length 0, hash 1 + sample 72: + time = 5950000 + flags = 1 + data = length 0, hash 1 + sample 73: + time = 6000000 + flags = 1 + data = length 3, hash FFFED79E + sample 74: + time = 6100000 + flags = 1 + data = length 0, hash 1 + sample 75: + time = 6200000 + flags = 1 + data = length 0, hash 1 + sample 76: + time = 6250000 + flags = 1 + data = length 3, hash FFFED771 + sample 77: + time = 6350000 + flags = 1 + data = length 0, hash 1 + sample 78: + time = 6450000 + flags = 1 + data = length 0, hash 1 + sample 79: + time = 6500000 + flags = 1 + data = length 3, hash FFFED7A3 + sample 80: + time = 6600000 + flags = 1 + data = length 0, hash 1 + sample 81: + time = 6700000 + flags = 1 + data = length 0, hash 1 + sample 82: + time = 6750000 + flags = 1 + data = length 3, hash FFFED771 + sample 83: + time = 6850000 + flags = 1 + data = length 0, hash 1 + sample 84: + time = 6950000 + flags = 1 + data = length 0, hash 1 + sample 85: + time = 7000000 + flags = 1 + data = length 3, hash FFFED751 + sample 86: + time = 7100000 + flags = 1 + data = length 0, hash 1 + sample 87: + time = 7200000 + flags = 1 + data = length 0, hash 1 + sample 88: + time = 7300000 + flags = 1 + data = length 0, hash 1 + sample 89: + time = 7400000 + flags = 1 + data = length 0, hash 1 + sample 90: + time = 7500000 + flags = 1 + data = length 0, hash 1 + sample 91: + time = 7600000 + flags = 1 + data = length 0, hash 1 + sample 92: + time = 7700000 + flags = 1 + data = length 0, hash 1 + sample 93: + time = 7800000 + flags = 1 + data = length 0, hash 1 + sample 94: + time = 7900000 + flags = 1 + data = length 0, hash 1 + sample 95: + time = 8000000 flags = 1 data = length 3, hash FFFED733 tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.unknown_length.dump index 5d1ded9a59..449498d92f 100644 --- a/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.unknown_length.dump +++ b/libraries/test_data/src/test/assets/extractordumps/midi/Twinkle.mid.unknown_length.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: total output bytes = 96 - sample count = 30 + sample count = 96 format 0: sampleMimeType = audio/midi sample 0: @@ -21,111 +21,375 @@ track 0: flags = 1 data = length 3, hash FFFED75B sample 3: - time = 128 + time = 100000 flags = 1 - data = length 3, hash FFFED733 + data = length 0, hash 1 sample 4: - time = 128 + time = 200000 flags = 1 - data = length 3, hash FFFED751 + data = length 0, hash 1 sample 5: - time = 256 + time = 300000 flags = 1 - data = length 3, hash FFFED733 + data = length 0, hash 1 sample 6: - time = 256 + time = 400000 flags = 1 - data = length 3, hash FFFED839 + data = length 0, hash 1 sample 7: - time = 384 + time = 500000 flags = 1 - data = length 3, hash FFFED80C + data = length 3, hash FFFED733 sample 8: - time = 384 + time = 500000 flags = 1 - data = length 3, hash FFFED83E + data = length 3, hash FFFED751 sample 9: - time = 512 + time = 600000 flags = 1 - data = length 3, hash FFFED80C + data = length 0, hash 1 sample 10: - time = 512 + time = 700000 flags = 1 - data = length 3, hash FFFED877 + data = length 0, hash 1 sample 11: - time = 640 + time = 800000 flags = 1 - data = length 3, hash FFFED84A + data = length 0, hash 1 sample 12: - time = 640 + time = 900000 flags = 1 - data = length 3, hash FFFED87C + data = length 0, hash 1 sample 13: - time = 768 + time = 1000000 flags = 1 - data = length 3, hash FFFED84A + data = length 3, hash FFFED733 sample 14: - time = 768 + time = 1000000 flags = 1 - data = length 3, hash FFFED82F + data = length 3, hash FFFED839 sample 15: - time = 1024 + time = 1100000 flags = 1 - data = length 3, hash FFFED80C + data = length 0, hash 1 sample 16: - time = 1024 + time = 1200000 flags = 1 - data = length 3, hash FFFED800 + data = length 0, hash 1 sample 17: - time = 1152 + time = 1300000 flags = 1 - data = length 3, hash FFFED7CE + data = length 0, hash 1 sample 18: - time = 1152 + time = 1400000 flags = 1 - data = length 3, hash FFFED7FB + data = length 0, hash 1 sample 19: - time = 1280 + time = 1500000 flags = 1 - data = length 3, hash FFFED7CE + data = length 3, hash FFFED80C sample 20: - time = 1280 + time = 1500000 flags = 1 - data = length 3, hash FFFED7E1 + data = length 3, hash FFFED83E sample 21: - time = 1344 + time = 1600000 flags = 1 - data = length 3, hash FFFED7AF + data = length 0, hash 1 sample 22: - time = 1408 + time = 1700000 flags = 1 - data = length 3, hash FFFED7D7 + data = length 0, hash 1 sample 23: - time = 1472 + time = 1800000 flags = 1 - data = length 3, hash FFFED7AF + data = length 0, hash 1 sample 24: - time = 1536 + time = 1900000 flags = 1 - data = length 3, hash FFFED79E + data = length 0, hash 1 sample 25: - time = 1600 + time = 2000000 flags = 1 - data = length 3, hash FFFED771 + data = length 3, hash FFFED80C sample 26: - time = 1664 + time = 2000000 flags = 1 - data = length 3, hash FFFED7A3 + data = length 3, hash FFFED877 sample 27: - time = 1728 + time = 2100000 flags = 1 - data = length 3, hash FFFED771 + data = length 0, hash 1 sample 28: - time = 1792 + time = 2200000 flags = 1 - data = length 3, hash FFFED751 + data = length 0, hash 1 sample 29: - time = 2048 + time = 2300000 + flags = 1 + data = length 0, hash 1 + sample 30: + time = 2400000 + flags = 1 + data = length 0, hash 1 + sample 31: + time = 2500000 + flags = 1 + data = length 3, hash FFFED84A + sample 32: + time = 2500000 + flags = 1 + data = length 3, hash FFFED87C + sample 33: + time = 2600000 + flags = 1 + data = length 0, hash 1 + sample 34: + time = 2700000 + flags = 1 + data = length 0, hash 1 + sample 35: + time = 2800000 + flags = 1 + data = length 0, hash 1 + sample 36: + time = 2900000 + flags = 1 + data = length 0, hash 1 + sample 37: + time = 3000000 + flags = 1 + data = length 3, hash FFFED84A + sample 38: + time = 3000000 + flags = 1 + data = length 3, hash FFFED82F + sample 39: + time = 3100000 + flags = 1 + data = length 0, hash 1 + sample 40: + time = 3200000 + flags = 1 + data = length 0, hash 1 + sample 41: + time = 3300000 + flags = 1 + data = length 0, hash 1 + sample 42: + time = 3400000 + flags = 1 + data = length 0, hash 1 + sample 43: + time = 3500000 + flags = 1 + data = length 0, hash 1 + sample 44: + time = 3600000 + flags = 1 + data = length 0, hash 1 + sample 45: + time = 3700000 + flags = 1 + data = length 0, hash 1 + sample 46: + time = 3800000 + flags = 1 + data = length 0, hash 1 + sample 47: + time = 3900000 + flags = 1 + data = length 0, hash 1 + sample 48: + time = 4000000 + flags = 1 + data = length 3, hash FFFED80C + sample 49: + time = 4000000 + flags = 1 + data = length 3, hash FFFED800 + sample 50: + time = 4100000 + flags = 1 + data = length 0, hash 1 + sample 51: + time = 4200000 + flags = 1 + data = length 0, hash 1 + sample 52: + time = 4300000 + flags = 1 + data = length 0, hash 1 + sample 53: + time = 4400000 + flags = 1 + data = length 0, hash 1 + sample 54: + time = 4500000 + flags = 1 + data = length 3, hash FFFED7CE + sample 55: + time = 4500000 + flags = 1 + data = length 3, hash FFFED7FB + sample 56: + time = 4600000 + flags = 1 + data = length 0, hash 1 + sample 57: + time = 4700000 + flags = 1 + data = length 0, hash 1 + sample 58: + time = 4800000 + flags = 1 + data = length 0, hash 1 + sample 59: + time = 4900000 + flags = 1 + data = length 0, hash 1 + sample 60: + time = 5000000 + flags = 1 + data = length 3, hash FFFED7CE + sample 61: + time = 5000000 + flags = 1 + data = length 3, hash FFFED7E1 + sample 62: + time = 5100000 + flags = 1 + data = length 0, hash 1 + sample 63: + time = 5200000 + flags = 1 + data = length 0, hash 1 + sample 64: + time = 5250000 + flags = 1 + data = length 3, hash FFFED7AF + sample 65: + time = 5350000 + flags = 1 + data = length 0, hash 1 + sample 66: + time = 5450000 + flags = 1 + data = length 0, hash 1 + sample 67: + time = 5500000 + flags = 1 + data = length 3, hash FFFED7D7 + sample 68: + time = 5600000 + flags = 1 + data = length 0, hash 1 + sample 69: + time = 5700000 + flags = 1 + data = length 0, hash 1 + sample 70: + time = 5750000 + flags = 1 + data = length 3, hash FFFED7AF + sample 71: + time = 5850000 + flags = 1 + data = length 0, hash 1 + sample 72: + time = 5950000 + flags = 1 + data = length 0, hash 1 + sample 73: + time = 6000000 + flags = 1 + data = length 3, hash FFFED79E + sample 74: + time = 6100000 + flags = 1 + data = length 0, hash 1 + sample 75: + time = 6200000 + flags = 1 + data = length 0, hash 1 + sample 76: + time = 6250000 + flags = 1 + data = length 3, hash FFFED771 + sample 77: + time = 6350000 + flags = 1 + data = length 0, hash 1 + sample 78: + time = 6450000 + flags = 1 + data = length 0, hash 1 + sample 79: + time = 6500000 + flags = 1 + data = length 3, hash FFFED7A3 + sample 80: + time = 6600000 + flags = 1 + data = length 0, hash 1 + sample 81: + time = 6700000 + flags = 1 + data = length 0, hash 1 + sample 82: + time = 6750000 + flags = 1 + data = length 3, hash FFFED771 + sample 83: + time = 6850000 + flags = 1 + data = length 0, hash 1 + sample 84: + time = 6950000 + flags = 1 + data = length 0, hash 1 + sample 85: + time = 7000000 + flags = 1 + data = length 3, hash FFFED751 + sample 86: + time = 7100000 + flags = 1 + data = length 0, hash 1 + sample 87: + time = 7200000 + flags = 1 + data = length 0, hash 1 + sample 88: + time = 7300000 + flags = 1 + data = length 0, hash 1 + sample 89: + time = 7400000 + flags = 1 + data = length 0, hash 1 + sample 90: + time = 7500000 + flags = 1 + data = length 0, hash 1 + sample 91: + time = 7600000 + flags = 1 + data = length 0, hash 1 + sample 92: + time = 7700000 + flags = 1 + data = length 0, hash 1 + sample 93: + time = 7800000 + flags = 1 + data = length 0, hash 1 + sample 94: + time = 7900000 + flags = 1 + data = length 0, hash 1 + sample 95: + time = 8000000 flags = 1 data = length 3, hash FFFED733 tracksEnded = true From 1f47fa832c6228a5545d8a15c9c09fe76c17dfc5 Mon Sep 17 00:00:00 2001 From: claincly Date: Fri, 1 Jul 2022 11:06:12 +0000 Subject: [PATCH 63/73] Round the frame rate in MediaFormat Although MediaCodec claims supporting float frame rate, encoder init failed on API21 Nexus 5. Since it's just a performance hint to the codec, it's OK to generalize it to other API versions. PiperOrigin-RevId: 458434650 --- .../androidx/media3/transformer/DefaultEncoderFactory.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java b/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java index fda367d6f0..c3048f4368 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java @@ -23,6 +23,7 @@ import static androidx.media3.common.util.Util.SDK_INT; import static java.lang.Math.abs; import static java.lang.Math.floor; +import static java.lang.Math.round; import android.content.Context; import android.media.MediaCodecInfo; @@ -231,7 +232,7 @@ public Codec createForVideoEncoding(Format format, List allowedMimeTypes String mimeType = checkNotNull(format.sampleMimeType); MediaFormat mediaFormat = MediaFormat.createVideoFormat(mimeType, format.width, format.height); - mediaFormat.setFloat(MediaFormat.KEY_FRAME_RATE, format.frameRate); + mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, round(format.frameRate)); mediaFormat.setInteger( MediaFormat.KEY_BIT_RATE, supportedVideoEncoderSettings.bitrate != VideoEncoderSettings.NO_VALUE From c9abe70259adabd1523b0e2aa0a4df74d78339d9 Mon Sep 17 00:00:00 2001 From: bachinger Date: Fri, 1 Jul 2022 13:53:11 +0000 Subject: [PATCH 64/73] Use ContextCompat.getMainExecutor when calling MediaBrowser methods This allows the service to be switched to run in another process and the app still works the same as if it is running in the same process. Issue: androidx/media#100 PiperOrigin-RevId: 458460005 --- .../main/java/androidx/media3/demo/session/MainActivity.kt | 3 ++- .../androidx/media3/demo/session/PlayableFolderActivity.kt | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/demos/session/src/main/java/androidx/media3/demo/session/MainActivity.kt b/demos/session/src/main/java/androidx/media3/demo/session/MainActivity.kt index be7c324e36..9abfd65056 100644 --- a/demos/session/src/main/java/androidx/media3/demo/session/MainActivity.kt +++ b/demos/session/src/main/java/androidx/media3/demo/session/MainActivity.kt @@ -27,6 +27,7 @@ import android.widget.ArrayAdapter import android.widget.ListView import android.widget.TextView import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat import androidx.media3.common.MediaItem import androidx.media3.session.LibraryResult import androidx.media3.session.MediaBrowser @@ -164,7 +165,7 @@ class MainActivity : AppCompatActivity() { val root: MediaItem = result.value!! pushPathStack(root) }, - MoreExecutors.directExecutor() + ContextCompat.getMainExecutor(this) ) } diff --git a/demos/session/src/main/java/androidx/media3/demo/session/PlayableFolderActivity.kt b/demos/session/src/main/java/androidx/media3/demo/session/PlayableFolderActivity.kt index f1c1631d45..125b0e0b8a 100644 --- a/demos/session/src/main/java/androidx/media3/demo/session/PlayableFolderActivity.kt +++ b/demos/session/src/main/java/androidx/media3/demo/session/PlayableFolderActivity.kt @@ -29,6 +29,7 @@ import android.widget.LinearLayout import android.widget.ListView import android.widget.TextView import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat import androidx.media3.common.MediaItem import androidx.media3.common.Player import androidx.media3.session.MediaBrowser @@ -150,7 +151,7 @@ class PlayableFolderActivity : AppCompatActivity() { val result = mediaItemFuture.get()!! title.text = result.value!!.mediaMetadata.title }, - MoreExecutors.directExecutor() + ContextCompat.getMainExecutor(this) ) childrenFuture.addListener( { @@ -161,7 +162,7 @@ class PlayableFolderActivity : AppCompatActivity() { subItemMediaList.addAll(children) mediaListAdapter.notifyDataSetChanged() }, - MoreExecutors.directExecutor() + ContextCompat.getMainExecutor(this) ) } From 2c0806814bd28612834b51b8489a138e5eb10ecf Mon Sep 17 00:00:00 2001 From: bachinger Date: Fri, 1 Jul 2022 14:27:24 +0000 Subject: [PATCH 65/73] Document custom commands in the DefaultMediaNotificationProvider Issue: androidx/media#103 #minor-release PiperOrigin-RevId: 458465479 --- .../DefaultMediaNotificationProvider.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libraries/session/src/main/java/androidx/media3/session/DefaultMediaNotificationProvider.java b/libraries/session/src/main/java/androidx/media3/session/DefaultMediaNotificationProvider.java index 992a6fdad0..3605fec100 100644 --- a/libraries/session/src/main/java/androidx/media3/session/DefaultMediaNotificationProvider.java +++ b/libraries/session/src/main/java/androidx/media3/session/DefaultMediaNotificationProvider.java @@ -69,6 +69,14 @@ *

  • {@link MediaController#COMMAND_SEEK_TO_NEXT} to seek to the next item. * * + *

    Custom commands

    + * + * Custom actions are sent to the session under the hood. You can receive them by overriding the + * session callback method {@link MediaSession.Callback#onCustomCommand(MediaSession, ControllerInfo + * controller, SessionCommand, Bundle)}. This is useful because starting with Android 13, the System + * UI notification sends commands directly to the session. So handling the custom commands on the + * session level allows you to handle them at the same callback for all API levels. + * *

    Drawables

    * * The drawables used can be overridden by drawables with the same names defined the application. @@ -219,6 +227,14 @@ public final boolean handleCustomCommand(MediaSession session, String action, Bu * customized by defining the index of the command in compact view of up to 3 commands in their * extras with key {@link DefaultMediaNotificationProvider#COMMAND_KEY_COMPACT_VIEW_INDEX}. * + *

    To make the custom layout and commands work, you need to {@linkplain + * MediaSession#setCustomLayout(List) set the custom layout of commands} and add the custom + * commands to the available commands when a controller {@linkplain + * MediaSession.Callback#onConnect(MediaSession, ControllerInfo) connects to the session}. + * Controllers that connect after you called {@link MediaSession#setCustomLayout(List)} need the + * custom command set in {@link MediaSession.Callback#onPostConnect(MediaSession, ControllerInfo)} + * also. + * * @param playerCommands The available player commands. * @param customLayout The {@linkplain MediaSession#setCustomLayout(List) custom layout of * commands}. From 3df4f3eb19aaa3486d2b3f8153be9167bd31027d Mon Sep 17 00:00:00 2001 From: claincly Date: Fri, 1 Jul 2022 14:58:47 +0000 Subject: [PATCH 66/73] Find only REGULAR_CODECS in EncoderUtil. We used "ALL_COOECS" previously, and it is not necessary because "ALL_CODECS" additionally the codecs that support tunneling/secure decoding, which there is no use case in Transformer. PiperOrigin-RevId: 458470278 --- .../main/java/androidx/media3/transformer/EncoderUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderUtil.java b/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderUtil.java index a312d8e75a..9b267f4e64 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderUtil.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderUtil.java @@ -236,7 +236,7 @@ public static int findHighestSupportedEncodingLevel( */ @Nullable public static String findCodecForFormat(MediaFormat format, boolean isDecoder) { - MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.ALL_CODECS); + MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS); // Format must not include KEY_FRAME_RATE on API21. // https://developer.android.com/reference/android/media/MediaCodecList#findDecoderForFormat(android.media.MediaFormat) @Nullable String frameRate = null; @@ -352,7 +352,7 @@ private static ImmutableListMultimap populateEncoderInfo ImmutableListMultimap.Builder encoderInfosBuilder = new ImmutableListMultimap.Builder<>(); - MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.ALL_CODECS); + MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS); MediaCodecInfo[] allCodecInfos = mediaCodecList.getCodecInfos(); for (MediaCodecInfo mediaCodecInfo : allCodecInfos) { From ceb23e69bbdc075df96943e5c29d52cf1d492db9 Mon Sep 17 00:00:00 2001 From: tonihei Date: Fri, 1 Jul 2022 15:28:39 +0000 Subject: [PATCH 67/73] Only consider enabled tracks in ProgressiveMediaPeriod.bufferedPosition ProgressiveMediaPeriod loads all available tracks into SampleStreams (because it needs to read the data anyway and it allows easy activation of tracks without reloading). However, the SampleStreams for disabled tracks are not read and no one if waiting for them. The buffered position is used for user-visible state (e.g. in the UI) and to check how much data is already buffered to decide when to stop buffering (using LoadControl). Both values benefit from only using the actually enabled tracks to better reflect what is available for playback at the moment. Issue:Issue: google/ExoPlayer#10361 PiperOrigin-RevId: 458475038 --- RELEASENOTES.md | 2 + .../source/ProgressiveMediaPeriod.java | 51 +++++++++++-------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5bc7b29b77..7c68c4b33c 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -7,6 +7,8 @@ results in a call to `Player.Listener#onTimelineChanged` with `reason=Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED` ([#9889](https://github.com/google/ExoPlayer/issues/9889)). + * For progressive media, only include selected tracks in buffered position + ([#10361](https://github.com/google/ExoPlayer/issues/10361)). * Extractors: * Add support for AVI ([#2092](https://github.com/google/ExoPlayer/issues/2092)). diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/ProgressiveMediaPeriod.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/ProgressiveMediaPeriod.java index 1f83a065fc..7471f3a2bd 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/ProgressiveMediaPeriod.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/ProgressiveMediaPeriod.java @@ -15,6 +15,7 @@ */ package androidx.media3.exoplayer.source; +import static androidx.media3.common.util.Assertions.checkNotNull; import static java.lang.Math.max; import static java.lang.Math.min; @@ -193,8 +194,7 @@ public ProgressiveMediaPeriod( onContinueLoadingRequestedRunnable = () -> { if (!released) { - Assertions.checkNotNull(callback) - .onContinueLoadingRequested(ProgressiveMediaPeriod.this); + checkNotNull(callback).onContinueLoadingRequested(ProgressiveMediaPeriod.this); } }; handler = Util.createHandlerForCurrentLooper(); @@ -366,7 +366,7 @@ public boolean isLoading() { @Override public long getNextLoadPositionUs() { - return enabledTrackCount == 0 ? C.TIME_END_OF_SOURCE : getBufferedPositionUs(); + return getBufferedPositionUs(); } @Override @@ -382,8 +382,7 @@ public long readDiscontinuity() { @Override public long getBufferedPositionUs() { assertPrepared(); - boolean[] trackIsAudioVideoFlags = trackState.trackIsAudioVideoFlags; - if (loadingFinished) { + if (loadingFinished || enabledTrackCount == 0) { return C.TIME_END_OF_SOURCE; } else if (isPendingReset()) { return pendingResetPositionUs; @@ -393,14 +392,16 @@ public long getBufferedPositionUs() { // Ignore non-AV tracks, which may be sparse or poorly interleaved. int trackCount = sampleQueues.length; for (int i = 0; i < trackCount; i++) { - if (trackIsAudioVideoFlags[i] && !sampleQueues[i].isLastSampleQueued()) { + if (trackState.trackIsAudioVideoFlags[i] + && trackState.trackEnabledStates[i] + && !sampleQueues[i].isLastSampleQueued()) { largestQueuedTimestampUs = min(largestQueuedTimestampUs, sampleQueues[i].getLargestQueuedTimestampUs()); } } } if (largestQueuedTimestampUs == Long.MAX_VALUE) { - largestQueuedTimestampUs = getLargestQueuedTimestampUs(); + largestQueuedTimestampUs = getLargestQueuedTimestampUs(/* includeDisabledTracks= */ false); } return largestQueuedTimestampUs == Long.MIN_VALUE ? lastSeekPositionUs @@ -536,7 +537,7 @@ private void maybeStartDeferredRetry(int track) { for (SampleQueue sampleQueue : sampleQueues) { sampleQueue.reset(); } - Assertions.checkNotNull(callback).onContinueLoadingRequested(this); + checkNotNull(callback).onContinueLoadingRequested(this); } private boolean suppressRead() { @@ -550,7 +551,8 @@ public void onLoadCompleted( ExtractingLoadable loadable, long elapsedRealtimeMs, long loadDurationMs) { if (durationUs == C.TIME_UNSET && seekMap != null) { boolean isSeekable = seekMap.isSeekable(); - long largestQueuedTimestampUs = getLargestQueuedTimestampUs(); + long largestQueuedTimestampUs = + getLargestQueuedTimestampUs(/* includeDisabledTracks= */ true); durationUs = largestQueuedTimestampUs == Long.MIN_VALUE ? 0 @@ -578,7 +580,7 @@ public void onLoadCompleted( /* mediaStartTimeUs= */ loadable.seekTimeUs, durationUs); loadingFinished = true; - Assertions.checkNotNull(callback).onContinueLoadingRequested(this); + checkNotNull(callback).onContinueLoadingRequested(this); } @Override @@ -609,7 +611,7 @@ public void onLoadCanceled( sampleQueue.reset(); } if (enabledTrackCount > 0) { - Assertions.checkNotNull(callback).onContinueLoadingRequested(this); + checkNotNull(callback).onContinueLoadingRequested(this); } } } @@ -755,7 +757,7 @@ private void maybeFinishPrepare() { TrackGroup[] trackArray = new TrackGroup[trackCount]; boolean[] trackIsAudioVideoFlags = new boolean[trackCount]; for (int i = 0; i < trackCount; i++) { - Format trackFormat = Assertions.checkNotNull(sampleQueues[i].getUpstreamFormat()); + Format trackFormat = checkNotNull(sampleQueues[i].getUpstreamFormat()); @Nullable String mimeType = trackFormat.sampleMimeType; boolean isAudio = MimeTypes.isAudio(mimeType); boolean isAudioVideo = isAudio || MimeTypes.isVideo(mimeType); @@ -786,7 +788,7 @@ private void maybeFinishPrepare() { } trackState = new TrackState(new TrackGroupArray(trackArray), trackIsAudioVideoFlags); prepared = true; - Assertions.checkNotNull(callback).onPrepared(this); + checkNotNull(callback).onPrepared(this); } private void startLoading() { @@ -801,7 +803,7 @@ private void startLoading() { return; } loadable.setLoadPosition( - Assertions.checkNotNull(seekMap).getSeekPoints(pendingResetPositionUs).first.position, + checkNotNull(seekMap).getSeekPoints(pendingResetPositionUs).first.position, pendingResetPositionUs); for (SampleQueue sampleQueue : sampleQueues) { sampleQueue.setStartTimeUs(pendingResetPositionUs); @@ -898,11 +900,13 @@ private int getExtractedSamplesCount() { return extractedSamplesCount; } - private long getLargestQueuedTimestampUs() { + private long getLargestQueuedTimestampUs(boolean includeDisabledTracks) { long largestQueuedTimestampUs = Long.MIN_VALUE; - for (SampleQueue sampleQueue : sampleQueues) { - largestQueuedTimestampUs = - max(largestQueuedTimestampUs, sampleQueue.getLargestQueuedTimestampUs()); + for (int i = 0; i < sampleQueues.length; i++) { + if (includeDisabledTracks || checkNotNull(trackState).trackEnabledStates[i]) { + largestQueuedTimestampUs = + max(largestQueuedTimestampUs, sampleQueues[i].getLargestQueuedTimestampUs()); + } } return largestQueuedTimestampUs; } @@ -914,8 +918,8 @@ private boolean isPendingReset() { @EnsuresNonNull({"trackState", "seekMap"}) private void assertPrepared() { Assertions.checkState(prepared); - Assertions.checkNotNull(trackState); - Assertions.checkNotNull(seekMap); + checkNotNull(trackState); + checkNotNull(seekMap); } private final class SampleStreamImpl implements SampleStream { @@ -1058,9 +1062,12 @@ public void load() throws IOException { public void onIcyMetadata(ParsableByteArray metadata) { // Always output the first ICY metadata at the start time. This helps minimize any delay // between the start of playback and the first ICY metadata event. - long timeUs = !seenIcyMetadata ? seekTimeUs : max(getLargestQueuedTimestampUs(), seekTimeUs); + long timeUs = + !seenIcyMetadata + ? seekTimeUs + : max(getLargestQueuedTimestampUs(/* includeDisabledTracks= */ true), seekTimeUs); int length = metadata.bytesLeft(); - TrackOutput icyTrackOutput = Assertions.checkNotNull(this.icyTrackOutput); + TrackOutput icyTrackOutput = checkNotNull(this.icyTrackOutput); icyTrackOutput.sampleData(metadata, length); icyTrackOutput.sampleMetadata( timeUs, C.BUFFER_FLAG_KEY_FRAME, length, /* offset= */ 0, /* cryptoData= */ null); From deea5c927a61da5a84c534b485ad8a249d10cbd6 Mon Sep 17 00:00:00 2001 From: claincly Date: Fri, 1 Jul 2022 16:05:39 +0000 Subject: [PATCH 68/73] Fix error in frame rate handling. The old getString() will throw because FRAME_RATE can only be float or int. PiperOrigin-RevId: 458481251 --- .../java/androidx/media3/transformer/EncoderUtil.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderUtil.java b/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderUtil.java index 9b267f4e64..1123d39893 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderUtil.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderUtil.java @@ -239,9 +239,14 @@ public static String findCodecForFormat(MediaFormat format, boolean isDecoder) { MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS); // Format must not include KEY_FRAME_RATE on API21. // https://developer.android.com/reference/android/media/MediaCodecList#findDecoderForFormat(android.media.MediaFormat) - @Nullable String frameRate = null; + float frameRate = Format.NO_VALUE; if (Util.SDK_INT == 21 && format.containsKey(MediaFormat.KEY_FRAME_RATE)) { - frameRate = format.getString(MediaFormat.KEY_FRAME_RATE); + try { + frameRate = format.getFloat(MediaFormat.KEY_FRAME_RATE); + } catch (ClassCastException e) { + frameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE); + } + // Clears the frame rate field. format.setString(MediaFormat.KEY_FRAME_RATE, null); } @@ -251,7 +256,7 @@ public static String findCodecForFormat(MediaFormat format, boolean isDecoder) { : mediaCodecList.findEncoderForFormat(format); if (Util.SDK_INT == 21) { - MediaFormatUtil.maybeSetString(format, MediaFormat.KEY_FRAME_RATE, frameRate); + MediaFormatUtil.maybeSetInteger(format, MediaFormat.KEY_FRAME_RATE, round(frameRate)); } return mediaCodecName; } From a0870a42be5336b313f79f596e94411563e14720 Mon Sep 17 00:00:00 2001 From: huangdarwin Date: Fri, 1 Jul 2022 16:57:43 +0000 Subject: [PATCH 69/73] HDR: Configure GL shaders and encoder. Configure the GL shaders and encoder to take in HDR metadata. This mostly just consists of passing the Format.colorInfo through the VideoTranscodingSamplePipeline down to the encoder, rather than passing the PQ-ness down to the GL step. Due to b/237674316, this will remove HDR10+ support temporarily to introduce support for HLG10. Manually tested to confirm that HLG10 operations that don't affect color display correctly after this CL with "HDR editing" in the demo checked, and continue to display incorrectly (as before this CL) without the option unchecked. PiperOrigin-RevId: 458490810 --- .../androidx/media3/common/util/GlUtil.java | 18 +++++-------- .../transformer/DefaultEncoderFactory.java | 2 ++ .../transformer/ExternalTextureProcessor.java | 15 ++++------- ...lMatrixTransformationProcessorWrapper.java | 27 ++++++++----------- .../transformer/GlEffectsFrameProcessor.java | 23 ++++++++-------- .../VideoTranscodingSamplePipeline.java | 13 ++++++++- 6 files changed, 48 insertions(+), 50 deletions(-) diff --git a/libraries/common/src/main/java/androidx/media3/common/util/GlUtil.java b/libraries/common/src/main/java/androidx/media3/common/util/GlUtil.java index adbb780e7a..1d623ef416 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/GlUtil.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/GlUtil.java @@ -66,12 +66,8 @@ public GlException(String message) { // https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_gl_colorspace.txt private static final int EGL_GL_COLORSPACE_KHR = 0x309D; - // https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_gl_colorspace_bt2020_linear.txt - private static final int EGL_GL_COLORSPACE_BT2020_PQ_EXT = 0x3340; private static final int[] EGL_WINDOW_SURFACE_ATTRIBUTES_NONE = new int[] {EGL14.EGL_NONE}; - private static final int[] EGL_WINDOW_SURFACE_ATTRIBUTES_BT2020_PQ = - new int[] {EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_BT2020_PQ_EXT, EGL14.EGL_NONE}; private static final int[] EGL_CONFIG_ATTRIBUTES_RGBA_8888 = new int[] { EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT, @@ -213,19 +209,19 @@ public static EGLSurface getEglSurface(EGLDisplay eglDisplay, Object surface) th /** * Returns a new {@link EGLSurface} wrapping the specified {@code surface}, for HDR rendering with - * Rec. 2020 color primaries and using the PQ transfer function. + * Rec. 2020 color primaries. * * @param eglDisplay The {@link EGLDisplay} to attach the surface to. * @param surface The surface to wrap; must be a surface, surface texture or surface holder. */ @RequiresApi(17) - public static EGLSurface getEglSurfaceBt2020Pq(EGLDisplay eglDisplay, Object surface) + public static EGLSurface getEglSurfaceBt2020(EGLDisplay eglDisplay, Object surface) throws GlException { return Api17.getEglSurface( eglDisplay, surface, EGL_CONFIG_ATTRIBUTES_RGBA_1010102, - EGL_WINDOW_SURFACE_ATTRIBUTES_BT2020_PQ); + EGL_WINDOW_SURFACE_ATTRIBUTES_NONE); } /** @@ -277,22 +273,22 @@ public static void focusPlaceholderEglSurface(EGLContext eglContext, EGLDisplay /** * Creates and focuses a new {@link EGLSurface} wrapping a 1x1 pixel buffer, for HDR rendering - * with Rec. 2020 color primaries and using the PQ transfer function. + * with Rec. 2020 color primaries. * * @param eglContext The {@link EGLContext} to make current. * @param eglDisplay The {@link EGLDisplay} to attach the surface to. */ @RequiresApi(17) - public static void focusPlaceholderEglSurfaceBt2020Pq( - EGLContext eglContext, EGLDisplay eglDisplay) throws GlException { + public static void focusPlaceholderEglSurfaceBt2020(EGLContext eglContext, EGLDisplay eglDisplay) + throws GlException { int[] pbufferAttributes = new int[] { EGL14.EGL_WIDTH, /* width= */ 1, EGL14.EGL_HEIGHT, /* height= */ 1, + // TODO(b/227624622): Figure out if we can remove the EGL_GL_COLORSPACE_KHR item. EGL_GL_COLORSPACE_KHR, - EGL_GL_COLORSPACE_BT2020_PQ_EXT, EGL14.EGL_NONE }; EGLSurface eglSurface = diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java b/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java index c3048f4368..df4bcb1393 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java @@ -34,6 +34,7 @@ import androidx.media3.common.Format; import androidx.media3.common.MimeTypes; import androidx.media3.common.util.Log; +import androidx.media3.common.util.MediaFormatUtil; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; import com.google.common.collect.ImmutableList; @@ -254,6 +255,7 @@ public Codec createForVideoEncoding(Format format, List allowedMimeTypes adjustMediaFormatForH264EncoderSettings(mediaFormat, encoderInfo); } + MediaFormatUtil.maybeSetColorInfo(mediaFormat, format.colorInfo); mediaFormat.setInteger( MediaFormat.KEY_COLOR_FORMAT, supportedVideoEncoderSettings.colorProfile); diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/ExternalTextureProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/ExternalTextureProcessor.java index 693f5533bc..a2f96ef63f 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/ExternalTextureProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/ExternalTextureProcessor.java @@ -49,19 +49,14 @@ /** * Creates a new instance. * - * @param enableExperimentalHdrEditing Whether to attempt to process the input as an HDR signal. + * @param useHdr Whether to process the input as an HDR signal. * @throws FrameProcessingException If a problem occurs while reading shader files. */ - public ExternalTextureProcessor(Context context, boolean enableExperimentalHdrEditing) - throws FrameProcessingException { + public ExternalTextureProcessor(Context context, boolean useHdr) throws FrameProcessingException { String vertexShaderFilePath = - enableExperimentalHdrEditing - ? VERTEX_SHADER_TEX_TRANSFORM_ES3_PATH - : VERTEX_SHADER_TEX_TRANSFORM_PATH; + useHdr ? VERTEX_SHADER_TEX_TRANSFORM_ES3_PATH : VERTEX_SHADER_TEX_TRANSFORM_PATH; String fragmentShaderFilePath = - enableExperimentalHdrEditing - ? FRAGMENT_SHADER_COPY_EXTERNAL_YUV_ES3_PATH - : FRAGMENT_SHADER_COPY_EXTERNAL_PATH; + useHdr ? FRAGMENT_SHADER_COPY_EXTERNAL_YUV_ES3_PATH : FRAGMENT_SHADER_COPY_EXTERNAL_PATH; try { glProgram = new GlProgram(context, vertexShaderFilePath, fragmentShaderFilePath); } catch (IOException | GlUtil.GlException e) { @@ -72,7 +67,7 @@ public ExternalTextureProcessor(Context context, boolean enableExperimentalHdrEd "aFramePosition", GlUtil.getNormalizedCoordinateBounds(), GlUtil.HOMOGENEOUS_COORDINATE_VECTOR_SIZE); - if (enableExperimentalHdrEditing) { + if (useHdr) { // In HDR editing mode the decoder output is sampled in YUV. glProgram.setFloatsUniform("uColorTransform", MATRIX_YUV_TO_BT2020_COLOR_TRANSFORM); } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java index 44b890d903..1be2c7ea98 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FinalMatrixTransformationProcessorWrapper.java @@ -61,7 +61,7 @@ private final long streamOffsetUs; private final DebugViewProvider debugViewProvider; private final FrameProcessor.Listener frameProcessorListener; - private final boolean enableExperimentalHdrEditing; + private final boolean useHdr; private int inputWidth; private int inputHeight; @@ -86,7 +86,7 @@ public FinalMatrixTransformationProcessorWrapper( long streamOffsetUs, FrameProcessor.Listener frameProcessorListener, DebugViewProvider debugViewProvider, - boolean enableExperimentalHdrEditing) { + boolean useHdr) { this.context = context; this.matrixTransformations = matrixTransformations; this.eglDisplay = eglDisplay; @@ -94,7 +94,7 @@ public FinalMatrixTransformationProcessorWrapper( this.streamOffsetUs = streamOffsetUs; this.debugViewProvider = debugViewProvider; this.frameProcessorListener = frameProcessorListener; - this.enableExperimentalHdrEditing = enableExperimentalHdrEditing; + this.useHdr = useHdr; } /** @@ -194,9 +194,8 @@ private synchronized boolean ensureConfigured(int inputWidth, int inputHeight) SurfaceInfo outputSurfaceInfo = this.outputSurfaceInfo; @Nullable EGLSurface outputEglSurface = this.outputEglSurface; if (outputEglSurface == null) { // This means that outputSurfaceInfo changed. - if (enableExperimentalHdrEditing) { - // TODO(b/227624622): Don't assume BT.2020 PQ input/output. - outputEglSurface = GlUtil.getEglSurfaceBt2020Pq(eglDisplay, outputSurfaceInfo.surface); + if (useHdr) { + outputEglSurface = GlUtil.getEglSurfaceBt2020(eglDisplay, outputSurfaceInfo.surface); } else { outputEglSurface = GlUtil.getEglSurface(eglDisplay, outputSurfaceInfo.surface); } @@ -207,8 +206,7 @@ private synchronized boolean ensureConfigured(int inputWidth, int inputHeight) outputSurfaceInfo.width, outputSurfaceInfo.height); if (debugSurfaceView != null) { debugSurfaceViewWrapper = - new SurfaceViewWrapper( - eglDisplay, eglContext, enableExperimentalHdrEditing, debugSurfaceView); + new SurfaceViewWrapper(eglDisplay, eglContext, useHdr, debugSurfaceView); } if (matrixTransformationProcessor != null) { matrixTransformationProcessor.release(); @@ -281,7 +279,7 @@ public synchronized void setOutputSurfaceInfo(@Nullable SurfaceInfo outputSurfac private static final class SurfaceViewWrapper implements SurfaceHolder.Callback { private final EGLDisplay eglDisplay; private final EGLContext eglContext; - private final boolean enableExperimentalHdrEditing; + private final boolean useHdr; @GuardedBy("this") @Nullable @@ -295,13 +293,10 @@ private static final class SurfaceViewWrapper implements SurfaceHolder.Callback private int height; public SurfaceViewWrapper( - EGLDisplay eglDisplay, - EGLContext eglContext, - boolean enableExperimentalHdrEditing, - SurfaceView surfaceView) { + EGLDisplay eglDisplay, EGLContext eglContext, boolean useHdr, SurfaceView surfaceView) { this.eglDisplay = eglDisplay; this.eglContext = eglContext; - this.enableExperimentalHdrEditing = enableExperimentalHdrEditing; + this.useHdr = useHdr; surfaceView.getHolder().addCallback(this); surface = surfaceView.getHolder().getSurface(); width = surfaceView.getWidth(); @@ -321,8 +316,8 @@ public synchronized void maybeRenderToSurfaceView(FrameProcessingTask renderingT } if (eglSurface == null) { - if (enableExperimentalHdrEditing) { - eglSurface = GlUtil.getEglSurfaceBt2020Pq(eglDisplay, surface); + if (useHdr) { + eglSurface = GlUtil.getEglSurfaceBt2020(eglDisplay, surface); } else { eglSurface = GlUtil.getEglSurface(eglDisplay, surface); } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java index ce418d8281..d01d690c6e 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/GlEffectsFrameProcessor.java @@ -53,7 +53,7 @@ * @param listener A {@link Listener}. * @param effects The {@link GlEffect GlEffects} to apply to each frame. * @param debugViewProvider A {@link DebugViewProvider}. - * @param enableExperimentalHdrEditing Whether to attempt to process the input as an HDR signal. + * @param useHdr Whether to process the input as an HDR signal. * @return A new instance. * @throws FrameProcessingException If reading shader files fails, or an OpenGL error occurs while * creating and configuring the OpenGL components. @@ -64,7 +64,7 @@ public static GlEffectsFrameProcessor create( long streamOffsetUs, List effects, DebugViewProvider debugViewProvider, - boolean enableExperimentalHdrEditing) + boolean useHdr) throws FrameProcessingException { ExecutorService singleThreadExecutorService = Util.newSingleThreadExecutor(THREAD_NAME); @@ -78,7 +78,7 @@ public static GlEffectsFrameProcessor create( streamOffsetUs, effects, debugViewProvider, - enableExperimentalHdrEditing, + useHdr, singleThreadExecutorService)); try { @@ -106,23 +106,22 @@ private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( long streamOffsetUs, List effects, DebugViewProvider debugViewProvider, - boolean enableExperimentalHdrEditing, + boolean useHdr, ExecutorService singleThreadExecutorService) throws GlUtil.GlException, FrameProcessingException { checkState(Thread.currentThread().getName().equals(THREAD_NAME)); EGLDisplay eglDisplay = GlUtil.createEglDisplay(); EGLContext eglContext = - enableExperimentalHdrEditing + useHdr ? GlUtil.createEglContextEs3Rgba1010102(eglDisplay) : GlUtil.createEglContext(eglDisplay); if (GlUtil.isSurfacelessContextExtensionSupported()) { GlUtil.focusEglSurface( eglDisplay, eglContext, EGL14.EGL_NO_SURFACE, /* width= */ 1, /* height= */ 1); - } else if (enableExperimentalHdrEditing) { - // TODO(b/227624622): Don't assume BT.2020 PQ input/output. - GlUtil.focusPlaceholderEglSurfaceBt2020Pq(eglContext, eglDisplay); + } else if (useHdr) { + GlUtil.focusPlaceholderEglSurfaceBt2020(eglContext, eglDisplay); } else { GlUtil.focusPlaceholderEglSurface(eglContext, eglDisplay); } @@ -137,13 +136,13 @@ private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( streamOffsetUs, listener, debugViewProvider, - enableExperimentalHdrEditing); + useHdr); ImmutableList intermediateTextureProcessors = textureProcessors.first; FinalMatrixTransformationProcessorWrapper finalTextureProcessorWrapper = textureProcessors.second; ExternalTextureProcessor externalTextureProcessor = - new ExternalTextureProcessor(context, enableExperimentalHdrEditing); + new ExternalTextureProcessor(context, useHdr); FrameProcessingTaskExecutor frameProcessingTaskExecutor = new FrameProcessingTaskExecutor(singleThreadExecutorService, listener); chainTextureProcessorsWithListeners( @@ -182,7 +181,7 @@ private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( long streamOffsetUs, FrameProcessor.Listener listener, DebugViewProvider debugViewProvider, - boolean enableExperimentalHdrEditing) + boolean useHdr) throws FrameProcessingException { ImmutableList.Builder textureProcessorListBuilder = new ImmutableList.Builder<>(); @@ -213,7 +212,7 @@ private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( streamOffsetUs, listener, debugViewProvider, - enableExperimentalHdrEditing)); + useHdr)); } /** diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java index 2bd3311656..5e1b6ddd12 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java @@ -24,6 +24,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.media3.common.C; +import androidx.media3.common.ColorInfo; import androidx.media3.common.Format; import androidx.media3.common.util.Util; import androidx.media3.decoder.DecoderInputBuffer; @@ -97,6 +98,10 @@ public VideoTranscodingSamplePipeline( transformationRequest, fallbackListener); + // TODO(b/237674316): While HLG10 is correctly reported, HDR10 currently will be incorrectly + // processed as SDR, because the inputFormat.colorInfo reports the wrong value. + boolean useHdr = transformationRequest.enableHdrEditing && isHdr(inputFormat.colorInfo); + try { frameProcessor = GlEffectsFrameProcessor.create( @@ -131,7 +136,7 @@ public void onFrameProcessingEnded() { streamOffsetUs, effectsListBuilder.build(), debugViewProvider, - transformationRequest.enableHdrEditing); + useHdr); } catch (FrameProcessingException e) { throw TransformationException.createForFrameProcessingException( e, TransformationException.ERROR_CODE_GL_INIT_FAILED); @@ -147,6 +152,11 @@ public void onFrameProcessingEnded() { maxPendingFrameCount = decoder.getMaxPendingFrameCount(); } + /** Whether this is a supported HDR format. */ + private static boolean isHdr(@Nullable ColorInfo colorInfo) { + return colorInfo != null && colorInfo.colorTransfer != C.COLOR_TRANSFER_SDR; + } + @Override @Nullable public DecoderInputBuffer dequeueInputBuffer() throws TransformationException { @@ -352,6 +362,7 @@ public SurfaceInfo getSurfaceInfo(int requestedWidth, int requestedHeight) transformationRequest.videoMimeType != null ? transformationRequest.videoMimeType : inputFormat.sampleMimeType) + .setColorInfo(inputFormat.colorInfo) .build(); encoder = From 9c8dcb402b45620174ae6be2d943ff8f32e4da14 Mon Sep 17 00:00:00 2001 From: hschlueter Date: Fri, 1 Jul 2022 18:34:02 +0000 Subject: [PATCH 70/73] Fallback to SDR if encoder doesn't support HDR (HLG only). If the input is HDR (HLG), check encoder capabilities for HDR support and request tone-mapping to SDR during decoder configuration otherwise. Capabilities are only checked for API 31 and above, as HDR editing is not supported before. As the encoder capabilities check needs to happen before selecting the encoder to use (as this may depend on the resolution output by the effects chain), the EncoderWrapper checks all candidate encoders for the MIME type for HDR capabilities and only requests fallback to SDR if none of them support it. When the actual encoder is selected, the wrapper checks that it matches one of the encoders is checked capabilities for. PiperOrigin-RevId: 458511599 --- .../androidx/media3/common/ColorInfo.java | 7 ++ .../media3/transformer/FallbackListener.java | 9 ++ .../VideoTranscodingSamplePipeline.java | 97 ++++++++++++++++--- 3 files changed, 102 insertions(+), 11 deletions(-) diff --git a/libraries/common/src/main/java/androidx/media3/common/ColorInfo.java b/libraries/common/src/main/java/androidx/media3/common/ColorInfo.java index 829262bb88..6477706932 100644 --- a/libraries/common/src/main/java/androidx/media3/common/ColorInfo.java +++ b/libraries/common/src/main/java/androidx/media3/common/ColorInfo.java @@ -31,6 +31,13 @@ /** Stores color info. */ @UnstableApi public final class ColorInfo implements Bundleable { + /** Standard Dynamic Range (SDR). */ + public static final ColorInfo SDR = + new ColorInfo( + C.COLOR_SPACE_BT709, + C.COLOR_RANGE_LIMITED, + C.COLOR_TRANSFER_SDR, + /* hdrStaticInfo= */ null); /** * Returns the {@link C.ColorSpace} corresponding to the given ISO color primary code, as per diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/FallbackListener.java b/libraries/transformer/src/main/java/androidx/media3/transformer/FallbackListener.java index 4bcf1c30b6..b3271472d9 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/FallbackListener.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/FallbackListener.java @@ -91,6 +91,15 @@ public void onTransformationRequestFinalized(TransformationRequest transformatio if (transformationRequest.outputHeight != originalTransformationRequest.outputHeight) { fallbackRequestBuilder.setResolution(transformationRequest.outputHeight); } + if (transformationRequest.enableHdrEditing != originalTransformationRequest.enableHdrEditing) { + fallbackRequestBuilder.experimental_setEnableHdrEditing( + transformationRequest.enableHdrEditing); + } + if (transformationRequest.enableRequestSdrToneMapping + != originalTransformationRequest.enableRequestSdrToneMapping) { + fallbackRequestBuilder.setEnableRequestSdrToneMapping( + transformationRequest.enableRequestSdrToneMapping); + } fallbackTransformationRequest = fallbackRequestBuilder.build(); if (trackCount == 0 && !originalTransformationRequest.equals(fallbackTransformationRequest)) { diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java index 5e1b6ddd12..ad943b297c 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoTranscodingSamplePipeline.java @@ -17,20 +17,25 @@ package androidx.media3.transformer; import static androidx.media3.common.util.Assertions.checkNotNull; +import static androidx.media3.common.util.Assertions.checkState; import android.content.Context; import android.media.MediaCodec; +import android.media.MediaCodecInfo; import android.view.Surface; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.media3.common.C; import androidx.media3.common.ColorInfo; import androidx.media3.common.Format; +import androidx.media3.common.MimeTypes; +import androidx.media3.common.util.Log; import androidx.media3.common.util.Util; import androidx.media3.decoder.DecoderInputBuffer; import com.google.common.collect.ImmutableList; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.dataflow.qual.Pure; @@ -39,6 +44,8 @@ * Pipeline to decode video samples, apply transformations on the raw samples, and re-encode them. */ /* package */ final class VideoTranscodingSamplePipeline implements SamplePipeline { + private static final String TAG = "VideoTranscodingSP"; + private final int maxPendingFrameCount; private final DecoderInputBuffer decoderInputBuffer; @@ -98,9 +105,17 @@ public VideoTranscodingSamplePipeline( transformationRequest, fallbackListener); + boolean enableRequestSdrToneMapping = transformationRequest.enableRequestSdrToneMapping; // TODO(b/237674316): While HLG10 is correctly reported, HDR10 currently will be incorrectly - // processed as SDR, because the inputFormat.colorInfo reports the wrong value. + // processed as SDR, because the inputFormat.colorInfo reports the wrong value. boolean useHdr = transformationRequest.enableHdrEditing && isHdr(inputFormat.colorInfo); + if (useHdr && !encoderWrapper.supportsHdr()) { + // TODO(b/236316454): Also check whether GlEffectsFrameProcessor supports HDR, i.e., whether + // EXT_YUV_target is supported. + useHdr = false; + enableRequestSdrToneMapping = true; + encoderWrapper.signalFallbackToSdr(); + } try { frameProcessor = @@ -146,9 +161,9 @@ public void onFrameProcessingEnded() { decoder = decoderFactory.createForVideoDecoding( - inputFormat, - frameProcessor.getInputSurface(), - transformationRequest.enableRequestSdrToneMapping); + inputFormat, frameProcessor.getInputSurface(), enableRequestSdrToneMapping); + // TODO(b/236316454): Check in the decoder output format whether tone-mapping was actually + // applied and throw an exception if not. maxPendingFrameCount = decoder.getMaxPendingFrameCount(); } @@ -232,23 +247,33 @@ public void release() { * processing, with {@link Format#rotationDegrees} of 90 added to the output format. * @param requestedFormat The requested format. * @param supportedFormat A format supported by the device. + * @param fallbackToSdr Whether HDR editing was requested via the TransformationRequest or + * inferred from the input and tone-mapping to SDR was used instead due to lack of encoder + * capabilities. */ @Pure private static TransformationRequest createFallbackTransformationRequest( TransformationRequest transformationRequest, boolean hasOutputFormatRotation, Format requestedFormat, - Format supportedFormat) { + Format supportedFormat, + boolean fallbackToSdr) { // TODO(b/210591626): Also update bitrate etc. once encoder configuration and fallback are - // implemented. - if (Util.areEqual(requestedFormat.sampleMimeType, supportedFormat.sampleMimeType) + // implemented. + if (!fallbackToSdr + && Util.areEqual(requestedFormat.sampleMimeType, supportedFormat.sampleMimeType) && (hasOutputFormatRotation ? requestedFormat.width == supportedFormat.width : requestedFormat.height == supportedFormat.height)) { return transformationRequest; } - return transformationRequest - .buildUpon() + TransformationRequest.Builder transformationRequestBuilder = transformationRequest.buildUpon(); + if (fallbackToSdr) { + transformationRequestBuilder + .setEnableRequestSdrToneMapping(true) + .experimental_setEnableHdrEditing(false); + } + return transformationRequestBuilder .setVideoMimeType(supportedFormat.sampleMimeType) .setResolution(hasOutputFormatRotation ? requestedFormat.width : requestedFormat.height) .build(); @@ -309,12 +334,14 @@ private boolean isDecodeOnlyBuffer(long presentationTimeUs) { private final List allowedOutputMimeTypes; private final TransformationRequest transformationRequest; private final FallbackListener fallbackListener; + private final HashSet hdrMediaCodecNames; private @MonotonicNonNull SurfaceInfo encoderSurfaceInfo; private volatile @MonotonicNonNull Codec encoder; private volatile int outputRotationDegrees; private volatile boolean releaseEncoder; + private boolean fallbackToSdr; public EncoderWrapper( Codec.EncoderFactory encoderFactory, @@ -328,6 +355,8 @@ public EncoderWrapper( this.allowedOutputMimeTypes = allowedOutputMimeTypes; this.transformationRequest = transformationRequest; this.fallbackListener = fallbackListener; + + hdrMediaCodecNames = new HashSet<>(); } @Nullable @@ -362,18 +391,27 @@ public SurfaceInfo getSurfaceInfo(int requestedWidth, int requestedHeight) transformationRequest.videoMimeType != null ? transformationRequest.videoMimeType : inputFormat.sampleMimeType) - .setColorInfo(inputFormat.colorInfo) + .setColorInfo(fallbackToSdr ? ColorInfo.SDR : inputFormat.colorInfo) .build(); encoder = encoderFactory.createForVideoEncoding(requestedEncoderFormat, allowedOutputMimeTypes); + if (!hdrMediaCodecNames.isEmpty() && !hdrMediaCodecNames.contains(encoder.getName())) { + Log.d( + TAG, + "Selected encoder " + + encoder.getName() + + " does not report sufficient HDR capabilities"); + } + Format encoderSupportedFormat = encoder.getConfigurationFormat(); fallbackListener.onTransformationRequestFinalized( createFallbackTransformationRequest( transformationRequest, /* hasOutputFormatRotation= */ flipOrientation, requestedEncoderFormat, - encoderSupportedFormat)); + encoderSupportedFormat, + fallbackToSdr)); encoderSurfaceInfo = new SurfaceInfo( @@ -432,5 +470,42 @@ public void release() { } releaseEncoder = true; } + + /** + * Checks whether at least one MediaCodec encoder on the device has sufficient capabilities to + * encode HDR (only checks support for HLG at this time). + */ + public boolean supportsHdr() { + if (Util.SDK_INT < 31) { + return false; + } + + // The only output MIME type that Transformer currently supports that can be used with HDR + // is H265/HEVC. So we assume that the EncoderFactory will pick this if HDR is requested. + String mimeType = MimeTypes.VIDEO_H265; + + List mediaCodecInfos = EncoderSelector.DEFAULT.selectEncoderInfos(mimeType); + for (int i = 0; i < mediaCodecInfos.size(); i++) { + MediaCodecInfo mediaCodecInfo = mediaCodecInfos.get(i); + if (EncoderUtil.isFeatureSupported( + mediaCodecInfo, mimeType, MediaCodecInfo.CodecCapabilities.FEATURE_HdrEditing)) { + for (MediaCodecInfo.CodecProfileLevel capabilities : + mediaCodecInfo.getCapabilitiesForType(MimeTypes.VIDEO_H265).profileLevels) { + // TODO(b/227624622): What profile to check depends on the HDR format. Once other + // formats besides HLG are supported, check the corresponding profiles here. + if (capabilities.profile == MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10) { + return hdrMediaCodecNames.add(mediaCodecInfo.getCanonicalName()); + } + } + } + } + return !hdrMediaCodecNames.isEmpty(); + } + + public void signalFallbackToSdr() { + checkState(encoder == null, "Fallback to SDR is only allowed before encoder initialization"); + fallbackToSdr = true; + hdrMediaCodecNames.clear(); + } } } From 7d2eb7601947570245dcd2ff86b7dcf1c8393d40 Mon Sep 17 00:00:00 2001 From: samrobinson Date: Mon, 4 Jul 2022 17:32:27 +0000 Subject: [PATCH 71/73] Implement device based encoder bitrate mapping. This feature is disabled by default for now. PiperOrigin-RevId: 458932471 --- .../transformer/DefaultEncoderFactory.java | 70 +- .../DeviceMappedEncoderBitrateProvider.java | 1835 +++++++++++++++++ .../transformer/EncoderBitrateProvider.java | 36 + 3 files changed, 1930 insertions(+), 11 deletions(-) create mode 100644 libraries/transformer/src/main/java/androidx/media3/transformer/DeviceMappedEncoderBitrateProvider.java create mode 100644 libraries/transformer/src/main/java/androidx/media3/transformer/EncoderBitrateProvider.java diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java b/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java index df4bcb1393..d6ba06c05c 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java @@ -56,6 +56,7 @@ public static final class Builder { @Nullable private EncoderSelector encoderSelector; @Nullable private VideoEncoderSettings requestedVideoEncoderSettings; private boolean enableFallback; + private boolean automaticQualityAdjustment; /** Creates a new {@link Builder}. */ public Builder(Context context) { @@ -76,10 +77,18 @@ public Builder setVideoEncoderSelector(EncoderSelector encoderSelector) { /** * Sets the requested {@link VideoEncoderSettings}. * - *

    Values in {@code requestedVideoEncoderSettings} could be adjusted to improve encoding - * quality and/or reduce failures. Specifically, {@link VideoEncoderSettings#profile} and {@link - * VideoEncoderSettings#level} are ignored for {@link MimeTypes#VIDEO_H264}. Consider - * implementing {@link Codec.EncoderFactory} if such adjustments are unwanted. + *

    Values in {@code requestedVideoEncoderSettings} may be ignored to improve encoding quality + * and/or reduce failures. + * + *

      + *
    • {@link VideoEncoderSettings#bitrate} is ignored if {@link + * Builder#setAutomaticQualityAdjustment(boolean)} is enabled and {@link + * VideoEncoderSettings#bitrateMode} is VBR. + *
    • {@link VideoEncoderSettings#profile} and {@link VideoEncoderSettings#level} are ignored + * for {@link MimeTypes#VIDEO_H264} + *
    + * + *

    Consider implementing {@link Codec.EncoderFactory} if such adjustments are unwanted. * *

    {@code requestedVideoEncoderSettings} should be handled with care because there is no * fallback support for it. For example, using incompatible {@link VideoEncoderSettings#profile} @@ -110,8 +119,19 @@ public Builder setEnableFallback(boolean enableFallback) { return this; } + /** + * Sets whether to use automatic quality adjustment. + * + *

    With this enabled, encoders are configured to output high quality video. + * + *

    Default value is {@code false}. + */ + public Builder setAutomaticQualityAdjustment(boolean automaticQualityAdjustment) { + this.automaticQualityAdjustment = automaticQualityAdjustment; + return this; + } + /** Creates an instance of {@link DefaultEncoderFactory}, using defaults if values are unset. */ - @SuppressWarnings("deprecation") public DefaultEncoderFactory build() { if (encoderSelector == null) { encoderSelector = EncoderSelector.DEFAULT; @@ -120,7 +140,11 @@ public DefaultEncoderFactory build() { requestedVideoEncoderSettings = VideoEncoderSettings.DEFAULT; } return new DefaultEncoderFactory( - context, encoderSelector, requestedVideoEncoderSettings, enableFallback); + context, + encoderSelector, + requestedVideoEncoderSettings, + enableFallback, + automaticQualityAdjustment); } } @@ -128,6 +152,7 @@ public DefaultEncoderFactory build() { private final EncoderSelector videoEncoderSelector; private final VideoEncoderSettings requestedVideoEncoderSettings; private final boolean enableFallback; + private final boolean automaticQualityAdjustment; /** * @deprecated Use {@link Builder} instead. @@ -157,10 +182,25 @@ public DefaultEncoderFactory( EncoderSelector videoEncoderSelector, VideoEncoderSettings requestedVideoEncoderSettings, boolean enableFallback) { + this( + context, + videoEncoderSelector, + requestedVideoEncoderSettings, + enableFallback, + /* automaticQualityAdjustment= */ false); + } + + private DefaultEncoderFactory( + Context context, + EncoderSelector videoEncoderSelector, + VideoEncoderSettings requestedVideoEncoderSettings, + boolean enableFallback, + boolean automaticQualityAdjustment) { this.context = context; this.videoEncoderSelector = videoEncoderSelector; this.requestedVideoEncoderSettings = requestedVideoEncoderSettings; this.enableFallback = enableFallback; + this.automaticQualityAdjustment = automaticQualityAdjustment; } @Override @@ -234,12 +274,20 @@ public Codec createForVideoEncoding(Format format, List allowedMimeTypes String mimeType = checkNotNull(format.sampleMimeType); MediaFormat mediaFormat = MediaFormat.createVideoFormat(mimeType, format.width, format.height); mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, round(format.frameRate)); - mediaFormat.setInteger( - MediaFormat.KEY_BIT_RATE, - supportedVideoEncoderSettings.bitrate != VideoEncoderSettings.NO_VALUE - ? supportedVideoEncoderSettings.bitrate - : getSuggestedBitrate(format.width, format.height, format.frameRate)); + int bitrate; + if (automaticQualityAdjustment) { + bitrate = + new DeviceMappedEncoderBitrateProvider() + .getBitrate( + encoderInfo.getName(), format.width, format.height, round(format.frameRate)); + } else if (supportedVideoEncoderSettings.bitrate != VideoEncoderSettings.NO_VALUE) { + bitrate = supportedVideoEncoderSettings.bitrate; + } else { + bitrate = getSuggestedBitrate(format.width, format.height, format.frameRate); + } + + mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate); mediaFormat.setInteger(MediaFormat.KEY_BITRATE_MODE, supportedVideoEncoderSettings.bitrateMode); if (supportedVideoEncoderSettings.profile != VideoEncoderSettings.NO_VALUE diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/DeviceMappedEncoderBitrateProvider.java b/libraries/transformer/src/main/java/androidx/media3/transformer/DeviceMappedEncoderBitrateProvider.java new file mode 100644 index 0000000000..d40aa86e63 --- /dev/null +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/DeviceMappedEncoderBitrateProvider.java @@ -0,0 +1,1835 @@ +/* + * Copyright 2022 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 androidx.media3.transformer; + +import android.os.Build; +import androidx.media3.common.util.UnstableApi; +import androidx.media3.common.util.Util; + +/** Provides encoder bitrates that should target 0.95 SSIM or higher, accounting for device used. */ +@UnstableApi +public class DeviceMappedEncoderBitrateProvider implements EncoderBitrateProvider { + + @Override + public int getBitrate(String encoderName, int width, int height, int frameRate) { + double bitrateMultiplier = + getBitrateMultiplierFromMapping( + encoderName, Util.SDK_INT, Build.MODEL, "" + width + "x" + height, frameRate); + return (int) (width * height * frameRate * bitrateMultiplier); + } + + private static double getBitrateMultiplierFromMapping( + String encoderName, + int deviceSdkVersion, + String deviceModel, + String resolution, + int framerate) { + switch (encoderName) { + case "OMX.Exynos.AVC.Encoder": + switch (deviceSdkVersion) { + case 24: + switch (deviceModel) { + case "SM-G920V": + return 0.245; + case "SM-G935F": + return 0.2625; + case "SM-G570M": + case "SM-J710MN": + default: + return 0.37188; + } + case 26: + switch (deviceModel) { + case "SM-A520F": + case "SM-J600G": + return 0.3325; + case "SM-G930F": + return 0.20125; + case "SM-G935F": + switch (resolution) { + case "1920x1080": + return 0.1225; + case "1280x720": + default: + return 0.315; + } + case "SM-G950F": + return 0.2975; + case "SM-G955F": + switch (resolution) { + case "640x480": + return 0.245; + case "1920x1080": + switch (framerate) { + case 60: + return 0.14; + case 30: + default: + return 0.175; + } + case "3840x2160": + return 0.0914; + case "1280x720": + default: + return 0.2975; + } + case "SM-G960F": + switch (resolution) { + case "1920x1080": + switch (framerate) { + case 30: + return 0.1575; + case 60: + default: + return 0.175; + } + case "1280x720": + default: + return 0.35; + } + case "SM-A750GN": + default: + return 0.35; + } + case 27: + switch (deviceModel) { + case "SM-G610F": + case "SM-J260F": + return 0.3325; + case "SM-J260G": + switch (resolution) { + case "640x480": + return 0.41563; + case "1920x1080": + switch (framerate) { + case 30: + case 60: + default: + return 0.4375; + } + case "1280x720": + default: + return 0.525; + } + case "SM-M205F": + switch (resolution) { + case "640x480": + return 0.41563; + case "1920x1080": + switch (framerate) { + case 60: + return 0.28; + case 30: + default: + return 0.315; + } + case "1280x720": + default: + return 0.56875; + } + default: + return 0.56875; + } + case 28: + switch (deviceModel) { + case "SM-A105FN": + switch (resolution) { + case "640x480": + return 0.41563; + case "1920x1080": + return 0.35; + case "1280x720": + default: + return 0.7; + } + case "SM-G950F": + switch (resolution) { + case "1280x720": + return 0.1925; + case "1920x1080": + switch (framerate) { + case 60: + return 0.175; + case 30: + default: + return 0.21; + } + case "640x480": + default: + return 0.245; + } + case "SM-G955F": + return 0.1925; + case "SM-G965F": + switch (resolution) { + case "640x480": + return 0.21; + case "1920x1080": + return 0.11375; + case "1280x720": + default: + return 0.39375; + } + case "SM-G965N": + switch (resolution) { + case "640x480": + return 0.21; + case "1920x1080": + return 0.175; + case "3840x2160": + return 0.08269; + case "1280x720": + default: + return 0.39375; + } + case "SM-J701F": + return 0.3325; + case "SM-N960F": + case "SM-N960N": + switch (resolution) { + case "640x480": + return 0.21; + case "1920x1080": + switch (framerate) { + case 60: + return 0.175; + case 30: + default: + return 0.1925; + } + case "1280x720": + default: + return 0.39375; + } + default: + return 0.7; + } + case 29: + switch (deviceModel) { + case "SM-A105FN": + switch (resolution) { + case "640x480": + return 0.4375; + case "1280x720": + return 0.7; + case "1920x1080": + switch (framerate) { + case 30: + return 1.05; + case 60: + default: + return 1.4; + } + default: + return 1.4; + } + case "SM-G977N": + switch (resolution) { + case "1280x720": + return 0.4375; + case "1920x1080": + default: + return 0.7; + } + case "SM-N970F": + return 0.245; + default: + return 1.4; + } + case 30: + switch (deviceModel) { + case "SM-A127F": + case "SM-A217F": + return 0.35; + case "SM-A505F": + case "SM-A515F": + case "SM-A515U1": + case "SM-M315F": + return 0.1925; + case "SM-A102U1": + case "SM-A105F": + case "SM-A202F": + case "SM-A205F": + case "SM-A307GN": + case "SM-A405FN": + default: + return 0.37188; + } + case 31: + return 0.245; + default: + return 1.4; + } + case "OMX.Exynos.HEVC.Encoder": + switch (deviceSdkVersion) { + case 28: + switch (deviceModel) { + case "SM-G965N": + return 0.0525; + case "SM-G950F": + default: + return 0.07; + } + case 26: + default: + return 0.07; + } + case "OMX.IMG.TOPAZ.VIDEO.Encoder": + switch (deviceModel) { + case "ANE-LX1": + case "ANE-LX2": + switch (resolution) { + case "1280x720": + return 0.245; + case "1920x1080": + switch (framerate) { + case 60: + return 0.1925; + case 30: + default: + return 0.2625; + } + case "3840x2160": + return 0.23208; + case "640x480": + default: + return 0.28; + } + case "FIG-LX1": + return 0.245; + default: + return 0.28; + } + case "OMX.MTK.VIDEO.ENCODER.AVC": + switch (deviceSdkVersion) { + case 22: + return 0.245; + case 23: + switch (deviceModel) { + case "LG-K430": + return 0.28; + case "Redmi Note 4": + return 0.35; + case "SM-G532F": + return 0.39375; + case "SM-G532G": + switch (resolution) { + case "1280x720": + return 0.39375; + case "1920x1080": + switch (framerate) { + case 30: + case 60: + default: + return 0.525; + } + default: + return 0.525; + } + default: + return 0.525; + } + case 24: + switch (deviceModel) { + case "Moto C": + return 0.2625; + case "LG-M250": + default: + return 0.28; + } + case 27: + switch (deviceModel) { + case "CPH1920": + return 0.2625; + case "Infinix X650": + switch (resolution) { + case "640x480": + return 0.28; + case "1280x720": + default: + return 0.4375; + } + case "Nokia 1": + switch (resolution) { + case "1280x720": + return 0.21; + case "640x480": + default: + return 0.2975; + } + case "Redmi 6A": + switch (resolution) { + case "1920x1080": + switch (framerate) { + case 60: + return 0.14875; + case 30: + default: + return 0.175; + } + case "640x480": + default: + return 0.315; + } + default: + return 0.4375; + } + case 28: + switch (deviceModel) { + case "CPH2015": + case "CPH2083": + case "RMX1941": + case "Redmi 6A": + default: + return 0.2625; + } + case 29: + switch (deviceModel) { + case "CPH2179": + case "Infinix X688B": + case "LM-K500": + case "LM-Q730": + case "M2006C3LG": + case "SM-A013M": + case "SM-A215U1": + case "TECNO KE5": + return 0.28; + case "k61v1_basic_ref": + switch (resolution) { + case "640x480": + return 0.35; + case "1280x720": + return 0.525; + case "1920x1080": + default: + return 0.7; + } + default: + return 0.7; + } + case 30: + switch (deviceModel) { + case "M1908C3JGG": + case "SM-A325F": + return 0.2625; + case "SM-A037U": + case "SM-A107F": + case "SM-A107M": + case "SM-A125F": + case "W-K610-TVM": + case "vivo 1904": + return 0.28; + case "wembley_2GB_full": + switch (resolution) { + case "640x480": + return 0.35; + case "1280x720": + return 0.525; + case "1920x1080": + default: + return 0.7; + } + default: + return 0.7; + } + default: + return 0.7; + } + case "OMX.hisi.video.encoder.avc": + switch (deviceSdkVersion) { + case 24: + switch (resolution) { + case "640x480": + return 0.525; + case "1920x1080": + switch (framerate) { + case 30: + case 60: + default: + return 0.245; + } + case "1280x720": + default: + return 0.56875; + } + case 27: + switch (deviceModel) { + case "CLT-L29": + case "EML-AL00": + return 0.1925; + case "COR-L29": + switch (resolution) { + case "1280x720": + return 0.1925; + case "1920x1080": + switch (framerate) { + case 60: + return 0.13125; + case 30: + default: + return 0.14; + } + case "640x480": + default: + return 0.245; + } + default: + return 0.245; + } + case 28: + switch (deviceModel) { + case "HMA-L29": + return 0.175; + case "COL-L29": + default: + return 0.21; + } + default: + return 0.56875; + } + case "OMX.qcom.video.encoder.avc": + switch (deviceSdkVersion) { + case 23: + switch (deviceModel) { + case "LG-AS110": + switch (resolution) { + case "1280x720": + return 0.39375; + case "1920x1080": + return 0.35; + case "640x480": + default: + return 0.48125; + } + case "Moto G (4)": + switch (resolution) { + case "1920x1080": + switch (framerate) { + case 60: + return 0.3325; + case 30: + default: + return 0.35; + } + case "1280x720": + default: + return 0.4375; + } + case "Moto G Play": + switch (resolution) { + case "1920x1080": + switch (framerate) { + case 60: + return 0.3325; + case 30: + default: + return 0.35; + } + case "1280x720": + default: + return 0.37188; + } + case "MotoG3": + return 0.37188; + case "Nexus 5": + switch (resolution) { + case "640x480": + return 0.3325; + case "1920x1080": + switch (framerate) { + case 60: + return 0.28; + case 30: + default: + return 0.35; + } + case "1280x720": + default: + return 0.48125; + } + case "Nexus 6P": + switch (resolution) { + case "640x480": + return 0.3325; + case "1920x1080": + switch (framerate) { + case 30: + return 0.35; + case 60: + default: + return 0.39375; + } + case "1280x720": + default: + return 0.6125; + } + case "SM-G900F": + return 0.35; + case "vivo 1610": + switch (resolution) { + case "1920x1080": + switch (framerate) { + case 60: + return 0.315; + case 30: + default: + return 0.4375; + } + case "1280x720": + default: + return 0.54688; + } + default: + return 0.6125; + } + case 24: + switch (deviceModel) { + case "Moto G (5)": + return 0.39375; + case "Nexus 6P": + switch (resolution) { + case "640x480": + return 0.3325; + case "1920x1080": + switch (framerate) { + case 30: + return 0.35; + case 60: + default: + return 0.39375; + } + case "3840x2160": + return 0.20891; + default: + return 0.39375; + } + case "SM-G935V": + return 0.3325; + case "XT1650": + switch (framerate) { + case 60: + return 0.39375; + case 30: + default: + return 0.48125; + } + default: + return 0.48125; + } + case 25: + switch (deviceModel) { + case "CPH1801": + case "ONEPLUS A5000": + case "Redmi 5 Plus": + case "SM-J510FN": + return 0.35; + case "G8142": + case "Pixel": + case "Pixel XL": + switch (resolution) { + case "1280x720": + return 0.39375; + case "1920x1080": + switch (framerate) { + case 30: + return 0.48125; + case 60: + default: + return 0.525; + } + default: + return 0.525; + } + case "LM-X210(G)": + case "Redmi 4A": + case "Redmi 4X": + case "Redmi 5A": + return 0.39375; + case "PH-1": + switch (framerate) { + case 60: + return 0.39375; + case 30: + default: + return 0.48125; + } + default: + return 0.525; + } + case 26: + switch (deviceModel) { + case "F8331": + switch (resolution) { + case "640x480": + return 0.2275; + case "1920x1080": + switch (framerate) { + case 60: + return 0.21; + case 30: + default: + return 0.245; + } + case "3840x2160": + return 0.08704; + default: + return 0.245; + } + case "F8332": + case "Pixel": + case "SM-G935T": + case "SO-01J": + switch (resolution) { + case "1920x1080": + switch (framerate) { + case 30: + return 0.245; + case 60: + default: + return 0.28; + } + case "1280x720": + default: + return 0.28; + } + case "G8342": + case "MI 5s": + case "SAMSUNG-SM-G930A": + switch (resolution) { + case "640x480": + return 0.2275; + case "1920x1080": + switch (framerate) { + case 60: + return 0.21; + case 30: + default: + return 0.245; + } + default: + return 0.245; + } + case "G8441": + case "Pixel 2": + switch (resolution) { + case "640x480": + return 0.2275; + case "1280x720": + case "1920x1080": + default: + return 0.28; + } + case "H8314": + case "LG-H932": + switch (resolution) { + case "1920x1080": + return 0.21; + case "640x480": + default: + return 0.2275; + } + case "H8324": + switch (framerate) { + case 30: + return 0.18375; + case 60: + default: + return 0.21; + } + case "HTC 10": + case "SM-G930V": + case "SM-G955W": + case "moto g(6)": + return 0.2275; + case "HTC U11 plus": + switch (resolution) { + case "640x480": + return 0.2275; + case "1920x1080": + switch (framerate) { + case 30: + return 0.245; + case 60: + default: + return 0.28; + } + case "1280x720": + default: + return 0.28; + } + case "MI 5s Plus": + switch (resolution) { + case "640x480": + case "1280x720": + default: + return 0.2275; + } + case "Mi MIX 2": + case "ONEPLUS A3003": + case "SAMSUNG-SM-G930AZ": + case "SM-G892U": + case "SM-G935R4": + switch (framerate) { + case 60: + return 0.21; + case 30: + default: + return 0.245; + } + case "Nokia 8 Sirocco": + switch (resolution) { + case "640x480": + return 0.21; + case "1920x1080": + switch (framerate) { + case 60: + return 0.21; + case 30: + default: + return 0.245; + } + case "1280x720": + default: + return 0.28; + } + case "SAMSUNG-SM-G891A": + switch (resolution) { + case "1280x720": + case "1920x1080": + default: + return 0.28; + } + case "SM-A9200": + case "SM-A920F": + switch (resolution) { + case "1920x1080": + switch (framerate) { + case 60: + return 0.21; + case 30: + default: + return 0.245; + } + case "640x480": + default: + return 0.28; + } + case "SM-G8850": + switch (resolution) { + case "640x480": + return 0.28; + case "1920x1080": + switch (framerate) { + case 60: + return 0.21; + case 30: + default: + return 0.245; + } + case "1280x720": + default: + return 0.35; + } + case "SM-G885S": + switch (resolution) { + case "640x480": + return 0.28; + case "1920x1080": + switch (framerate) { + case 30: + return 0.245; + case 60: + default: + return 0.28; + } + case "1280x720": + default: + return 0.35; + } + case "SM-G892A": + switch (resolution) { + case "640x480": + return 0.21; + case "1920x1080": + switch (framerate) { + case 60: + return 0.21; + case 30: + default: + return 0.245; + } + default: + return 0.245; + } + case "SM-G950U1": + case "SM-G955U": + case "SM-N950U": + switch (resolution) { + case "640x480": + case "1920x1080": + default: + return 0.21; + } + case "SM-G955U1": + switch (resolution) { + case "640x480": + return 0.21; + case "1280x720": + return 0.2625; + case "1920x1080": + switch (framerate) { + case 30: + return 0.245; + case 60: + default: + return 0.28; + } + default: + return 0.28; + } + case "SM-G960U1": + switch (resolution) { + case "640x480": + return 0.21; + case "1920x1080": + switch (framerate) { + case 30: + return 0.18375; + case 60: + default: + return 0.21; + } + case "3840x2160": + return 0.09575; + case "1280x720": + default: + return 0.35; + } + case "SM-G9650": + switch (resolution) { + case "1920x1080": + switch (framerate) { + case 30: + return 0.18375; + case 60: + default: + return 0.21; + } + case "640x480": + default: + return 0.21; + } + case "SM-G965U1": + switch (resolution) { + case "640x480": + return 0.21; + case "1920x1080": + switch (framerate) { + case 30: + return 0.18375; + case 60: + default: + return 0.21; + } + case "3840x2160": + return 0.09575; + case "1280x720": + default: + return 0.2275; + } + case "SOV33": + switch (resolution) { + case "640x480": + return 0.2275; + case "3840x2160": + return 0.08704; + case "1280x720": + case "1920x1080": + default: + return 0.28; + } + case "moto e5 play": + switch (resolution) { + case "640x480": + return 0.39375; + case "1920x1080": + return 0.35; + case "1280x720": + default: + return 0.48125; + } + default: + return 0.48125; + } + case 27: + switch (deviceModel) { + case "ASUS_X00TD": + switch (resolution) { + case "1920x1080": + switch (framerate) { + case 30: + return 0.28; + case 60: + default: + return 0.4375; + } + case "1280x720": + default: + return 0.45937; + } + case "DUB-LX1": + return 0.2275; + case "F-01L": + switch (resolution) { + case "640x480": + return 0.315; + case "1280x720": + return 0.48125; + case "1920x1080": + switch (framerate) { + case 30: + return 0.28; + case 60: + default: + return 0.7; + } + default: + return 0.7; + } + case "Lenovo TB-8504F": + case "moto e5 play": + switch (resolution) { + case "640x480": + return 0.39375; + case "1920x1080": + switch (framerate) { + case 30: + case 60: + default: + return 0.35; + } + case "1280x720": + default: + return 0.48125; + } + case "Moto Z3 Play": + switch (resolution) { + case "640x480": + return 0.315; + case "1920x1080": + default: + return 0.7; + } + case "Nokia 2.1": + switch (resolution) { + case "640x480": + return 0.39375; + case "1920x1080": + return 0.35; + case "1280x720": + default: + return 0.48125; + } + case "Pixel 2": + switch (resolution) { + case "640x480": + case "1920x1080": + default: + return 0.21; + } + case "Pixel 2 XL": + switch (resolution) { + case "640x480": + return 0.21; + case "1920x1080": + switch (framerate) { + case 60: + return 0.21; + case 30: + default: + return 0.245; + } + default: + return 0.245; + } + case "Redmi 5 Plus": + switch (resolution) { + case "1920x1080": + switch (framerate) { + case 60: + return 0.245; + case 30: + default: + return 0.28; + } + case "3840x2160": + return 0.17409; + case "640x480": + default: + return 0.315; + } + case "Redmi Note 5": + switch (framerate) { + case 60: + return 0.245; + case 30: + default: + return 0.28; + } + case "SM-J260MU": + return 0.3325; + case "SM-J727V": + switch (resolution) { + case "1920x1080": + return 0.21; + case "640x480": + default: + return 0.28; + } + case "SM-N960U1": + switch (resolution) { + case "640x480": + return 0.21; + case "1920x1080": + switch (framerate) { + case 30: + return 0.18375; + case 60: + default: + return 0.21; + } + case "1280x720": + default: + return 0.35; + } + case "TC77": + switch (resolution) { + case "640x480": + return 0.39375; + case "1280x720": + return 0.6125; + case "1920x1080": + switch (framerate) { + case 30: + return 0.28; + case 60: + default: + return 0.7; + } + case "3840x2160": + return 0.1915; + default: + return 0.7; + } + case "vivo 1805": + switch (resolution) { + case "640x480": + case "1920x1080": + return 0.21; + case "1280x720": + default: + return 0.35; + } + default: + return 0.7; + } + case 28: + switch (deviceModel) { + case "801SO": + case "H9493": + switch (resolution) { + case "1920x1080": + return 0.21; + case "1280x720": + default: + return 0.35; + } + case "ASUS_X00TD": + switch (resolution) { + case "1280x720": + return 0.4375; + case "1920x1080": + switch (framerate) { + case 30: + return 0.245; + case 60: + default: + return 0.7; + } + default: + return 0.7; + } + case "H8216": + switch (resolution) { + case "1920x1080": + switch (framerate) { + case 30: + return 0.35; + case 60: + default: + return 0.525; + } + case "1280x720": + default: + return 0.525; + } + case "H8266": + switch (resolution) { + case "1920x1080": + return 0.35; + case "1280x720": + default: + return 0.525; + } + case "H8416": + switch (resolution) { + case "1920x1080": + return 0.35; + case "1280x720": + default: + return 0.39375; + } + case "LM-Q910": + case "Pixel 2 XL": + case "SM-T837V": + switch (resolution) { + case "640x480": + return 0.21; + case "1280x720": + return 0.35; + case "1920x1080": + switch (framerate) { + case 30: + return 0.245; + case 60: + default: + return 0.7; + } + default: + return 0.7; + } + case "LM-V405": + switch (resolution) { + case "1920x1080": + switch (framerate) { + case 30: + return 0.175; + case 60: + default: + return 0.21; + } + case "1280x720": + default: + return 0.35; + } + case "MI 8 Pro": + case "SC-02K": + switch (resolution) { + case "1920x1080": + switch (framerate) { + case 30: + return 0.175; + case 60: + default: + return 0.21; + } + case "640x480": + default: + return 0.21; + } + case "MI MAX 3": + switch (resolution) { + case "640x480": + return 0.28; + case "1920x1080": + switch (framerate) { + case 30: + return 0.245; + case 60: + default: + return 0.7; + } + default: + return 0.7; + } + case "Mi A1": + switch (resolution) { + case "1280x720": + return 0.2275; + case "1920x1080": + switch (framerate) { + case 30: + return 0.28; + case 60: + default: + return 0.7; + } + default: + return 0.7; + } + case "Nokia 7.2": + case "Redmi Note 6 Pro": + switch (resolution) { + case "640x480": + return 0.28; + case "1920x1080": + switch (framerate) { + case 30: + return 0.245; + case 60: + default: + return 0.7; + } + case "3840x2160": + return 0.1915; + default: + return 0.7; + } + case "Nokia 9": + switch (framerate) { + case 30: + return 0.175; + case 60: + default: + return 0.21; + } + case "ONEPLUS A5010": + switch (resolution) { + case "640x480": + return 0.21; + case "1280x720": + default: + return 0.2275; + } + case "ONEPLUS A6013": + switch (resolution) { + case "640x480": + return 0.21; + case "1920x1080": + switch (framerate) { + case 30: + case 60: + default: + return 0.175; + } + case "1280x720": + default: + return 0.35; + } + case "Pixel 3": + switch (resolution) { + case "1920x1080": + switch (framerate) { + case 30: + return 0.175; + case 60: + default: + return 0.21; + } + case "3840x2160": + return 0.09575; + case "640x480": + default: + return 0.21; + } + case "Pixel 3a": + switch (framerate) { + case 30: + return 0.245; + case 60: + default: + return 0.7; + } + case "SC-03K": + switch (resolution) { + case "640x480": + case "1920x1080": + return 0.21; + case "1280x720": + default: + return 0.35; + } + case "SH-01L": + switch (resolution) { + case "640x480": + return 0.315; + case "1920x1080": + switch (framerate) { + case 30: + return 0.28; + case 60: + default: + return 0.7; + } + default: + return 0.7; + } + case "SH-03K": + switch (resolution) { + case "1280x720": + return 0.525; + case "1920x1080": + switch (framerate) { + case 60: + return 0.7; + case 30: + default: + return 1.05; + } + default: + return 1.05; + } + case "SHV39": + switch (resolution) { + case "640x480": + return 0.2625; + case "1280x720": + return 0.37188; + case "1920x1080": + switch (framerate) { + case 30: + return 0.245; + case 60: + default: + return 0.7; + } + default: + return 0.7; + } + case "SM-J415F": + case "SM-J415FN": + case "U693CL": + return 0.3325; + case "SM-N950U1": + return 0.2275; + case "SM-T720": + switch (resolution) { + case "640x480": + return 0.21; + case "1920x1080": + switch (framerate) { + case 30: + return 0.18375; + case 60: + default: + return 0.21; + } + case "1280x720": + default: + return 0.35; + } + case "SM-T827V": + switch (resolution) { + case "640x480": + return 0.2275; + case "1920x1080": + switch (framerate) { + case 30: + return 0.245; + case 60: + default: + return 0.7; + } + default: + return 0.7; + } + case "moto g(7) plus": + switch (resolution) { + case "640x480": + return 0.315; + case "1920x1080": + switch (framerate) { + case 30: + return 0.28; + case 60: + default: + return 0.7; + } + case "3840x2160": + return 0.20891; + default: + return 0.7; + } + default: + return 1.05; + } + case 29: + switch (deviceModel) { + case "CPH1931": + case "Redmi Note 9 Pro": + return 0.2275; + case "Pixel 2 XL": + switch (resolution) { + case "640x480": + return 0.315; + case "1280x720": + return 0.48125; + case "1920x1080": + default: + return 0.7; + } + case "Pixel XL": + case "SM-G960U1": + return 0.2625; + case "Redmi 8": + return 0.35; + case "SM-G981U1": + switch (resolution) { + case "1280x720": + return 0.35; + case "1920x1080": + switch (framerate) { + case 30: + return 0.2275; + case 60: + default: + return 0.7; + } + default: + return 0.7; + } + case "SM-N9750": + return 0.21; + case "moto g(7)": + case "moto g(7) play": + return 0.315; + default: + return 0.7; + } + case 30: + switch (deviceModel) { + case "CPH2127": + case "M2101K7AG": + case "Redmi Note 8": + case "Redmi Note 9S": + case "SM-A715F": + return 0.2275; + case "SM-A207F": + case "SM-M115F": + case "SM-S115DL": + return 0.315; + case "SM-F916U1": + switch (resolution) { + case "640x480": + return 0.175; + case "1920x1080": + switch (framerate) { + case 30: + return 0.2275; + case 60: + default: + return 0.35; + } + case "1280x720": + default: + return 0.35; + } + case "SM-N986U": + return 0.1925; + case "Nokia 1.4": + case "SM-A015M": + default: + return 0.35; + } + case 31: + switch (deviceModel) { + case "SM-G975U1": + case "SM-N975U1": + default: + return 0.21; + } + case 32: + switch (resolution) { + case "640x480": + return 0.14; + case "1920x1080": + switch (framerate) { + case 30: + return 0.2275; + case 60: + default: + return 0.35; + } + case "1280x720": + default: + return 0.35; + } + default: + return 1.05; + } + case "OMX.qcom.video.encoder.hevc": + switch (deviceSdkVersion) { + case 26: + switch (deviceModel) { + case "F8331": + case "MI 5s": + return 0.105; + case "SM-G885S": + default: + return 0.1575; + } + case 27: + return 0.1575; + case 28: + switch (deviceModel) { + case "Nokia 7.2": + return 0.1575; + case "moto g(7) plus": + default: + return 0.35; + } + default: + return 0.35; + } + case "c2.exynos.h264.encoder": + switch (deviceSdkVersion) { + case 31: + switch (resolution) { + case "1280x720": + return 0.245; + case "1920x1080": + switch (framerate) { + case 30: + case 60: + default: + return 0.7; + } + default: + return 0.7; + } + case 32: + switch (deviceModel) { + case "Pixel 6": + switch (resolution) { + case "640x480": + return 0.28; + case "1280x720": + return 0.245; + case "1920x1080": + switch (framerate) { + case 30: + case 60: + default: + return 0.7; + } + default: + return 0.7; + } + case "Pixel 6 Pro": + switch (resolution) { + case "1280x720": + return 0.245; + case "1920x1080": + switch (framerate) { + case 30: + case 60: + default: + return 0.7; + } + default: + return 0.7; + } + default: + return 0.7; + } + case 33: + return 0.245; + default: + return 0.7; + } + case "c2.qti.avc.encoder": + switch (deviceSdkVersion) { + case 29: + switch (deviceModel) { + case "Pixel 3": + switch (resolution) { + case "640x480": + return 0.21; + case "1280x720": + return 0.245; + case "1920x1080": + default: + return 0.7; + } + case "Pixel 4": + switch (resolution) { + case "640x480": + case "1280x720": + return 0.1925; + case "1920x1080": + switch (framerate) { + case 30: + return 0.21; + case 60: + default: + return 1.4; + } + case "3840x2160": + return 0.08704; + default: + return 1.4; + } + default: + return 1.4; + } + case 30: + switch (deviceModel) { + case "Pixel 4": + switch (resolution) { + case "1280x720": + return 0.21; + case "1920x1080": + default: + return 0.35; + } + case "Pixel 4 XL": + return 0.21; + case "Pixel 5": + switch (resolution) { + case "640x480": + return 0.20125; + case "1280x720": + return 0.2275; + case "1920x1080": + default: + return 0.28; + } + case "Pixel 5a": + switch (resolution) { + case "1280x720": + return 0.2275; + case "1920x1080": + switch (framerate) { + case 30: + return 0.21; + case 60: + default: + return 0.28; + } + default: + return 0.28; + } + case "SM-F711U1": + switch (resolution) { + case "640x480": + return 0.21; + case "1280x720": + return 0.2275; + case "1920x1080": + switch (framerate) { + case 30: + return 0.245; + case 60: + default: + return 0.7; + } + default: + return 0.7; + } + case "SM-F926U1": + switch (resolution) { + case "640x480": + return 0.21; + case "1280x720": + return 0.2275; + case "1920x1080": + default: + return 0.7; + } + case "SM-G991U1": + return 0.2275; + default: + return 0.7; + } + case 31: + switch (deviceModel) { + case "Pixel 3": + case "Pixel 3 XL": + case "Pixel 3a": + case "Pixel 3a XL": + return 0.245; + case "Pixel 4": + return 0.20563; + case "Pixel 4a": + case "SM-G991U1": + return 0.21; + case "Pixel 4a (5G)": + case "Pixel 5a": + case "SM-F711U1": + case "SM-F926U1": + case "SM-G998U1": + return 0.2275; + case "Pixel 5": + switch (resolution) { + case "1280x720": + return 0.2275; + case "1920x1080": + switch (framerate) { + case 30: + return 0.21; + case 60: + default: + return 0.28; + } + default: + return 0.28; + } + case "SM-A528B": + return 0.20125; + case "SM-S908U1": + return 0.14; + default: + return 0.28; + } + case 32: + switch (deviceModel) { + case "Pixel 4": + return 0.21; + case "Pixel 5": + switch (resolution) { + case "1280x720": + return 0.2275; + case "1920x1080": + switch (framerate) { + case 30: + return 0.21; + case 60: + default: + return 0.28; + } + default: + return 0.28; + } + default: + return 0.28; + } + default: + return 1.4; + } + case "c2.qti.hevc.encoder": + switch (deviceModel) { + case "Pixel 4": + return 0.0875; + case "Pixel 3": + default: + return 0.105; + } + default: + return 1.4; + } + } +} diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderBitrateProvider.java b/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderBitrateProvider.java new file mode 100644 index 0000000000..02205aeb3b --- /dev/null +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderBitrateProvider.java @@ -0,0 +1,36 @@ +/* + * Copyright 2022 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 androidx.media3.transformer; + +import android.media.MediaCodecInfo; +import androidx.media3.common.util.UnstableApi; + +/** Provides bitrates for encoders to use as a target. */ +@UnstableApi +public interface EncoderBitrateProvider { + + /** + * Returns a recommended bitrate that the encoder should target. + * + * @param encoderName The name of the encoder, see {@link MediaCodecInfo#getName()} + * @param width The output width of the video after encoding. + * @param height The output height of the video after encoding. + * @param frameRate The expected output frame rate of the video after encoding. + * @return The bitrate the encoder should target. + */ + int getBitrate(String encoderName, int width, int height, int frameRate); +} From ff3d7dff12f0e7b1fd06906620f4daf6aa5a02f6 Mon Sep 17 00:00:00 2001 From: Shraddha Basantwani Date: Wed, 6 Jul 2022 12:46:52 +0530 Subject: [PATCH 72/73] Fix VP8 Reader Update VP8 header to check if the S bit is set. Variable fragmentedSampleSizeBytes is initialised with -1, and reader is directly adding fragmentSize to this variable. Updated it to check if the size is unset. Bug: 238153477 Test: manual Change-Id: I9d5735422a4a0eeb2967af93809b879b434e3c57 --- .../media3/exoplayer/rtsp/reader/RtpVp8Reader.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/reader/RtpVp8Reader.java b/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/reader/RtpVp8Reader.java index 72b739edd2..dda04bf8c6 100644 --- a/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/reader/RtpVp8Reader.java +++ b/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/reader/RtpVp8Reader.java @@ -113,7 +113,11 @@ public void consume( int fragmentSize = data.bytesLeft(); trackOutput.sampleData(data, fragmentSize); - fragmentedSampleSizeBytes += fragmentSize; + if (fragmentedSampleSizeBytes == C.LENGTH_UNSET) { + fragmentedSampleSizeBytes = fragmentSize; + } else { + fragmentedSampleSizeBytes += fragmentSize; + } if (rtpMarker) { if (firstReceivedTimestamp == C.TIME_UNSET) { @@ -150,7 +154,7 @@ private boolean validateVp8Descriptor(ParsableByteArray payload, int packetSeque if (!gotFirstPacketOfVp8Frame) { // TODO(b/198620566) Consider using ParsableBitArray. // For start of VP8 partition S=1 and PID=0 as per RFC7741 Section 4.2. - if ((header & 0x10) != 0x1 || (header & 0x07) != 0) { + if ((header & 0x10) != 0x10 || (header & 0x07) != 0) { Log.w(TAG, "RTP packet is not the start of a new VP8 partition, skipping."); return false; } From 1de4ee3af519f73e686f0b301eb2cfb117fc55e4 Mon Sep 17 00:00:00 2001 From: Shraddha Basantwani Date: Mon, 25 Apr 2022 15:05:36 +0530 Subject: [PATCH 73/73] Add RTP VP8 Reader Test Update VP8 Reader to handle missing frames/fragments. Change-Id: I9eede8f1e3a20fb0ff2e7add0dfc60f0780ec769 --- .../exoplayer/rtsp/reader/RtpVp8Reader.java | 60 ++++-- .../rtsp/reader/RtpVp8ReaderTest.java | 180 ++++++++++++++++++ 2 files changed, 219 insertions(+), 21 deletions(-) create mode 100644 libraries/exoplayer_rtsp/src/test/java/androidx/media3/exoplayer/rtsp/reader/RtpVp8ReaderTest.java diff --git a/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/reader/RtpVp8Reader.java b/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/reader/RtpVp8Reader.java index dda04bf8c6..eb5e589901 100644 --- a/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/reader/RtpVp8Reader.java +++ b/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/reader/RtpVp8Reader.java @@ -15,6 +15,7 @@ */ package androidx.media3.exoplayer.rtsp.reader; +import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkStateNotNull; import androidx.media3.common.C; @@ -50,6 +51,7 @@ private int previousSequenceNumber; /** The combined size of a sample that is fragmented into multiple RTP packets. */ private int fragmentedSampleSizeBytes; + private long sampleTimeUsOfFragmentedSample; private long startTimeOffsetUs; /** @@ -67,6 +69,7 @@ public RtpVp8Reader(RtpPayloadFormat payloadFormat) { firstReceivedTimestamp = C.TIME_UNSET; previousSequenceNumber = C.INDEX_UNSET; fragmentedSampleSizeBytes = C.LENGTH_UNSET; + sampleTimeUsOfFragmentedSample = C.TIME_UNSET; // The start time offset must be 0 until the first seek. startTimeOffsetUs = 0; gotFirstPacketOfVp8Frame = false; @@ -81,7 +84,10 @@ public void createTracks(ExtractorOutput extractorOutput, int trackId) { } @Override - public void onReceivingFirstPacket(long timestamp, int sequenceNumber) {} + public void onReceivingFirstPacket(long timestamp, int sequenceNumber) { + checkState(firstReceivedTimestamp == C.TIME_UNSET); + firstReceivedTimestamp = timestamp; + } @Override public void consume( @@ -119,19 +125,11 @@ public void consume( fragmentedSampleSizeBytes += fragmentSize; } + sampleTimeUsOfFragmentedSample = + toSampleUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp); + if (rtpMarker) { - if (firstReceivedTimestamp == C.TIME_UNSET) { - firstReceivedTimestamp = timestamp; - } - long timeUs = toSampleUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp); - trackOutput.sampleMetadata( - timeUs, - isKeyFrame ? C.BUFFER_FLAG_KEY_FRAME : 0, - fragmentedSampleSizeBytes, - /* offset= */ 0, - /* cryptoData= */ null); - fragmentedSampleSizeBytes = C.LENGTH_UNSET; - gotFirstPacketOfVp8Frame = false; + outputSampleMetadataForFragmentedPackets(); } previousSequenceNumber = sequenceNumber; } @@ -151,18 +149,18 @@ public void seek(long nextRtpTimestamp, long timeUs) { private boolean validateVp8Descriptor(ParsableByteArray payload, int packetSequenceNumber) { // VP8 Payload Descriptor is defined in RFC7741 Section 4.2. int header = payload.readUnsignedByte(); - if (!gotFirstPacketOfVp8Frame) { - // TODO(b/198620566) Consider using ParsableBitArray. - // For start of VP8 partition S=1 and PID=0 as per RFC7741 Section 4.2. - if ((header & 0x10) != 0x10 || (header & 0x07) != 0) { - Log.w(TAG, "RTP packet is not the start of a new VP8 partition, skipping."); - return false; + // TODO(b/198620566) Consider using ParsableBitArray. + // For start of VP8 partition S=1 and PID=0 as per RFC7741 Section 4.2. + if ((header & 0x10) == 0x10 && (header & 0x07) == 0) { + if (gotFirstPacketOfVp8Frame && fragmentedSampleSizeBytes > 0) { + // Received new VP8 fragment, output data of previous fragment to decoder. + outputSampleMetadataForFragmentedPackets(); } gotFirstPacketOfVp8Frame = true; - } else { + } else if (gotFirstPacketOfVp8Frame) { // Check that this packet is in the sequence of the previous packet. int expectedSequenceNumber = RtpPacket.getNextSequenceNumber(previousSequenceNumber); - if (packetSequenceNumber != expectedSequenceNumber) { + if (packetSequenceNumber < expectedSequenceNumber) { Log.w( TAG, Util.formatInvariant( @@ -171,6 +169,9 @@ private boolean validateVp8Descriptor(ParsableByteArray payload, int packetSeque expectedSequenceNumber, packetSequenceNumber)); return false; } + } else { + Log.w(TAG, "RTP packet is not the start of a new VP8 partition, skipping."); + return false; } // Check if optional X header is present. @@ -199,6 +200,23 @@ private boolean validateVp8Descriptor(ParsableByteArray payload, int packetSeque return true; } + /** + * Outputs sample metadata. + * + *

    Call this method only when receiving a end of VP8 partition + */ + private void outputSampleMetadataForFragmentedPackets() { + trackOutput.sampleMetadata( + sampleTimeUsOfFragmentedSample, + isKeyFrame ? C.BUFFER_FLAG_KEY_FRAME : 0, + fragmentedSampleSizeBytes, + /* offset= */ 0, + /* cryptoData= */ null); + fragmentedSampleSizeBytes = 0; + sampleTimeUsOfFragmentedSample = C.TIME_UNSET; + gotFirstPacketOfVp8Frame = false; + } + private static long toSampleUs( long startTimeOffsetUs, long rtpTimestamp, long firstReceivedRtpTimestamp) { return startTimeOffsetUs diff --git a/libraries/exoplayer_rtsp/src/test/java/androidx/media3/exoplayer/rtsp/reader/RtpVp8ReaderTest.java b/libraries/exoplayer_rtsp/src/test/java/androidx/media3/exoplayer/rtsp/reader/RtpVp8ReaderTest.java new file mode 100644 index 0000000000..8bd2e347b4 --- /dev/null +++ b/libraries/exoplayer_rtsp/src/test/java/androidx/media3/exoplayer/rtsp/reader/RtpVp8ReaderTest.java @@ -0,0 +1,180 @@ +/* + * Copyright 2022 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 androidx.media3.exoplayer.rtsp.reader; + +import static androidx.media3.common.util.Util.getBytesFromHexString; +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.when; + +import androidx.media3.common.Format; +import androidx.media3.common.MimeTypes; +import androidx.media3.common.util.ParsableByteArray; +import androidx.media3.exoplayer.rtsp.RtpPacket; +import androidx.media3.exoplayer.rtsp.RtpPayloadFormat; +import androidx.media3.extractor.ExtractorOutput; +import androidx.media3.test.utils.FakeTrackOutput; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.common.collect.ImmutableMap; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +/** + * Unit test for {@link RtpVp8Reader}. + */ +@RunWith(AndroidJUnit4.class) +public final class RtpVp8ReaderTest { + + private final RtpPacket frame1fragment1 = + createRtpPacket( + /* timestamp= */ 2599168056L, + /* sequenceNumber= */ 40289, + /* marker= */ false, + /* payloadData= */ getBytesFromHexString("10000102030405060708090A")); + private final RtpPacket frame1fragment2 = + createRtpPacket( + /* timestamp= */ 2599168056L, + /* sequenceNumber= */ 40290, + /* marker= */ true, + /* payloadData= */ getBytesFromHexString("000B0C0D0E")); + private final byte[] frame1Data = getBytesFromHexString("000102030405060708090A0B0C0D0E"); + private final RtpPacket frame2fragment1 = + createRtpPacket( + /* timestamp= */ 2599168344L, + /* sequenceNumber= */ 40291, + /* marker= */ false, + /* payloadData= */ getBytesFromHexString("100D0C0B0A090807060504")); + // Add optional headers + private final RtpPacket frame2fragment2 = + createRtpPacket( + /* timestamp= */ 2599168344L, + /* sequenceNumber= */ 40292, + /* marker= */ true, + /* payloadData= */ getBytesFromHexString("80D6AA95396103020100")); + private final byte[] frame2Data = getBytesFromHexString("0D0C0B0A09080706050403020100"); + + private static final RtpPayloadFormat VP8_FORMAT = + new RtpPayloadFormat( + new Format.Builder() + .setSampleMimeType(MimeTypes.VIDEO_VP8) + .setSampleRate(500000) + .build(), + /* rtpPayloadType= */ 97, + /* clockRate= */ 48_000, + /* fmtpParameters= */ ImmutableMap.of()); + + @Rule + public final MockitoRule mockito = MockitoJUnit.rule(); + + private ParsableByteArray packetData; + + private RtpVp8Reader vp8Reader; + private FakeTrackOutput trackOutput; + @Mock + private ExtractorOutput extractorOutput; + + @Before + public void setUp() { + packetData = new ParsableByteArray(); + trackOutput = new FakeTrackOutput(/* deduplicateConsecutiveFormats= */ true); + when(extractorOutput.track(anyInt(), anyInt())).thenReturn(trackOutput); + vp8Reader = new RtpVp8Reader(VP8_FORMAT); + vp8Reader.createTracks(extractorOutput, /* trackId= */ 0); + } + + @Test + public void consume_validPackets() { + vp8Reader.onReceivingFirstPacket(frame1fragment1.timestamp, frame1fragment1.sequenceNumber); + consume(frame1fragment1); + consume(frame1fragment2); + consume(frame2fragment1); + consume(frame2fragment2); + + assertThat(trackOutput.getSampleCount()).isEqualTo(2); + assertThat(trackOutput.getSampleData(0)).isEqualTo(frame1Data); + assertThat(trackOutput.getSampleTimeUs(0)).isEqualTo(0); + assertThat(trackOutput.getSampleData(1)).isEqualTo(frame2Data); + assertThat(trackOutput.getSampleTimeUs(1)).isEqualTo(3200); + } + + @Test + public void consume_fragmentedFrameMissingFirstFragment() { + // First packet timing information is transmitted over RTSP, not RTP. + vp8Reader.onReceivingFirstPacket(frame1fragment1.timestamp, frame1fragment1.sequenceNumber); + consume(frame1fragment2); + consume(frame2fragment1); + consume(frame2fragment2); + + assertThat(trackOutput.getSampleCount()).isEqualTo(1); + assertThat(trackOutput.getSampleData(0)).isEqualTo(frame2Data); + assertThat(trackOutput.getSampleTimeUs(0)).isEqualTo(3200); + } + + @Test + public void consume_fragmentedFrameMissingBoundaryFragment() { + vp8Reader.onReceivingFirstPacket(frame1fragment1.timestamp, frame1fragment1.sequenceNumber); + consume(frame1fragment1); + consume(frame2fragment1); + consume(frame2fragment2); + + assertThat(trackOutput.getSampleCount()).isEqualTo(2); + assertThat(trackOutput.getSampleData(0)) + .isEqualTo(getBytesFromHexString("000102030405060708090A")); + assertThat(trackOutput.getSampleTimeUs(0)).isEqualTo(0); + assertThat(trackOutput.getSampleData(1)).isEqualTo(frame2Data); + assertThat(trackOutput.getSampleTimeUs(1)).isEqualTo(3200); + } + + @Test + public void consume_outOfOrderFragmentedFrame() { + vp8Reader.onReceivingFirstPacket(frame1fragment1.timestamp, frame1fragment1.sequenceNumber); + consume(frame1fragment1); + consume(frame2fragment1); + consume(frame1fragment2); + consume(frame2fragment2); + + assertThat(trackOutput.getSampleCount()).isEqualTo(2); + assertThat(trackOutput.getSampleData(0)) + .isEqualTo(getBytesFromHexString("000102030405060708090A")); + assertThat(trackOutput.getSampleTimeUs(0)).isEqualTo(0); + assertThat(trackOutput.getSampleData(1)).isEqualTo(frame2Data); + assertThat(trackOutput.getSampleTimeUs(1)).isEqualTo(3200); + } + + private static RtpPacket createRtpPacket( + long timestamp, int sequenceNumber, boolean marker, byte[] payloadData) { + return new RtpPacket.Builder() + .setTimestamp((int) timestamp) + .setSequenceNumber(sequenceNumber) + .setMarker(marker) + .setPayloadData(payloadData) + .build(); + } + + private void consume(RtpPacket rtpPacket) { + packetData.reset(rtpPacket.payloadData); + vp8Reader.consume( + packetData, + rtpPacket.timestamp, + rtpPacket.sequenceNumber, + /* isFrameBoundary= */ rtpPacket.marker); + } +}

  • M;A$*W<4s#SsV+z%BDwafhSbeC1M zXEfJReb^cSiRWu7LWC5HSCbj$AMFSf6WO}QvF#7D1}EY{sqx|w?~z)PF+RaYT7T12 zA?Qo=uIvWHx6Rc4<7%7Fk=Hgc6HYvLnU5Gg9TH(#EZbG@DK2--l@Kn-h(ZOMRof9} zTN=A_1xGv_G@O+zSoC~Mz+V*a_xRi7zd+MgH8yryP~u23?0=|AfYGj_7C#EL(Zq=`Ge0BwxAW zQlo}Ek|bX|^tB%eE{Do_LyWJ)r>zhEAn(|O z6mOpZ!40nrpjP5f^WxCz=3`CCyvpPQiCXd)q<_ex z{9W1e=1+8O49fc(8DS?`mp%4^C~au+LHz`7CS3Y8e|lM-!L{jEoGvI}bj9V&lIWq2 zf;1V;9ecPmXpvG8@D6B&8E%Q$lSH&HsEP3omiXIGn=UTuj=gia`pU{}@kY2D^~F~r zTXi<9ekhq$LBS=P@x!OBR^NePt9ilq#uOSl``^(3jU)LoDm^`&wRH~&NdD&v8nHCH zq_t+9MPw$4UKTRO!Q^c%(JvO~yo#(FQ~#*Z2rFTv58RH2^AqyT$S>{L5 z=`PFKHhv$LAdQUv;@KGga2&`npRW2MSlBZ)CT!%8@xH` zOnheUoh@@zGc_nZ;3OxQ=i~C!SZ>Lv)`nU!_NvWwulZHixEZPN^F9Q@=dzCT+C?YH zBJ(abDDjS(AAFNAt3O`cx9| zbo%_~(4{;B>FS4|6?GN(nMvJ_;OiX_?Y)?u%Y+u0< zMBVchl-l&cG-yqK8gf~k5W0<1cl3IvKh1Ns{{#Rv{`^B6R@1+YyBjU}sHn`sYqDP} z=nO$A?;pY#*XFs(EdL`sOFQ<~!SipRSJR80tfY$lC;jA6k&MyVV>%e*IzBx!t(~U0 zR0S@3$n_8V>4|89#2IO|YuwYLD`2Nd|Ijt2ojf(E{kr2}_PM%LBKKdBbc4#|H`hfcfvL|rOdZ215calRlg9*=Oz@4at z1WOcY9w_LRKUr_i1RBM*6I&?}T|4Dad3e7j#L*X~!`%fzb`_7ga(J)pW_J~0wFnff z6xj+K^>7CnhFmQ88MczuRn41o^cUq0Q*+zZoxA9v*)WZuSJ2Y@X#x3%-O+;#gBlT=c)4U9mmyuX_C=C_%gaCN z8#-`Z0l?lYE5P1K-pm)+j|mDLcL%Bu3uU>-M-13Zaj8W-i92^yt5SBGTUY%nnQRB4Kx3x4rSk7@QUB|>MC5VzN z)0c)1&r{?^$Oi*~%$*`ZuVGYUtT6fcXw&m%;i|w7tkN>ZKS=!~(;Uzlip+evIZRUt z=zkCM;=T`oi*eNHu|qhIG~<)_@it0ctP2-#8Tta(%OV7t zU5g|>AxSi>Jy#!A38zY~d?a?vI8&4#-}U2}q&2&ih7zW>0M*diYfxjOLBakaSS)QgT?}_ zNLmWWg*ttNSQRGLB})Sdai(;hqdD77HrgnVcw+ItuZFDwG)OWBM+Yu9F+)-B2rE_C z`oRHy`bhuq>tB{hLr@f*7h%&z6*}Xr6fM4+S26mpbmFhV+RU0qglOGGQ84JKQL$PP zorAfi5LPfh)zFN~LzPJ0qP*pa8~e&?fqhby;Vd3_vaVFwU{X)*cW!zH<*_d`#&Wcl1^Aaez&+!s|6YDhKISsS z2H!H)+tN6@#zvP1(+DF~=9N}lEUWihIM`O3MUU#!par+8k^)^5X5FV zIbFur(NBhRU5UkPxa5grBoJL1a%RMxFLw#sUH)6j-~*YNJo{|HAOycZkL79DyN_yR zkPJ=Mt!W%}Vwazqv4sxKv_^YW^p?sMy^#+|BTYyuaf^H2cOehDk~p89Wb5jFo7OQj zKWnnMGMK0KOMjv%><7=E`qbH18jyt|&{ zW_9?XXEN-!?P@DY+CH6&`u6C`)GTE?$e31O=GxS#q&4^J2WQ9Hv7xxZSMxh~ecIfAcF;~MRolxQPxA;)PHSDY4n4VouZ zL+BIr#P%cG?of4FL&9UINHtLi-24#Ql9n|Dr98!*J3cw0MJQMcrQ|y6ovB|oTx*4| z^i{D>2YwdA6By&&!Q)c29oGd;f#aUwL-()NGtpHtvp8N~C1BvIL@~(0eOS`Z=S;Vk z25mU=i7Sots`OeRQODH>F`#$#Lk3PFCAiFN>za=}RafuWM;BGmDan%>kSKaN+iwv` zNJtu*nl_ZE6CZybizVq$if&@+SQ2SsSnxO#8=!-$Ja4^vH~vhqtmM zv+Q9h_!IPX=AGmXq+p}>I%wQG!gD215RGuwaf>7F!C;u&S`JzppaC>uFCL?GacLg4 z%O9`dz3pkt=lE8z>$c1tjNZN@h5&Pxm^;mHdf0s>rW54jr)?^hO^Gw0F%9n{}n$`!1LX)XF> zWm@iiJ*_T3Z3f?~%(7?RmbJVEc|!4w}_D<(F-N?M=n_R{G+X2wye9^NPVR5z`e8_<;3^MyK;i>RJX zUR$SP4{ClaP@s?-U9EVxQgr{txTUfDl8S#5MLSvBLqRt)4Hyf;HebogUlI|(QnZ-D zUZd_>D#?bKd3Kw$3&bsPRZbQk3SUu))ZVx4x&`>e*Pa8uG~*Ii@k||*vnjPPf-kC0 zm;2*Da53gJM+L_jg=$55BltEmY2c)7SL^W4$AM`z^D#x-8gN80+3SyLQg`(U zTcRVQixh{cpKFv;-6FKqiif8^4HSI)L2F|{{;jQWlxOOiS?t{7`pZ}ysQZEReh_4~ zv274Ey~K3*%zQ#uJwL%9WU-{c@1TqOG43^13{`m-mvQy{n)-z4pe{oM8AtOY(Dck?|F6R5~?{J&N5&)Llf=H14;ux9z7X>#nJR zYg|ld;V~Lw*f?n7Cg(W8x#-hBpDPSoyU)EkCJRD@-&Fjc7htS%*S;PT>2;{o(2f?bJ8K-?C$l&m=7d%PmA! z!tNign$FJF)(bwcOaZS*&htyy3uV1PJqQ7~qyu*azwlV`d$j))`10~{$!?a-*uK}y zaa{J-f4_0jg^&riH^qRV{~9A2C*;S&!!-~!5XVdQc=`o|9IViO9pEA>dR4f7ynn|S zw+kYoHA^Y08hmEaNLqoz&ia+6ZHAd2|Q6V^)Ek+8khWwJCYaWYE3<{WQ69eXWD zF`qnE?tqjD_@YS6-SWk4^o!PCP1c!A47u?WI|kvd`*81YB1-wTEEI2>k8`3T`ikIPrGKHo4XY0P~?ZBnU9-+V!d}(H9wqg!i(? z+xxeDZ01EI!xBI>le=o;wWO5iNGwxoO!nkJ?Fo;Im%YNs;Fz!=cW(szK>EI3d z_MO_GFZv$1>Z#0A0~$y2|9E=KuqfL$T6l(`89E%g1O(}j98$Uk6p-$2P`aeMyGx|I zVF>9)N?N+RYtQq3dw>7uxQ~GwuIpUuTp?J9ZueE>kAZNZjlEWhC-S&p!~930dyN>` zz4lU||L3+u=A>d|r6fzX(xZ}qMdYL1P$vBcM5Y_X+q;HZYU+RBhDTS{dGM;zmbeOZm7T>^CO_R6OlCyN$*yNj6cUx+AQQN3}=s}=WnmhLF<4u+) zS#mLhTASWERGYudPQSg;2ft$u;PjivLnJAzmb`RNj{^KsdTd+ul}r3S^4m=N_^nR3Qs;pK#+!}*Ccp_*NbI_w!Te@Q?H!xMGz?^l^7-vb_Jwj~!o zbFk~K{SNn-^H=}AK3g>=Lm8pT8@0{4g-_v(*>IpBX%oKb$Z7TnXF7Eqt6gyo^dn12 zjDFF7ZSkoXc+RAJOPXBrc&YnbZT-3v*y+<)|HAL7fAwyKcGp&xL)@E3$;Je9?~j9n zOMCb>B|npEu(Qbt3-W!OtL$26qIv1~>|pl2u{HeYn_;AV<%`bjY&pfDrTiqz;HPPI z3#eA_5EupH&2}J}Je%vA58*6aleg23Q|vS!TUAv@l`6O)Y<wv^s<=Zd;VX>qR5l7?^DUzeahPNH^68vfTC0N z&h-tK0S4%+;u5}3j4vmh{m-s*hRmn>mB|X_txRW&RFF( zPe@^N8gBYi4?JK4x3&vm>kt*slG!I7bGnL37UA)Y;>%7@OJy=>o?Yai(IE+;q(gZh zx2JXfuRyuy^~c}J%f8#q!+Gyol>ScLrF6;FtnY?RD1ja*Uh0n^mVfUxm^}U=FUl(2 zoRXMIv5PQw zd|k0R>LfSI;!M?&MjNI-uV87<_R&PC1P)7eMBIBs6ZlJxmXB|nJC-)yVT~o?i5p2J zz8#h8yxhAzswa5>7VwR=M$eF5c~4-`m||Y6BKVVmM-PQ$1(lH4j;{(n>Y*a0xMa?z zjoq`thmK8lBlmdndUOh{9VECZu&Jr(Z1umr1AGjHBo!(9g`%TI;hn9w#?4-KP7i-W z{xtG9W7WG^yCG?pgo+J0N(}`9cth)_}C<%Vg zsDQ8ptit&=GOB7v6&3x&~kYS0wm7ax%|kvFv%$7@U$8Wzu7Zlb3A zID*S9yjk9vM*m{Pw%n($u}(Xh`?#UKhQ1j2p($0o3&$}s92E$ssc`#Bp+A+es+6t z50yq`3Sq<$FII(ju?ru=IoF^qxj79Em zU@k=Rl|TedhT14O(R5X?4`=wm7JeP)E;=hZI{AW&xkrcr_jEy zO?`~JlpDWJ#I9*_N4A%QY);m*jE|3>?_}8jgB!uhX3;nK{v{|2cPGFjs9qjV;RlyU zzg=BW9nqUN*k|ki5U?qQVZTlda5xkLYoTaAW&E|MF}BmkbY~GF{rx4mf!*Ifp5kOm zTaaoh=Q)Gwk|5TTw^;%gNZ=BbcRE(Sm^mX#ioi4y%)H&$L$dgk;FfKbO@z=JaC62^ z8o8A*!iHn2xgWrMYU1p&(7J4kZC&jY8Z<;AZJJapL4l~JyfM{6Cbq*=11!2vUSL~l z)JW40nZpG4CtvIumZ@nrAv%4on1sN@fKEjD_Judfq%AtWo9C#)yPqPzx+P|4jt<~y zVrw(N%Bg~{$Ri@3)gX#nZPb{9oD?!?oLmiKCf+OoW7QOz7M=&OtiU*Q^fzvkkoQ!S zF|vc%WMPb2OXc7!?Gj^v@If>p-sjxURJtV_Ykh`CB*+BZX{@l7k4`MJnqnc;gH{=T zW&h}#x*`opMMG_ESZPO8HvVQ0ZfmjbTCuDAAk*SUEia4r7c*L~3wjH+!DL*zFkPiB z1zf7a<4>LMN<3#C7&q1as*ga7IX(w?=`Rrfx)!_6R7ZyN#$m-4n??$xU{JB<$FlWQ zN2eS%xpwhyhPx$kO0AwUA3+8mg)ldRvOeVGu6ut(L_AC5m9VOkQ#Sd$X^B-`Hz0&x zZCtk)8)=}m?hRvCgfJNLXTS}@n=7zXsogJtx&^ssE3IS=R>k>p{VOi(1}nWTCcjfn zrt4tP#K91~ckUCvZ_ZHR1<(`U$Yezzf9{L=s?6uvU0ci2*FTQ|899OvjGU1Pdrz*b z)adL9x9@bm7c`CNpgYX8n3` ze$~G7ckw-U+Wfkzwd6g`SN7yI%O_CyMV?p)Ff!`t!nRAsxQ2sGW}z`9|L_d&;wb;k zJ!bVKaTGCkjvMoV@HAt-@6Rb2SH}59e5)>^&O4{jIbB0VkO4xZ?PRl58r9e6@1iIf z?`*iYlU#_A&Z5BUr2IcB836iL`Wv=v#CI|Sx|NMQ23qsCwA3!{&Gh|p!eAC^7edtC z_-I^l85B!C0`}*z&{4ZRZ`e@>LUqy1MJn*VS@Qv?S%8zp(KRkk9rVYJu(?SaH&^+Z zgMqr`vLObG3e7LZWi-_C0uqcS(GTNQOhCBXQ!y&d7#64k40u$?1qfk&?Y&U+;Z>*4 z=CjZaxt5K&P8a8F(v9fnG1=VQ!@=zXM?=obZeRD`_&(43x=z5p<($lTw<_}%dQz=< zKfKBCxv0x|KJ>jkeVypKoAMNS%pnr_OuAu@o~w*0f%1W@UOHt)XuJR4q0-R$rD-QM z*B@qrbpbPw`)QVp zt0b<619_+EAF4Ci7w?)|URn&pZDv|Z8Cj7RYBkCp$ep*WWkz}%&`Tk_*Zms;d%h?> zWzoweGw0ttdpQ7Wc$2pR42jL2n_2z_O~3$*T(qvh&NY^kGdSBjn(GYfo^lCofT>m}~qPiBtr9*`>D#|?%YVSRi~js;U}%V>q=dmDJy=XrN0=6d^%J1s7kRbHF%afca5_Bs23v%|yUdAKd@1N; zVl^kIwv1c?gQZmSG=+9MH4tEx$$A}dB~0;6!#h^+?dANT+WOjvBdN;H`{&qxUlRvi z&bPa>!Vo4RVAU(};NLu(J3XS=+opVl zCEGLmy7DEzl$GZAL_~V+x_aTE>A{Y$*=xcNZJ4ZV`Zx(|mco=Q>5ZUt&0s5nY8jl| zXle3`DwQi51J_hX)N-Z|51*73q75IQJ0it;Uq@3OUarU#)%NG>^(0Sm+fjW$-{Vyo zO5V4h@1S`J4S1{=iG2T9zi^B!KH(LqF{UUf1EN>|6*Yb&R1t~i|NIvI=a9(2$CUi2`3}{mg4YQTWp%uxc$?IARHjj zSv}b081HlUyB}JuWD4=6{GqhGC(>qXfz+`%AfUcDDx@T?ZMjDZp;iWO(rAX8kDp&` zpd9@G0@#L5;E#^~yZB8A2SDN2B2PFIIU<3#z+L$LH~y_Nkn(kJ;BNJ{GlX~bJE*KP z1e?Mq-Bma3xf~pfmy8x_ktGp{=^qjha+@HqjT04MZy`Jy3bvzFwI*1{r=7rbi!8~@ zNW~yrW-9nocpv+TS^aA-X9t*Ao=U(PlcPxXdue}ZfvnOUDZU|#zXOs<8Yrv~yN{YH zrl59Gz$d4Uh=uE9k!%uFy~*hhHd#?Jw1uaMJCh64oQ4&?;Wzr#<<-7(&jfo1IxSK$ zpvjUqkA}xNQ=`oL*N2|HbCT}qmMl@C_6Z=KmMS@_riTnxqHes`Z&1O_nOP!d$eC7fJ;V^^vtYe<|Lil7HyM`{mQCmIOU>M1 zlZ3l+Tjfi#_^)lJ32h_K2)`JxCXpy*UDc#!U0)&c)GqW;4%lEkL;SP6XbREl5W>$* z?NYfdks_`_-$7@aKzwD$KiU{H9_f+;@SO>q8gy-4lif4bi^w`)Dt-DqqG+wv;U2!& zJljIE9kNH92RL(oQOa{FI$13FBidCWGSo7s{6}oU_A7U4qQcb?nP%TDE`F>jz0BX! zD_ab6UF{L~=V1w)gKJ1wckDo@A0#Rcq_cbw>>_xaYSbZf5%)BU2upkkFV~#&_+*8Q zMy`9Us_|M*tg0XDouWWL%#nL!I97ev31DKm`r0etsPI7R>ZKK<&%uO4sX3odT z%_3@aD`NO#C5idDsKh!;WXJSBYesW#I~M}Zi-5tX(`8;~kXJB&Iyj<#%0_dmSVJjv=9QKoo!3_U)&Dh3&-v{3ssBODphirf zk*#a&MgOGLu2tWyxz=p^vED<9vaF5lt(+<$x~O`xz9r@0aKlxmirCYGPhyZTG=Sv?E$EM$cD+gjKP|D$UoVVj@AwAJdk7@W5Ks3OUFd> zU%o8BlUzc*aKv1!ko&a5_i&cU*!YWy8+5_{2j!EWHQ z1ZsK;%5CQ~Rx71drpYfrT@VM-q8F=?yY%c*#fWG$RMM5|MjU~5xbySPIX-3R zd-1XH@<0shZDx4DWyY-QJFT_o5z6p)Dls{^56YXFweKq*u)NpuPnQDx?Q6bm-Fhk? zXM)am_zfToUNq{ ze~h%3O|UfXUotdJJ)+5!?DryFl~;r8iJsRcuJBL%1aG7BL2M$u~m^Rb4@Qv86l@Gp)R9YZ}l=M3I>h=y$P7&HJQtU3AWE6mL@wacr9lLVv2rjJ2Gkmcui42ppDKC zXYvOP6kn3WJku^(x8!5H2>2-5XzSp<=%nRY{@Ep<$x%Op=b%NxlAnfdS^dC1@DE}OIdRf5?(Qt!p6}Mm>|N4r&`}2r7%Z#{x$7OCDQ^ff z)Cb?FrI-|bP~^upU4zCePZ?Kw4zI&dZ; z_fQ}+JKLZ^o5R{a(75+qP$S4Y9USTpz{h;#xctlD{qf4F;MuDgI->8?%VwgcQeO63 z?XPX=^IhEZ^IIe8aE=u5bnYn0rF!-`V6KBA14GH(R)TW%A{Kk&0AKd{l}ps_1RFeh z2flp3Or>Q<0a4Q07~trgodHvgL{r1=6MCjKy?u?0IDe7KiR?!ESdLiu@gp0M8U8p& zT#q#q19HFzf$pi_vR4)c%>G!I06s@g>dOR(Evc1IhM#d-!ECixRGj8A;uF1VzAyvB z0bdj&nYDtA$~cd9=d!Aef)Q{0ZII{&cU5KOS$CChl<&)~Z$CqhPr!jU>>|58Pu8`Lqs`pZlXUs9&%ajT4Xo}nng^1;eRTR7+Ps)6USFGd{UoNZ2 zXo;u}vguiu(=B}GUXRU10Ob4Bf53S(wprldwO$d&nIoNYG&Lxhcqr@)3*K$pm`nyQ zZ{kGvIrVQSxp)2o6;me*A$*zE$#>|?#c5Mbtq=!hhg0K?=*dUckF%?=W9Z8p@bBFk z1pxVjq(}m%=Y#2sr@B8^B#3e_`1L8#kC&4Tme@G725TV?GPtW%*;^8iZYNn0l?up= zZ~akj0i_EEa6Hrt8D~jw6Ghn?kmg!`g}>_mSOI$>FH~!m|AHL;8;80)UUSZ-M0|f7 zmc0kSdPA@s+}wguuqg~04yez}$fZ@NgCQWZ9I`>8II;~ITJE={d`MO7_->a0nj1zi%5>2 z!b|}ozU#4>dPzmLp~uVAtt(T6fq2p8)(MkIDxl4_mc zmEQgmvJ%f)5|NWkD5&Kn*Z%_KEbb6-SOy%08=T~u6VVnQiaLmComR?Z{$?)fNETLTWbA%XONj%XyEt~Uo5w&hnkXkRP=y?CGXcq6X{6u-@S z{CMgmYxiO19otUT-Jm=Eo4)q%UUSXAR(Cj_^}57K7$a9w&vnq}&E*sJA89ci+=$+E zMur;iGhmv`W26BXe8^g>RLW|JkCSE6V$80leW|KK;vjj}c+ zNLhl`Y#*`8I;Cd>3ad+=D2%80!iA>^VZ0#eT`d`si#+L5W5;(M5PF4z0im!g1|Su% zwk8x)6k=?8YFzGrJ&I*ZzQ|lVxq08N3mAqyI-5D!^F`WWt|veX>vI4%?+~ve9Ti;D ziqY`7w4|eHs6E31N~oil$mx)1$olwfaHv1BaGRnoNQ0lDt(9Na^(G>{Z0GZ}{8rut z!9tKg*AhmOk*Q`z|1x%45YK8T&?^If`Z_Hzq~V+D4824ix1pF3`AzQ_PABJCg8$Ct zpMEX>OiuaBG}bZ!Fap$YWhrxTaFWM_S|1n`yzfb{2Iy*u^~5w2!M z;h#1~vXKuStEXdL*OtTzjshypsd3pZR9G=h@)+dI9$SraXYDwtZ^akuovZ z-|_)WKCa<|8d4(Ndc2Nt$(d9jL5{F9h>rr!4q2@`qWq=L0*$VUsc}$Y_N^R{=U+WY zSmJPI9vU(Q-ni<9%+#rI?twvWZBVx*a{q^5V6RVzVHfQH9chpgsOkqdzF#ijzEw$y zs?p+yZfI{^w@LrTD3&@GPO++rY*nfRIU3Ge2GuWRaMX!jvWXVF0d89%T4Dh{3=+3X zF6l9zRipA7&Xlh7NR=g1?8AONA3AJJP^tMss-e|Fi%e z8vgkg4AB-?S?ZumB5I(9$XNfqf8izr+K-Ee9$c!+WbpB$Aq{&v!%ov2zmUfnPRSuY zJd)Jr+gBZ3TSEnykn4htcI4&{K1IY(Gy*)7xE>(^iS^H?40r6k6KH%04uggiyUD#S zbJQ2*+tuQ61Im%9JzxdD#WTilK*f*j31ory+VQFwu?djTG?ti6P!d-BZ|#pq{&<-0 z{ioycCB?bkvj-lUM+H$&3p!bG7zDy7i1`Gas|P(Kn1L*nRaNI3A(a1kyY2y9_hTq` zS2M~EuHHe{9#LzL9jBZ6&tbeq~_-4?EN@?_7EH+(IxItGc&lnBoe5z zIrv>f>C9*DR(tY}V!*%WyApxXoH8x&F*5H=nwlyVU<`^ZsdoBP0=5`Vg{*@Du)*q~ z>`viyZKm#%OhI9UD7j;PUg-22?Ba}xvBt4zfh(zLZ0HVs;@$oScN;I9{rT49VAT4} z@*pk*)+EcM;WR)i}ZL)b~&ueS;dC6~T2SCQLpZ*<@QLtu2clq~&3(1cbHrLY#LV`(Lwr5Me)Yrl zeT2UpJ(~W|x;m~*F3{SL2j;G(p2JVAKG98vQSe*S{w5p(h?d~xAOEq84u>pBwi6ywlL`?_|<0-pZR5mXqANHAGr&q1w_|Qoyz(EX@NEk%`m+V*J3P z9ryktq-I`5hl$6ulPpG;N_JC)nL@B99LO!L5W({q`WgoeI^)vl=>8NmM2j188Rr@^ z2=kAUObccpvkLanDCuFoDFut6eWbchxqnk2&s>CV5ninr?|Ppz+!f2kQmaR3+9A;X zM5k+XZ{6ATCQA}mk{Is#l+g} z8RrlAOF`nH=~spZk;>&G>6IOSOJ%!?9<)kQ_aQz;2f4s5Mj<*V)`T@A>O`ji&>4>w zZ2l#(-7dk4O9zFL7(m(acT-N#PxZGVU3zVlxM^-8oBzckKZ0v8j^<@ypO~B`VrV! z^!$-xKaXPbuPV+nzsV-OJ*5^y%Colx+14X0w4Rg5x}8J79`Pu*gQ$qrALy-`4u!st z49i1QStW#hsW0=H*h=GH(7tdXdEZpr`=F?Y6<-r($^uQ=c8VZBaci60IJ_3#Z6ql3 zoxSPnRc5|LiiNUG9JYJQu#{d_Jn}xus!LeOtZ)VF`j;!Zq>kd0*%bDgxcvOFD~gKF zH~0Mg#nOUe@SC++lGq%7bHAD4bXrA~JhhtSgkF^=-){B4JRpyr{kzmgrE?C2AYUYv}5%8f8!ehqJPybgh}{BsuxFO;2V|_Hlpq zd#mx|oR>HB=Q0;w7FAT4`pK_MFaEoW+;YI$0ndnMRjUlD*!+qAK(H~i+V*St-22ST zN#H<&>%@l6BJu(sbRj;_(-@q(;|JNV9uZQ61jjArnUB&Q<6dy&QrVgumX?=t5L0YA5;DHPB#yJ)Vhgbt=p{pob^}tvWDe8>_{o3&fE--?A{(;Uaoo+-6LgP>ofeg zR=8nB;|KEzE|31;TIY=Tp%AAPE^3$EsJTB&PqKKsc&7mJucFNK|@DCRI zx4!VtBK14qSzL6+A%g(A+K(ic(ifEY3u2st5(#Ha|J%7ko|vYj6KJ9D+G~ma%Tw3O znEp%3?b>U|Yw-WY_sVQZC;ncy`=mK~;r^$Mg^%Ua>zAzwzwEy)`>iH-G6f5-gm+{c zQM&h*rM$5FG4O_VXm_#lsy8JDzTVPd=Aq0PnEc)s&vpsU;5+Z+esR8d;<4 zJ|eEtL`qd5uL)}IJawo_U2QDuBTc4c?AdL`v^A_X=*s>Z+MoCmc*?R`=}x?O^n2P+ zGi9@xx}ivkfW5`olM9em?J4n z^4NEobCIuU?%?rD8KDxK6BiU2U_XLyqPhDveY$%2qDX3sjOD9*erk&0ID9}=Y|-WcxT-$X3KtZUcQ zpjILA{)XlTtwc=KMNb)JaT-x`Bl(eW}B_K;EM$CiT3AfKMjc^P{FcrboWqH?$(cav$sjUK|A@H5O>VvK* zP--_0V%33dGMQyYCBevCri@)+%AVdp|Y?QA?!1nGx~ySJMvn zNMcwIx`9%oYvFJ-d~7-V0X^=DY!z7o&*sQNwg0(J~#+gEjqjae$&5f> z#~;w>AAjpo#B`b}i_c!ISavz(=ZEbcW+s1$hg9Aeiq@P>y=Ly!3VK0Xa`y z@N5l}6aOpoW!{A8i{$WJS)zSs@4M`APKEcuVK6e(pCDrmk?-Hnan?KzSzK%*;0+JH zFI!FDpYAx|QowNd4~Ys_x-@8SJUx-cPzd+!@1wOgnw~NH8^|r*X3P@}${a9ot z{Ni6vGRJLpiyO-=GDyvn2S?WhV%0?bD5L$fccJTOKb$?>kRcfJjeD&WoKh9Gn$apt zsRC|^SBV^`tHzndh>2PB3gF3%Vh;X42tc%soOO3yk|5g{>_D5wuX<%47EW&=d=omz z4YnADt98Whl*t+tZ_?_{_Qj&W-00+&`&^U~Eg+&`F&&OG9c4cj5DF=6K6V&!+^e_@ zIITyp|UMgRji0}a= zW(sB-H}Z%#H~PfC+wU)EQ3|gT5P)O%`0bbyoM!wxRzL~Kpy@3mf34A&zi(V z2}bUCkjxT0^v_7h#OdpU zZ(N`7Tgmr!%ATLINEZbUZ_@_BE*!_Yn;F0EN%cSht-8Af(rXZ$n~^nmTG5DHYIOgl z!dXGY{5Z|5Q2E=o=P&hCQ_goc$(GIW*+x-6h?JcsNH9)8!PN9xCrHca@E$uDhnt?U9f#QPM+FYPcbEzq?6cSZE#a2JCu71{|^HQ+-y&Tab| zx8FJP_@#ep+SW5WmV;+2y&nVG@3sTa@-Oc*bFvJx&B3%mCo6V)2Jl2b+7IjQMrVyb z@);kg!#LE!JARQTK#N;_a!W35e$HeKq}h-=T=Eh0A85a(h|fF~yX%fhC;6HRCT=F& zL9mkqSI9>OYCWb}qeljk+`FYeOQ8m6d&mg$Y@Vz;K_z8dOE@bXq5f@B7zc2 zjn(6vYISP;lGC(5A4<{)CJ#8Mv7ezCjPjRY|BBuz2w3TN?BN4Lg8i>l-Cxn5^|o8^k3~?H(u{9DPOm+Uv}rSTMh<72w&LZkH<*I*iv6p z`X);l$g%DCI=`Q6@4ivKmTF}^Eo*!=+GLnFzJIhPVO@i{xEw01{X49L59jFuCygZs zQ656v{a~kX=UT31Tb*U(P>)62=UTtc6vc?A7{G3ib=G{uCuX)4g!Qjm4mPX5W^WxL zx~{w?zy-KXq(rAS-?^`Yo7!Ku=hAGB`mHEFBL@krG(eNLr;5XOk&*=rgh6ba#0XG9d0V6{HgVEjamGVrYg^7g zZY-b6D9lS3v^2x`vsSOTZXThm`a1cxUo*3^3_J7~dNnr(yB!D4y?8})hR6zLFPWM~ zgpj!7GtFgBB$ug_Vy-;1rnfy-B2Y$5o0a%u{VFMwN&DYj1#T-Z+V+tBVkVI?Gey!A zVz!&cexmrw-)V(1Il^%z>y8b4_{487r<$YvnX3QFoBCVPv_ffo$dlg?83Y`^--@-0 zf^ZpC7w`agCYaUzp1nq{v~;M|n_1gO1KR0g^O;cBr}|5X(aYk2jy%Hv;E*kz>6@@I z%rtx{hMxC(rRSo8CEg)JC$b8hr7W1F$>b#R$UBv~8{NMpGP5(Or2;#B{a5Vz-FW|9 znM55PvcOBvIg~sB(CZFcZh|~)ptDJ19y44}M+D%&;T!N&X2udGm?aYW5$d-%@!ioi z%#oyq66I(BTAU`zVek96v^NhOqPE_k@ov<`0HEjQ7H>Oz;FNOh2t%1CWQnPFj!Z4# z;BQv!*LfRRRL%4r(S$Y<;h!jbzX1tdd+`8V4_E@H%^8%l*HgNlP~gR(45`Jq*p$#d zxSrj({dU#!Zb;cD5{|bs$llNWySh>*HYi&6#F5dEh$n$T5cc602>fp}7&t=!%;CUV zBxlak-*azlX3A%Bkqgub5v;J+%{ zEAJS`t^sLE-yhgM&%kV9_kjN{D3=q8=h{FGZ6}^}kio{N|-XtNbrNZT=q4h3G z)+tb&_A4KnT9zQUd#B3dUxNIF$tR*S{*L#vX(2>7d7@AePt&_GiT#~T?u+&jXSprO z>-O>OPamf}>o04eoD&5yo6unJ*_+gs*nucxm2Zb6SfwezpB1u?QOvKYV}hr2PhKCS za2muzZob4e2$MiCFq^C+r)0c}8|}@!6IqLHM38^Pnh=N5690KP7C$k69X}nC7$i#xg^Nm}U)AbxFvRxfvqa4k*<8^KHRYbB!f8;n zVq8}3fWli3I)_mQ3+1GBj@rsM8v3(t+{DhT4tF!D_0bo|Wtwwb?p=J}er<&mL_7ok6U4 zGn$>2462|zyJ=F3qj?k^`#G+Y^b>SgD+l%<2~xVT`@X{Y`SkweBVjJ{v)0i!?1_p& zx2V3KbO};!Z)@T&r`Kw~ZFrb~y^65BHI*B@a;2`E^;iw^&j_TkW=PVYsi}2ON7n$% zV{)N=O!9qP-8Jj2;JOWhww37A0N$?+{@aFwuAZ)gtMO5bASjG5B__kuX&+_qY7u0) zzZU1ZV|PobL_ahrd0*&jgEOAU99Y#e`LbpIQf*#B27lM^dSgL-&Vu% zR(=h>Di?XJ5_$D~xrCF22dDN!FL2uYf6$s`A5LiGbUNe~}sTC8plM4N_I8EaBY-BQ%i`MBFk*uIZb!519Hi4IZ}* zUk64hN~CL=J_+&o}ef4S{@iWCo-m#nv^#(C*Qagxg*{OfdqFZz{;_{KuA& z8)`YUaH1W)#{lS$r%yBHvgtBNWJ2TzQ(ed=&6~$n*>;d6c&zP$$EB zO%%xN9Mh$|9u`Zg=ZreE%c$Ya(R2gt0y}z2CyddI`sV+}E_Y%_2OrsZYj;15iIP1q zPW-JYm@q}2URF-=N%yya!m=)MGx)!7UPaaO)}ug@{k&e}+4Fn#1ny8@Mz=`upw5xAV=M zC)Bmqm)kSAay;LX1m2Z^o`Ps_Lop*nOVh*iwkyjS{R+)rw2)t>j}K*&oTk|3iIWcl zG1r-u>IV@fmx_l%Uvex~-nkKArt+XQmQ!HBbq;-)km7h|^1+ezIkiuNX zu-lo~l7K|UNdb$w{ph7~4rS)A76D?76G4Qr7Zw%KxD0a`{AS(=MEU-B+*G4i0pExS zzwFWeuW>m?s5?a2H)0H42;>SEL+-M-n)AUC#+oa!1uYELYY-5oN6bl8tIj}TU~A%s z!#`~draGI)YfdR4qcWOB8aR^sJa;adXM2mQ*wzgfEtQm%@Ij#xYZdD{@_ua6)Jvqu zf21IzaJ!XMhLNtnAm8AgXP%zSu|SLy7sk9r6ic!#RexpeFRFD!(6{Lu5-;3s8T zcZ@`in=ZDY`@e3rQ3mv&{>ajbA7h818ZC$LgD%s!UkkZJ^maj3N_>gI*d+pBguX%_ z{Skk#Ce$W!WI10YUA6b^01ggj5PH230{0*KTLuoxY0bgzKx#zIU2ZQc?Wcm1Z!sr}wh)T&T#!?^9S!7WdIwXz=H25V@$#$3<5+)!P4O_p3hpHdm59=@r zy86(7&d5~~KE8(f&wT;TQ-6YZvNzK<1W61S5|Iu>Mvac{a(*TU5X%_P@w_$jt$isx z?=k)daQ&vO%sFI^TBre1ug7#T=!hg6g#nuYg3;dSvGs`MMLaj5tsRq_*c~|~v;Ji$ zoQV%6_pz-;4P%T1?nV)_1MaNIRHgS%8E8ExM7W$CpCn9cGjrD%3-jY@MN_~`5_3>o zZdNZa$wB+iq?-oSEVi8uxiYsfPUMS5iO$Ys(p;1N(0#i(E?mrz2%$d=E~j7&e9*da ze3fEg=OOCWFAEOtI8^t9tK!u(D6#65&a&z50K4Q*M}$A=9-E47(_|O(ZCT2Xry4Qmtc{MA zPEp`Y3mCK*^)}L+JiI-&Kq`Z8Y=oJvMN4l=ORwRZNA;hXQz52$;)IvWi=o0dpW#)n zuRLUScXTPWHumV=F~j`P?sk#D_5l;Kq?%u^@7h{4bSEXHtwXROZXnhbx@-3t92{%! zfP`zbIR@)1@)2Fb&~nk7 zWwp4~g@s)1^*vqvkv)%#k^^ru?&d&XPCiqvs=HOHYqioRO z{dxz1K+~ax(vV?Be^Kqoize2byBRh?hf}&axVLb-q*o&QMVz_E$C|WO@4e?D_xOlh zn(-x*Wo0R}a8(McS2G%6X5-&KvgcpQ-oW+e|7qQCn|!Z#DdBF~H45vY|DOU+`Tr>J zgw@ADk-G%n$J5steJ@6^R}8DFv7c3cOfN3PsHzZJN{(kR44K;z?H8^C9Md^cAS!IT+Yow;R)YZw`}r#0<|un zF$LN(f8gUCdp}gwc=eg|_26<&onx)YhhIH9kltcwuSoApT3x(aXS4l%=U=MxS-?YQ zq)Myws>{foFuJ;6ZJaQw&d`Y<@?IOM%9*A+9u-|k6g(eAt7`7h{3a!BEt+)Qj(K3^ zRM|;8w}_YY%Fg+WV2yZhs=~vijBs3nis6JC*OMSn@um&hxKxpS1s?r?--{?BuNf{T z=4I4wxkLmF-1@Y)5{>z5u~g3ZPhS4!B19#13iTr=5kg#;5_Px;?o$E51w|yKTzd2bX{s4I)@QMh>!PKHD z9{>AVck1U9k6NFNsoVZR_@YzSL&v9K)>HP`%WX1wu%E%Ey*l(` zWacNZqYc6D@Av@({RssUF|`E!(TaucaAf5wI-UruV;fU#4=hsMdq=8I!1Er zeTJr2O3r-SE1@Vu_#w!YYc#75NBf&UfaSVt1(qbP3Verny?B8vg_yC=Bh{*|LxZ^C zr!6D~CS>LkGFMMqsiT)h0}3BEa0vVqtY%F9gn-0tAbrxv#%N;;d=ZV7jeciA|r~w&q7c@u-%wbedlq|s?o=JN@`F1@Jf$DA|1pHmb z(3p|nI1-+A{htxQ$34t^B75WF0BP0hQc*{!88-BQI91QievtZU-G1fd0P_C&EfT(| zu@uj*QDD-98d8x~;9P@4Hz7a3gP!S+lrZsPS|n3vRUwTlk4pAp;4dT@@qgN`IO{oBtu3?v8zLgJQ^ zGj2&TncDpm9=qtENqk}*xQMh4X_y8mZV4t)>*!)t&UT@q>}2a^z59?*_^lNc`9?KV z6|LnSE>8El%{u*O($Oz8akp~n6EYA(xjAHvaHgxT+f5Q!H^T+zcQ*b#fp>Qi*Jo;f z0}#>kNF@-m>E}M|Pvquo0k9T%fLJWo8|wFoD7yb1s6LT$jl}y)hT_f~ah$j{d%cj^ zE*Z{N)f{}`)2fW5VBg?3^|4zSikL~XDylumGb*6)2l405l6|! zg&e%`&g8e`cwD%=KO9$X^=AORIHjBobP2fiBS&E=fT$=}3l`8F$pEzrIf*r+S4W)0 z*V@40?r>ykDh^DK^qA1~pRIAXy3AE#A%J)xc~_n}ShE5=$3c78$Tq&cMZJ-7VJ$q| zrI$$Ovf@JU?Jb51C5=LTTBS+{Q=7#v`N32D&~r`i9qc6=7}?syNJT9r&O#MOG?r%U zzbcIUDBLNjm7H|VN;J+4v_kWRn;~nKFMof%^qJQDSwloXELU#*lShK?M=NE9s_~rk zWujape+O|zV%z#jkx>pL`+W^EBRo3DDz(F3BR?RdZ(OaHv;K5M2KV;DM=t+ciWKt+ z$NPWq5~}7t9}ybFkVSU{*9l-Y5Y+JAP zJ1bibumYE!k|Dk@VB5ZFxXQ*ihwyT5P_R*-kVtS>hzo|q_Xalu^$=tL-hZhy^c)O6 zinmFyN&kEtcYU=#4BbdLbSd54At@cAbV_%3iG(zQ zfOJT=bPe4N($X<>=TP7HJm34iYn?TJ0&6(u?0fHhUDvOc0obK^=c&_LZ1+~P_05yb z#nZ1r_qi*~tDukyQbB*tC|uA6GMEwt850mEYLOw67qylfvn_!)3Sotu}P z7UUj)gAOW##E>W=GD;3yZ}+_~+Zcc};g}dD(pvrekdw+jy}3%R&bPtoKQ3?FJSDP| za(IHs6bE2iWh$PT^m3=d9?f7JPgV5tvE3YbSa&(`$c;*D@zR-Y@>XT%0PHz^4(gZm zm$2IRsNH=Pc~UbM@TWv@f*|b%Zcm3BpqGzTq$o$ZL$xlCwh6;+0!S|5`bYa^Q}^Gp z9m5j-BumMuJiXM`sj6KZ-xcM&e|?_|Vn`$j*9{e(04pl_$4Je4raqy=2`d@0Zd(!X zw49^cg`JKXLKfc{lcxsF59ovH+f zHFZ^g#y(p}Rwt;hejt5yUop@h5?07wmd>rUeT@ua{c4|M4`)@A%%lNcgThBvPZ}3a z8k=l{%0Ko_HyXkhCP2KHkXtP70%b&t_!cc}A^g&SDH!Wv*)hEjPI9gSlKv~4C!q1( zuyeCb$yz3_Q}y1Y2_daY+rW@dXksESUpl_Ny@z(iyw}+}d=;9xwYf>(XdlIH6s=n<2J@5<9_EZ3RHaK*2IY%tCPjUq0WQYx$Be!!2QxC0?)LMa3(uD z>f`piSRC;3xHs^-g^{;ij(eW%>N&zsoCx;wU0+klQ1Sj!5;ir(19famI5?;Z)7|pK zxulE-CEf|{DQ1wA&6c_>Aj4Z^_>Wt0h=Rj?HqR3Wyx{%iXHANsO-%mrvp%m%$T=Pb; zEGmMBEx_ab{u?L~@MVDV5jkZdn-+o0;T9eQ1|9AkV5gQ)$K;p-B>;`6nFdjRl9dJf zq6cl}zW(i`KA;mzseKx-^Q!-Bvt@$}C{5$6n!V9h_Cgs<+y$in8dM+0Od zf_FZBbw%dX_L9oUT7O@pnCnh2w#|9bp{eZ&JU{k;Yu$`Y{$-ahn-EO0VYXD734V`Z zrrlC`7e;O0E^nPkt zQwK$fj!w)>btp4JaOhV-mZsudj~&gRpsacIQ^7x6h|)>Blw&Ud=}!kVG>NnmNKya^ zv=?kD*Hk(Su^*~}W>|;wN%m;qaUJisc3gtNKUw>H(Q~tg-cEro$*l^%P?Gh{;aVwW zbqEKs*E2VrboXzT%h-~-NAQof&2V^SZyOH1vhgCBaxK6&K!=@88Zsaf!*P!F&s?DA*d8i}Luu^#Z_a_m_lZ>B5&nJxJaBZ&P{~e=Ep#p* zQ@`t4qTZ#}!w)*O`VNVfke;?LX6Ih%8_ez4(jk^+`MGbz+HS{Jb-@4r^7qM0&*iQ8 zjEQL3YT&NVY=Xb_Fdjey_n!7)A^)bjFW?iB!nx>*!z>%kC7ZZkey)}~`L>imu3yKk z>+}{-0Q-{=ChfBSXLdQEGC&dq{A4aLwqPe;^s2vFpIxEc@@)>U_?_leHVZB1?4|ZC z#WAw?L_&5P0_?zc z5zg-=P?*!`sJ^n0v62nF#ppy>jaxY0TX$Y__la*j*42it>zXdOc2Ub(B&1tNdYqL59|(S83S^!GGjI_fJgzaAjWbA8+~6^gP@^rl;{#xMV!EX1fIFIB|>4J>3EN zxtC@~p#=EOwmB*^YVSe{e=XDTrTJ@uVUUx$I`KE4-PiAVGT!$7OeM6Ib4PV^|J12r zP+G^&{8P_?w{1`s@}0D$>-Fy2MQ!%t+uE?!5w#Yi&QC>Y>SyLNBM5gyr>cdZO_&$z@J#k$iwZU z(z=VPdTAOEDld4V|HaE|l?-%Ou&fxO>ys5|u%PJ3_6dYsric)#2bZu+f7i#E-NKs^Y2I9CNswr2=b|G$JOkm)KUb|=LqihuTFAEBus~7uOi~c z5`Ls_4?aZxmIUIwZ?D*fMAH9=2gp0x3jWexbBB+U)x&!n8vl93|4A?`YE7iLKrr~t zDD8?|VT<}_KqU(IosX{tF0X!PUO>GWGDCmljjR|OmvI+DXHi(7(GHc-;dRUsgEWpA ztL}WBwO%=l!jj%rKLegjDQD*iVq+UW-gc2EO=u-JMbY`@3&EAu*8C znq@4w`mSjS*KFRQQPV@rEd;MN zk5&b!8U&a~mtJSO=`|Y?Xoza;^`J83bm>OH?d6NE$`+Ry_E`ZCrk0&&N87&2) z$nDH(IqLF7${h{M=*&V&3@eEv;zSl|`7TVwZ9=!<_VZhNUXK$IjZ778ADol&LQ@B3{ji zKIF;sjmLpni8IGN8?@pBF1gSP|Jc7qrwg^wZo#wqzaLzVIXhTe*T7WMX^h4Oy#V|# zJZ-gKe`G`2jJqI33KnRY|R z8#GG4Kb498s)qrCe_mQDEpiEl=Np{0ugOQkf~*(JI+pXCi4Gw>rPkE}SEx{WdaqS? zs|?9hIcZ8xM4?yaxIqHcy~Ld8xXV;NbM;*FeSbmYw<*Pb#|HKH2$I(;`eJNhI;&3iW>HB?&19DQ=jj7- znQg z^_9+4&D+PL!6~BtZwEpTop`8kt^}9KF!y`%_$|h=V#=-dc)ACMdMG!{AY*Y2=c(Yj>r9uhq%C- z#FuBBXG94u8b5qZ3xJ^mKjh2&C(`g%2Q?`rrnHRPK+%$M=*U5%8EKZ|$M4gj<=K$P zghv~Rj4HO0{9}w;qna5rDOWajhsu|8I3+e^I+i`4LomA)0cNwlnwQa>%d|RK#g4SD z*YM&DTG+Tzs$#~HV;6poCC+jv8$f6(Ku(@^Rs#(slb-e5&)%~^D6OmV0g0pQfiu32 zBdQ12zb9sQCU3;1M?LxV=eEA6UVjR!x;mY=m8dwKaUs*eN!gNpHYvrpxSpL$|4VHh zU&CF`s*;8b54D0qp{f0752B%eSB^c<4@kqPL#fWW0bKn!4ifxssWA1JH>RBjchd0t z)*e3U<>o*%zDSh|r6v&J+q)e-QoKcfMhOdMWF?vJTEPE`>vSM^#3o!?WW5oN0Kr6j(|3j_hO}AM>E+Ek^~XJ+xn~f#~58d zR5gIe<3(cErd!pgufOamnH;YTS&RPk6BNWQW_tT$>CN?dXMnuF_7%fT4fFJHj%sgp zbNjAZ?L4A~UWJp3&lkucHK3r-K8oX=xlXW|p=Y`impdSfJ4-p6ADflgCrkT|8{ zKyfU#LlHwK^F&Y((3nri40Emw+hBhE^NLyO95{?y#K$ezvEvCjOVl@5Rm?j~Ropvl zLd-X|tPD#D^NbEb8MHNMY+pfZQG{!pHzP&duVzKWWP_%ZTO9cY-z=I%oGki%&QI?& zcvRf^(IR)-!%6GEJuJNB)4~f6o^Of$`sZ7GSDj3E^f&i>_5NCmR|YA- zfAkM;IIS_Ps#!kfjNZm2?FYiS5?P|}GEDLXa7f&Pc*Syl(wQ@*whxdYMAukB(Wbb) zn53012SKb`vM9d&<(GBg4A0f(#1a@V=Rn!kgk_E34Kcs`@&$YS zFoM>67uLFTKP?W?UG@E7By<#^1RxO@0F1bZAS;dKcfr1fnbw@UEGaa% zmo-E{d=v7fLo*z>n(U5s8b=I%Xe~A(4|W&rDEFg?ZLtoJ6_^Ma=**9{Y&@Zqj`w zZ99p!nfNCfw~ZCY$kwu8WX;d;NOwNY3o!D9j07-_e#*-@k||c z1+$kPlan}z9fd6g7J7y%ONG23L8Xs$i6$I1NY(S(pwp zi%yvYk`Prwe+D4LJexY4>W%6Xh2+Kf8$d((J%HzPJ+F$C7PFP|9F?v0(`E-Qv07G) z_e$ZK9roZ2Bmdu?>p>~=d0Tr2HigcPR8F1m4r_c^Es*dSpvhmecR?||0_}!XaF4>W zkbvc+XkhT`luz)ZvzOy~J{gm-hHgpDmv9-C$iK$q@6Gj>2(9+IL0iJ}%rx^TuP!wB z?y6ck#J-={1b)k1!dYV!uc?x_ZZ$g<9HNI-rS^NMEBYxP6!%lSK3(J{cYA~u-WXY< zDPHV_8Fbax8UQ4=2AtaE!A>dn~X+ zSqPJ+!3vqBpFU3fZu#Z(^kw<~wB4cqm5%+sTJ;S)qkp*(e=O>_JNFf*MTVr>FF5`c z@CRwIG$L0i+1-{_v19&ebd;|5vP)&c0#?!bFJe)VHUtvCR~*L9Pch$9MAnA|Bm!wB zV6#x=axvzuedZ#wdx)J81(O_;nN5+`_G;;eB^7tU%M4`~r$bS5|K42hPZCD$CJMa8 zC&Idhi%xULKAJ6K^6}7YQoNb1LV(EI4bRaWXHs0da|6B%nV*gfrwMCAk`D(in+=w6 z2s^PWRo63^*d6rg6r8>)l)@TSDeQ8ys{`*u*S?=lo%?sro^$P2Ztc%vR-&AIqURJZ z$~rl?Uw-#@(4H>w{bth;84_!FvVH}v%Eb5?6*teZhcME$eWM=I4Ws6ofGPN9blP&N zDGbxXKDYdajF)*-Rx*(4x7P9YxPHayg;m3& zR%7!U3>?-y$4y*f!hVy5{%V1jU7++ZPyizXZ`v7P98qU^EbT*bSi&XFpaaK zyA?{Z5w&Sl3=*JSUbq^%WH?w~&d(CaG{nYxTQ))c-km$w7=AbVmhh3ctGOaUpAF zVENT?>Kxl(2>m??xz1h1t&?(y)>;o$_pJe57(a|Sz=6|)_2vP4d4)HOn&u1OBXaDn z*%`4_w)VEX>NYc`EDG@i@(0UK2=x*bRv5z1V^khaUhPc^R=1ue7%>G zb1>X`E#h+pD1#I|60kPiNlP*%A;5D&C?X(S|C;{y41JL*{}@@D(DM))9+K z0@a_V#lm40i`}oj3(|B?&{kF&8sE@*^bjpS@j@;$JCeapA1Lpx#{&T+--;%8Li z;%`dsL6km4%R&34*1|btFg5huIdTB=@Fx*NzYO1`CIx0P57(L_?xs;4e>Uqm6G#+Q!8b_5l4HG(t=_J8*h`F~WV_X?*dk_Y$8U@RNh( zmP$l|j3auL3Ucdo)M%^-evT2RIZB4w%7`-@UlgN>&zGKc$4yyw?b~2L1C!S7}BqFe>g_^9~9c){j z_T)@N+*IJ~2%4Jw)nqrw2b;ihY_%aTam39LZh0S{?RJGf_a<1A+9BgW1KTMfjF54kEix5&&e!Ej?X81B@|$_@h1YmLy(``Kmz6vxFn3TA0I0Yfom?`InLH~+BI_4? zQB>^_@sU^ZI&^!MI);itXroF-g`5Uj1}Ux+qo|@s?OVw|-AiprdVu~2#e)79pJn^q z2V&bh?rs?A^3mmL8T<3mQ&K)PwKPlCmYKkl#(zo>k*Fc7A$rx!y`@$&Um3oRIPp+A zm)m|+-+^|y}`Wvh2|f}B5Y8hw9qdgGCl=bssgjTkT5KfU^?>@yj{K2S*< zDkxGHRE&D0nZu$G*zvb$LyfRExzaoHHHT5aS;hP*HDAN_>x5#aXP+XEkUG7K)GMhA z*Bhl@9r9UBoUGf1f}>v%K-cmSwh9&pVmkf^;R~&fstag8=gD3 zLG^Ttwe@V(Hd54pd$8B1A8ue}Z2o}+)Zz@2DrLJrK*UeUZ)GuqXmh~iABfgd=XGTG z@r420XZE3Zt@hS&)Gak_!Zuorp@ToX$ePBj%!ZD^ohRl^U--}qCm9q&O7o<$5QLII z1ivW@y(N9x-Os|E_f&Ih(3S1)jd>0;W3eN8(=)sX`aG;)Sts0=CIo-t+#bUX%oHDx zD%#rlkk8(?M{|1JA4I*JUA`Pzir*iUy?&v`-jDy!rKgNSwMPBakO=Fce7RG7IWl@o z4}1ureB4v*WnhjhD;j)J6RuiwiM+Ca-Ld{ywp=#bb4878;n3}sh!+EW#Abo5Se-1W z-HydzugPA}^;ww(=;=WLkVn|$Q>Q=BpY36^O3`Nxk1NSBYYh@W=Hr+htVt%)J=xeX zN{kKIzoBnqUKzZ#-~Ao)9lo81g?^00nrU2d^d0upJAtphOC%?^RD6g>2rzKNse@)R zRk3$(qo!ydFAVRu?{`S&7phw)2zK=H0^pf?x_v-1 zS)(~VRcudije=Y?=+WuHw|%H#nF9NB_02|Ww4{16Sh+uS%u;N0$wLYNnY9V+GYy7+ zj#OVl&f8$828Q|1zbcwvradm6}oens#^`tj0L5-ljA4xYebJSo0!sA@)jfzm_ z3UHHZHB|=QqVHghf)HWOh>^dM?9@#@)ECQ{i8~@i*TB(tI$TbLMg7WMxvD?D)Xvqy zyw22kAn*3KDcP8+^gV~3+TB0)ET!VatkM?Ad<68a%VHCW`8xn-gHns&Bue9c!ooy6 z6_wcY$9p-roW1LC9(o7kPw_eg`eU^#ego7rDE?87 zDXeS<&85ETj}OVUPRE_|t?hDY?!BHRtYl-a@quBgW{GscjZd8E67hYTTfXU>9A0>6LY*`P|`Ul{sy!$@AHoyBt2KL6KJk`??n*!Sd$+s5c7W?35`g%fjAR(i8B)u~l0;7No_okYsL z0c`9W?sWNZO32D#NB^N_P~qrZ!vhZ1isK;8inu;)(a_KMA>ytFtMH97KL0cqu9#7I z{o(b=8u;w{Xuh34x_Hqo%o*YHeet+!`}R zBl~gnbYuGtJT9njWZ;Ur!hU{e^hEL+`r0ZTSw?-`N~~vpA0!fRhnhIlTXkPiv7wI< zPDBvKsM`pBvn{bMn*JwYp1VMMPMXEx+<=XY2Q`od*`QzhxGEHS!Sf3T6?c{qW&Xs; zwYJBjvCl^euyF}LX!zZM>EYW}uAe^0WexT~TmOaSJeE`wj;~S5L1rvwdS=Ef!k|oG zBvBCB14o4bS^fKrs?~4A+_%p8goT}6T>Yt;CFWWe!SB+l#x=BEEBtzu*8bLUMX7)n znv)Q6+z~em!seEOe+fXz_gm+XMb#xNvqaepp;o3aOTvgnRjDgANcMotX!-j?N#h%u z`Vq>RbD^*+@6m?W;RK^Pcfb5EIa-uw&WuJjCd!SZ{3yLL8A*FYZI9yv(g9N$3h$sk zoyHWy$w0(VbO5BAAOrxBetvhw3hkgh(X?#u5jjy5Ko+o8W^Q(=OJb72Y=BUAFNCI) zpqeo!n*~G+xjMJ1zqd!YirGP`z-F>}+}`*1Xo9eAvcA7R|Cz!)JO8dhzv$Pvn3Lm8 zn~cE8v{4Q~ztA8!1l=~nEX_HOxCg>_#SKMkktbI4lDf5k3n zGDsu&s3VY{qt?x#X;{0Q=TXOwPgF8x^;HhOiMiTFq%SJ+x;=RXPb7k~}A!4owD(ALP&~(rtwItv+4KKJeVg@H~38eYmTY`9d6Kop%V=IOheV+-l=ORDLAoo zUFayiyJ>7bczL*<9qZUO^T(5OfcTFusbz25eA@PYA6=jr@Ab3OO=!ex=)XV|Cd9FsVP z=wjfmC0?Fg5HSm3G^3hUE=B&-;5_Y-Kkqt$T^WGzYNN1b!JaXRjnh9|t)=^h<>q?h zoHM6$;VPg*{AiGSc&){F8CQ+1!d5Uywe?e#;p5oLlV_l-@w)IYDWP9dFchW#)aAM9 z+rX>*z~|S2=N->izT$UNFI4l7Xqifscm)>$%fpW1Z~5rgLqM=!c_7Cd1f$k0)z=0sg1yCy0Bl=l(9O3RTei zozpHg;g_CYt>fLd?8g)#_PZ?V_oqX*>vlu)jn5v>PA)?H)otuO)`Q`Se0L%fj>MnX zY`tG*3nsh-6G?J}YZpS}%>yz$K3i3k;+6jHwo}Lv<5IA%S#c0KoHnh2+mAx+LpF-+ z^#FQx_E{t4#t z%dp+Z0si{>Al6)9MTTVyfm8)J!4?@hD~xc5w_d*9{3(y6ETSSV$d)y{I5EMruO{)2 zoXpO#5!6(c=d}T4GUPFe@UqU+Ag3NNYeoSyIXNsrJbJ`qru+ZMG{#mGmA7C7uu20BU4fNM9R*=}nvp2Wm#QL`eRGnNd z05d~L+tF;3e5{-d%>i2i%Bs!+wgA?zINc$$Jc1>Rzw*EQCJUHU05c!Y+-r5>>@|PW@rT@H7^DzsGa9D=y2Jhtj0J z0$7oQ5%Qaf^QVePS?Jf=81uL(lG%vPX?HEtRzv)bDm%oJ&>&;AZQNR zy?smVJ63T0a`Mk=MCCrNA;vYsZp?yuy7l-uwL*+Ev`elV--Mu%U^`$fbcvruj>m!$m6D>-}(LPCO^;M!b)|Lko10KE1 zIm1)*@#Z%J+ujqC<=@h07$oYkD%saeYIQd*E?y1L!((;2KxCBJ#(ddkA{6-?NaCO* znJ#mau=F{JMv|6U31x|ObuCHeX*wPj8{EUU64+co`vkxD#2?5I5aD1Qkv${H)H~DCprsgkJmz6KWE`h(nkxL^yGTeblREj)CK4=0@m+OqNyjV1@?uH zeDYSBIKq)6ih(FnmosSbW8L*RymB{mL2Hc|5(aXo@lx!95fdS6G{|B&>s#m0MZ>lp z?bISowLFPW1{zga3CTPfbt(_nLa=e-{&lmCxIvw}95t&<;9VrHYznc~CT`2c{-x}~ z?cHn$RC)Aqe)eYxj?AhslJ@a*dtT(}TW|R%^6iqri05Sd=HzkB4$5;IJ2o?J(bVe) zLlK#)#j;Po4P}Kq!Oc@~t5dN}hVm_B08r0kl$*AcFmK#-69Wpp#9Y%~5pFYY%lw+W zy&&Lb{rr#yIMlz9r?K!&ZJy zN6O^1{^p_U7x{&AR)Je(7$?cL%HOn}d(0hS9-}Z9VuZ6U@f2v8kK@FQ0X#=eAZkE0 zK=tv#*sxhNVBN<>ylUR5t+HRE>!xv8%y*}HMc{jA&GWiZJY;BuGbNT-_w`qMLIQ;) z^q`cryzXqgh6XEx+GGiDUA#+<7|FR6LgS<_%wHU6%&&cnf0u@xPtu2W$4qBgx4Q~M z_96pfc1YVZ)fs=;W^Je5r0jjnyx)H@uMr>eig>fMQn!hWbikI><5hiN+5`wt1f z^VI5OjD2azKR(=sh7j7b2eBi68TMf{B4`Zp>vaLDi$8<|aTto6-?BU+D9t_taDYwC z6tjcje|Y;PBzv5}W>5r2t@c>lOn`LiAw_cYywt7RT?-{C!CAjhpC9RSLfmozPHT2#WM5>gKHpo_qAI zmJBw(m{=~wUMn4;E z__snA6O*Gqhh-1ZW7+Ahx1~Q8*qlB_a(K)&aH-nfO>{#bA)bz@vN0P}smo(_fN@7#qu+k;&@h-rVm} z)93OYuw!75uNC>ul@w%&5iN&az^3-`ZPHw-k}Nn*0bZ&5OurqbBOSDuESef)1~U^9 z=+Bt8R=@!bHBFHI*;Y>h-v{2+wt$#_Lh=0p)${WisMq5enu;ogvCz+47R62~w8L$4 z$~^0>ucsR4f8T^j?(o!Us;O|3T7$}TwXql!H+bg{dD+;%#hBOV8qeEJwjk@KFvuav zCZgw`qt5ITAjKh>SUkHsJpoM0}6Y{~+inKDHgT#k} z5{(OIbE~@IRf|UV$9IPuV>I;N2X%Csw{nkP?!=r22f6+t4HYyu4K~aBlqJod&j&Qe zgU%5wB(nG3EJ5+vT{ByKllR1O3hRV|b*yI7l~#4aF+nrNKM)R22pCcaA$pAN8AiC~lHWNoNt+4_CYH^6 zy;tQV^{2{`zHLn28=X~x-nm!dsT0?42A;OFEqjv?5RBC{2aTJQ)}mV$M$ikuy%s*# zGA+AnWV52K;CWWgw$IUS-6NX?L2D^Dj2a2p$%C=Q5QT?^#<}}?tspArd)|>Z`2-4Z zj1;<=niYD9?VUulrF!JDFmremz-3%e0LapB7x_v=yFX{trO&5ql++rS9Q-XhHt1E2 zpQdQyEcMZY%TpbW+OIqe6EVy7gnjoOm`0LUJHct-frjexR2;gZP_t`ZN>3b=sw{6Z zo%~68uBNy{zb?+%WP9mOklqAxuM^O(YpO)pn(D}3AQDn*rl0$2IoAA)1FokRGi)u^ zMt6!-pa}vARY*M`%ShN4@J5UYl>ab%NNUq(((Cq#p7c^*%;otU@{1h!iUG0OJk0d~ zWsw<0Cq9Ssd*2j}s6&J+{K9(_Vyrd+#g{Ab*< zTl?`z+yy~cs}azlqXX)1{eF7w@--I1>ThVMx_CWQ`YCBqlJLtIzm8_uk%H8XRD$~V zz!!s(O}rFe<3JX(%9LDoA615IzpKXicq7&t-zEmLK*4$XnK#ELURm184`j#E9dbP4 zeRKF%m^!xIchydly}D%kdy&v2b+=-GikuJo{#bI)4f+Bb(dGp!wFJGm=m>n}jUGfyAZ0-$O~-E54gyGN z2kxjQx*$NwNE-NIlY?Ywf^lD|VIho|$5N%}`H@G|h^x#X5M}L)H9oeX8u=bTW?353 zZyD>rAf^Rt!xALr&f^$AJHl);_i1{0degxvCsg9<6@8xM4I{~t6@lGa0(=LApFM{x zLBN%DJzVH)r5D~%gZXy^;FsqpBb0M{3*%xkOeyY6qqB(jCO=O%h#%_5^y@EX@KH2g zFDq5pZScK57y*ISsL7|{mnX}AN_N-(@3EnQ=byyy|Bb%m+Lr{Xoe$Uc&K&m~>>$Bn z4;8<11}_JWAE37?obl9jW#2sJ+8i|-kHlK{0ecS~8g>#+RK|rPH#k?WJ|>iBZvrcQ zHEPXF7d5*d{U1(V;u&j&{6dltR==1OnsE?r;gI$_h@&l{?DeqT1}3_!@j(n!191wT z`PwOi*x7(P#Ij=)J@W>a?)w5tV=({Q^A%6~7e5G6)Z)qo)L|%a&G*ZVLjkFhRP9X1 zQ~MHai+JVhZm&UFmZJXCg`mDs>_soklX^EYXxRF#atHwWNNHC*h-Gz)e8nj0^dcdc z_;=FwPRnI@CMA4H-S+tBLE#KzY;0`xYWY81lcD1t!GXt!Y+YDp)OM#@q;@?#Adl2H zf*d~XGv=YlXF*TG(_H(^^&a5Ax-k-!*wHU*0?$grig&3nyF=vcPm=3Z<47N4$T;&* zw6k!Jxen`O4&_W$Duln@+*;g4`ag5gKxKHKrk!Jxy%$dz`%;VFATUM*yhd7CS-fF{|ETW=r z?{1rz+hV9GSq#*SAZwcP!y3OmnYs7A_Yzw%tkE`!dtMM+NubowHMw&p38e<4eO+Ik z6&8nhy8nAZuT8(@F^C##VM4mI5<$bgO&P)*7cR>xfnkE*|9BYx4YyDU{sotu7fpP_ zkCA&%_4irT^QxW;baEnfceF5M<{ z@pJUlXGC*Miy5^3Ej)`_G`d8*xkIdmR%H7T6SYi`9YzrNpuE1=Q}4*bwtNobufEa7 z(GjL21csh1@`44I#>K{o`GgI`AxLF&uH4{kp>*w^q&EhcHqiog7m6n~>?&xhGpZvi z`E3z2Y z`4QjmX0gcYVw;wXlG04*r*Zp=ngE+^Zbq;Nk^7b!KbGB0XFb+Zi){PycaZM8!xrS; z@BOY(#7!ddQtA%Ww&0f>{01A^JqaIFe1u1ioI3>@7950_uHCeW6)}Qcp+76^SOUz6P%w<`%jxs8F+=ad+8mY{}D_>V!FQN464M>Ao{j_I6I4E+KD`$mZ>i2 zBw)~y$C*=)10_*aay}?Lo>>tufR)tM2T2pY$oPch)f)kwJi=#7yBr$3TxvRZc7&s4 z&7ueJ;a8G*AN3ol#h$;oPI`FH_UH@W$vm;R4fe?PZn1=`h_6y<>AGql&le|>KAcl0>O_Bl;2!8(VlxOznJxNs; zA|1Fe*kNXy5CuyJ3s^}0@C2KQv_>P05Ln|Ai_g8ijuRI(e&b+^Ot&-_I@!!N?HFt) ziq$fk1AF6%9?}u5Ci^+`teFi%PDv=-as~vHMC!EU0vK%o{V+?7MY(H;VcrSjI6zJh zfFB-h^t)e7!TH0qX;qKuTh8Ans`MQmyi@BlaB!(?A^?cL)shS@W!<`D)_y2c_?{Ao zf{mkpp`f4IMelf3y+cIKrsOu;tf3JmMQ4>5ROED5eVpA;0uPT%< z9`UD4ocWX|Syo@#v|7+PD57{L6+BmD%c)ymDFf;bzugJu7N>@ix!v3Fj6Eh*2~TCA*RYD|ywl*Hrd?YtGRxD~4M?1A!8h|1`U}E^8C8m> z5ywYn`#ZXWYBD(2htid`MLvmUCM3h(hr@%9laIQ}XrQI82{KAifzC z_Nh|$n+%zEfU@W+dftU#V;!TBV1vpCK!v~w)N(>&9zZx0?y>bQfJ*$mr5vRh?>@`0utG09rXw zYnV7oCyQN#uS!nFn==K~3X%rV^xwvw)(azWKiO#!& zB(Ae|zw5q<=Ns{-@c*mK9RI1z%Kx*Keq?_>pntjY4ZK?$>C<*B#4wSPGP*;yHga zgr$G_@aV7knf%$95nLTc(^V*e(ns3b3V^v?Jgx-0d$I}cr0BWTq6s~&Qbc``;+b*{ zA2Jx}%O2|KF8Y%hzE;QEwxz{a3A)^sYJ5?9Zaj&rS(EVo)VZ<_V|Y0ix4hKa**d@R z>$!uTGQnIFhq1~-?%iRBJ;Mp{dKL`h!_I*c*@MduKUyz8OjEE}ejwOYtWi%mtFY=I z!JNo&n(^g5rj}O1h@v$(Uo>hcTwdya!A;j2g=OI<4JOO5>adr;$D{9>c49rF!2~{l zX6^NJluF1N&LotBLEHtYdWL11iZN$G*bv@Y)XBYRY&PgE!3`pTk9dvPvy*EvM*Xjh za6VsNYHk}jmbAWZ!B2XIrZbOxg2+5cV|!qk50=2y5&ij`2Zddgl{JeFHLH_k1}sDr z#lk<8;716NVs_-Dx6vO=@c+1H^sP`lWmSQ^1H*67kfC=iQH!7SeF6de1tuCh{-JDY zX|M8Kq8G1FaVS`v+`U6b;O&(`rIYvjXn%fwjPiNgKj~N=%Y=N(Z~4**EiP#@GBR>V zVsZ*KaXx6P@-5ig@+f0K2}qE`v~5k2f?b0uFb`U~99nzwAYB&q-8Rl4p07{O(%1ap zRIz{%%L%crnWBlavkiQBLuf3L<@K?QY!W)~EexeubI{x(XCpp$9IsQh6+uDJgFtY! zkQ;tQ%b9`gMF0-%i^g?^T?9xujCD(XVgu*roOCm2u@q!x?YdhR2e0_&`R^W#o)D@G z+dB{Evp4Q9RpI+|Zjpd1u$-J+YK-iHPuDVxFsq4OoB%f*?C)>SOkl|)Tl3K=ixB^WL^X*8-*5eL@=R<+1s#0nGAng18 zrwig08*;P_$912GcfFNy`EPX+iK({YX2Ssh4|Lhia zLA7x}t%KP+K4#( z@o_=a>WX3U-0o7+XuAMu$M`pC6woMt#mXfM z-@bpq+KF&Q4|UANQr8;DM$sTGN%2otdADy3)7Tiq)vv*wmwojx{&-kCrNXixOgLW@ zF#P*&JHUFH6CfH$4~PPH)%*FyIY&6=n`pvB%axV|9A)k}E;4>j724q`=`yVKf*G=S zU?58MbqX-}Gq%BA2z*Sa8iIhP5-;KvgMgs`1k?pp9+9lBt^!X~lb?FVUFAQk$%rX* zu$1Pu@f{K#aztgiNQ0;aOV!8jC<=uqPrlHdh?w!Y`plp7_U`+&vH6j=;;`4eojf=n zbixD=@4w9&$M(hMv;DxO>>3|WtjcZU8_i8_OO0!jR&-tUk2Cu!MQ-uUZde358-BH1 zA~4gvNBb7irvf4SsS-ub`WWLJct9X@irqC9>dr()_$-8J7`;9x)`Tw#J3AP$m^^F- z9*chGL2Uv*WD2fA_nld=yKptM#|vGKeUdXHzN?M@QCDV|#FOqS0W}z5M+J!^cem>weWxUq0JM&q$nZ$t;aAvP&x#(&;Db3QV5`l7XlPSSM;sBgTY1)!4ZB}i~T>wSNk^)$EDs?>l)c1ebj40PSA$!>svF(-|=bv z;8rlr-5y~FMIL=;F}aE`?sSgX1X1~CFl`4N?~Db`S#E1fLn$-uZx&ls4{O$PlR(U#xy$)fP!ei<>K zmgsf>%8)krsNK98AU-?C!T z@jk(1rCE!W;2)e(q#Sy{{P7*}8ifE*Nd&!n$cd>CzoJWfLtkfH)g}l+p!Jk{Ea-@9 zT|fIIH|LrYdOvxye+PFB*Q-BfzQCwyFmW#F={Q`IOUtVy!ov`Lle`cM7>2yE!SC91 zx(0!R4xeV~ZL-X_4PU6!?&ZzU!-gp(93O2#AS-HA#lT`Lhixh9-xZ@t%GIlAlwSS` z3of}b)#+aTOu0_+87KZ=XYQ&!2*t2AZx47!0^ehZ(7 zfAm+yyzS9sz(#z|5f`VxP9Bd$InmpmCLS(uwu87G_bArKf3l(^c0QJ*rA{1Ap1$~7 zu=8P(M6c6Zs<-ny9BXaOjLb+u)Gs7P^ge!dRg(+Ba`sFG2OpmpAS)C2D%!kadnE_( zv0s(I$^zKSg#2$&|Do8kvmC%CpT?`(*nxIlM8w)$<_#Q$D4tx*qA8U!IxPPC zzJ0D8q@wxj*YG7ZyqZgb^s_M$uHb*QKc5SQY?IhRoorw+r3XP4vr->7xexYP8=IWZ zK{Ig%%oMNnBlN?}74O>JW-M8PQNH6>H$YNaEc8EFqiMmO+c(3w*#4j^sn6K#bfxQew!)s{RoK%J%3&PL#1>T zL8uB1yZh}TC9b8=d;8JjqAq();RlJ6v?$3$Smqv6U)F9mR`*Wmhh3t_9Z{6(c}|gi zB7QB*g~`22kU3sebMDPF;r4DS54_~*JhCM*U!(BkS&}D7OX8UQNx7z8%gSkTrwM!B z^GvK6%?sY>;Y%{zgKU7M-%FZzxxSO&p}uOu@D|%dsWigveDJqgmzldA&#z?5l3GhE z5gb?!aks$%L9@77t^zrm`<4o`Jd!jfWp@D_IA(-*)+^Z7`jZF=N9~epn04`5dBLaO z_+#4Hr*G}3iyeSZ2ur|EdyMX$7O|@DfP?-9!*QLb5(UKD@KE8hS2vtfxwyN^7X<9i zIN_r6K@jne3LN>bzFFbX>JefK!D_L3xb%XSP15OwW5e79k_N z|NlsBKl(YC5qIgc9KU-2)IP|2nfAY#-*|&?oJWFvb&*MMUt7Z=AHswYKEr37xgkgK z`5#;V2;4hEZhiRQ)U7Kw)tW|)5*NI^gFD|{7&O|C73!xup6+VkNOF>GJ6)Oj`LMGh zdk1?RDsS&ED9MaP;j_4VmgE(rXTE<#d^qnE zPXACIh~_yqL-6}ecpd>(@9)EFb66wny|luw;RQkWG7b7~X{TNNmr+AL6EO)p zc^oDKimbic(TPVB7vw;(jc1wZSOP;6HvC?`yYkpd2rzd?4ic_vV4K^Vc&{B zk`THVkTV;`N*18$Z7HSUWjkjme61TEXl`1oVoW)=hz5={gHDn4%_s8)t#rBB7&Y=8{X)gH7Cx*W_`sb&Mnp#tu&Y zx8rQhh@pmtI#!d|=p_3%-$!|Y!a< z$1qW&lJ&QTb0!SLF@zaW#}2oveWql%pk)u$VzzVWL-n1`6(0V#0nbV)UYu{ykdje^ zH@CdozjBpG7{|5aLI@ot#2ErP$)xNO=J`Dm9kvgBYY;nPZe9T@Rp@GJ5F=XGPG%a> zQdDw7UAZfi)afMELoX~t4m^U64w0h=!99<^*)9%$qW};LDuu9T&@cvt2~UnF(}yd! z4)eB+-exMFGK6am(U^|0+6{Ac(6`T<=)3vfLNyqHn1hCiU*&vqHBffRK5f_q`0#fD zw4}C(ve7PEIK8kSid;q4e$z*{^k0&&EwG*2Zy!i@R0tE5!+v^%9F5Yi@15(w86@X` z;Ps^Zit|OR;uouJu+pWoSqBn~jO36&>!UP4D1y#<^vtsT*rpnBtYn5<86UsEuOg{< zr3`TNF4)lL70#gBBXFVCVC&{cQ)_)ylri+1+Lk3`c=Q5^JUiD!h#WyQqG6zO_}JTk zTn7tWb;bzeyi~l-u}Nu1kVw%Ih$!~vMB#BUbQI`T&%c?F#Jc3P+gt5Yw|ka)!&Ak9 z%z+vCxEyX9J1ix{Zi_-FS_zIKDzsdy*Gt7sz}cZsWlOyPPR&O;o42_6sd;6EpdTL3 zT$>5jN#L!-ZklDLF#$YSQU+@TOSs{f@0TDBC?gx2&HFo$?35k>ET$*q;@tu$gK|Dy zo(TukqwQ@Cg-yZD8ZKWh=bkqqO`a6fAu_1XS!Z~nc%g%9mdj?$ zN&!MV$ZLrWs^HBr_;uN~zPkJy2 z7JfA{gsK33KWrmI`MhfqIqshR?}@)hK+vjPRkz;!gYLOKwJTJN#%Z3=LMZJ8eTDTU zi)@_F<;lw7E&Wi}9S(aip@Um9^*QeNQOVArC#r_FQt;>lF|BEA5}h6l_}uJ;C710Y zDzlS~7;&^+lU8htD5NB2)i->w>GjryZO?$3lAxcZGhKJ8AQmVfg~LuFL%_8|lm z%rVOxtnMzt2-o~%e;cY`<>s?jF?y$^7-rV>v7EKXsXRZzK05IjSAQgy@1++_)X7R? zUUEku+ZV?9x|xaS$}Ba1du}Qj3M=%`=}1Ov@K^&8mdIlBV{Y2+g+Omu$qV3Z&yj90=Pg599?Pb`57 z#0kv3gMTPB{wwf(g!Rah>~NWEjy43f4T4##NKMj-f$+(Vp{R9&?gRWe-m?|q^ZRz* z)S}Ra&34T1Myjf2VWoBv$_W^(-ok3P5~HH03nZOBj-V7e34vear9ZdG@^u*2-7V#9 z*744WDnEow|JKLPp3m3}{azQI!v39y|NZ##{%`EMD*y!r6fYNV_qA`A zWgADvn@1dmH>LRwSHr^B${eJFVGZ79SJm$~SpCF1_g?i1?vVd>H8b8RAc$`8GLPoI z5zlyuU5EgSjsGNWPER^E0*M zl*jlMCL-*S3WUrlo?@2#N9^{!qt?Ar)~h0_ks>U!wzM>b3^&h=-umaw!31+EC1z`PbGL-$q7 zY7TOBhG?)Uq#TkrS+{Oer^jj)XUFrSA_}dVCf6G;Ch+TSJyfg-h)neWi4Om49Hz`x zRK0iFyP4dj@=ZVI&=6bm6mRAudfj1=>Vcl6<=Vc(dA9~vDzW5z~tJ1Uv&cNFzD_lM| zzcoE>pZRlvRFrs#U(`R#&(3|wPJ~LGfE#V=W*uPV_95Xvi)c^^dwjO^Lw-^-?poX0 zJz4-7Cx(GswX|_Mw+=Fmf9<0RfETS!J2~4r3m(V@&2U2eTfx9yBbmXzcm;sNmAlw^ zZ;$C7FPF}MsBHqtn{Q=A#>HJBUkcScD>11_jU2Cg*%0 zB%H&R{nFS(9mX!j$7DtE&VrP|7!)~F7AIxA8euFH>e^iyh;wC5m>$(tl*?$^`-x~r z>0bD2p^}W)Smh?=?Su`Mw2YaWnjMVnC~3rANN<#{mc<}DY)L*K#7Bu|b8_VsI9!AE z9H0fR=oRe1w9TL(+q%Ce93CD9)>z~c+?v{&^Fd8RpdRcV7`#4#fJMn>!8)U`*Nk%r zOXO-ZL`+7OEZZ5Tmwt++L=YjhD53wSp_l^Fn(?u5)!KkpNsJ_Va(khx+(p7mQblqPVar4D#ewwZ~YisFvYF(>J zoPg6Pj6C-Z%R=Of&j-_au%Kd@)PaHJ-ezq0EYcF&`NCZXn>6wI z6WH@FC}mr&So|?1y@iG0;5wh1ey#vX_v(w1cSR~cN?Ii`$0X|eq= zVe`IrehLG}DP@lv9t+>dMa~C*d=<7M48(y)MYUkPN!g}8t-J|HPh=No<{+nX!!b5d zAMaQ@rpO!BNh!w10XRGkdQ~UCE;TC6wAi#a@O3B= zFC7L!0Pn%Ae6L~_s8z;kThLMk77FjSKBM(zsq01AAhVOcij?!RFzwd5{BnEAYctk) zip$3ehOFJER=k7Wn0^P_WgT@x^7=Q}fW8jjvO4%Dx}>0G(PqXcT_)HP)EF=+EJKy; zEH}E0HVBS(mCXiah1>Fb(6xH*_;&rk^%ks6Zbw|A&b* z%U40-u&_SqKqMV;MvGI;i-@>NdM9d-KWwIG#}($srrRvrbfHnx8Q{;7E<| zVEoFnqFm_gFi#?2gy7>mMJdkY8=*7u(P1!kEvXmH+*-9ZYspOl2$#F4zshq-^cAz# z=xADDH=U_q@z$JmRnmw(De5$aVl5gqYblgRAxaIXzt`~@5DaZylw?KSK}Iex)!fS( z2qdYcrJvswz}MCORV2ZFQ{BdAfMBN@3T=JWmOD&POpTL zJ}#DUemY)1*}*mO3LwPMZqmtW{RBhF_VWB0O$N}_&nNK}@AAulcgBw=+z^;GxkGdDpYvr>rhzHYU~;+GL* z2&0TB#OcEk;)HvHR({0?xeU6hKQkTbbo6RW6mA3o7@7D&a8K{d-!x}WVi@y31|rip z5G|L!?;W>@U2_XBE&r)gQ>RnSL9CuJY4OhQgIFt~l^_DbQOFt{GSL`%=@gR90vUbI zjw#{Ak2gEDw;3~ro-WWH0q9ZFCF*EQN0(OKyGBEuMV(~?ytT(XW+wlG|AyXP)_=}>yy)OyaLNxKajah} zTEHho!-=dY36QQ_*`ySvT}$lZ8$dKUx=yVR!^x5he#Rf#kaP`8T{LSVA3TnOfg^i? zQ!}#76&p9<(-sA~KbVDEtWMa=MrQGsvuVSudGHjD9`%LnKV(e4e^)5Wm@I8=(>4NV zuQnaipE^K0v#IA5`i)&|JvYO+sR`;J;=C1XNx)jO#cGsn6^m!45oiaYnbNbtz$o5gKe{f|b6PT@rmro#Td;gx$Rkf&zWw|ua z>zVLs33Yq+UD3CREycj2ad)kCz3t02!KySSzz02t%a=9j$em{j`Dfk1amFEe7&IdoZDn0*-ZJv z8)1)fuuRRsXww|I9E&0`qh?nIxf3IA20%WVNIn}N$bm`s{5_>|XyEy!wg-vOpN5-M zk3HhZCaDo%z?}RHxZ7X=@xB5uDxZ5q3$`U zH^k<~4$J{PMZi%VbGulDwn1O^WnU-A38(+_e~E=HOh_eB=%A=qHBPqrp)b2h<4_H& z@O}UFt!%zR1c8i|jAhMR;!zvaC)$IfnIq|*b3P@kXpA0k)*iaxBVvjiYUF?$mZ%Tp z9X04|3A&ZXi6IP%#RzE1MI(i@Hf}A$JO05Pf2|oZLhhax1 zDON>Qazkes|5T@{BK9GeY);ZDjfogPut^&}-ekBCbcbBxqpPaQX!(vkZ(5g;0!qT{ z9YUuP{41}I@xLYsU0z(Vbny(N){&)@K=dUcbaXYR=0}c0l{TuA&jmav8_ldvE`o?! z7zrO}dojjc14gKaaHw+n*5v*lis-t{ofk{7?7gdRo{{WmUT0+5|MY>&!9nm97JJHWd4l zZ;O-LCArbQtjoc@m&G)usO~dk@T!hfJBkXA5Sut@tlm+^1K!1>q)qiN5Zjp(x+TdR z(f86mJ56uhV$!sRQNdpww75Rl?PSKJgEtW*8a@N{L$uy1@098+^#6^AELeu|QtI7ooqMSQAE2@ju;lNn_zHjsBpvs$2YdQgsq#rXcWXwQ zE9u|_25Uu(fyH@r*fmTegGA#i)`#6C452+A>H1B*c17YoqGJBSM zlFDp()=6Wn2!zuKKUIhR!I}FdNjKH|Pk}TGDtaL82*>!jW+S9a5n4_Q|Kr3CsFXa9 zyR4ce?l{3e`i(51Z8BlhUC*qXN;hOGu%#V){~Gkm-^!Rd5wp|XX2B;H&Xi+UI|Ho# zama=>zncYEzyRg5s!0nN>~<}r?^~sRA&{6dsOhEHugXvHpCue|jm!-P`26u&w9E}9 zLNt(S7yV25zCCPl{qARj7-|r*xM<(&Wu$oj2S>}DD!fgva}SGQ15V>M69w0=fAfVD zdL-|LGu;+OR||M)hj+gn34IQP6vaxfru7+R^{}BLf)%tj{$hq>Uf#(6y*n2=d++47 zpCmRZZMk;fGGyaoO_4U(j1RQ9DyYQ|6(sT17wpzTD+dF1!8Iqs!93V{pN=o}? z`TR~wNSKEHa{D$uGkxdpCZWT+wpkR|v_y$8wt|^GCx#<$8o2LfS~*94-$hRW#!5|1%|$yN zr77iz!TJFop5gv^RZ;NkIe{vYu!s6N92BdZUVh7T85;Rj^u&#Wi{zgQ-ZqmU= z3=SWl?pJmCZn28$8^}=x@xY5=d*3q7QT@U3TQw{* z%mZ#bOm#{3YS|7EIKTdp@lEOl#9$uo`rXneB74&yl-+9X+8mP*HzH};%K~yJ_d5Gg@CFhFp+ zdRErq7vo)TJJfw~$z4q%Zzt%fOcb@`)s> z_Be4};yXR&ditGhNrB&D@F==k-y;4}-}w;P-Bi^fk|qMyI`GgB4KmruZn7O)m55g2 zwpYiM#N(E1H1SPc_~g>x6?GyC^2Pq3>e5nb1rAu%Zgd!3O!bPCyWKXphW=;`2pA#l z6wZMw7m-YfOk9ESg*`dk#3)5OG2A|SAU0(oW1|f_%^z1LK`_#I^%+jvCB$WL5{=HK z)h~N~$|}79F$PfM?VRmbPV1jcD% zi3pzI`;O{Z?&q^LBoGK99yo8E$2oJ7z!W{4Z`p)xC*#O{kgFBI& z>%to)FZBWK#I=S$Af;LxHn&{=8g}E=^Tk}R*Yib}@P0qRDKrV@H+bs3K4Vo$y&Y13 zeM{xfE2=rO)CaG*S%03MHr z%jmq9wduD-ahXhjY!xOYv6 z8cCys#XhA7QkYZuGJp)zthu{SKft^eB*$PZA!4k4G$Kss()6EV1$&IV9^az5`B1Yw zQF*eu?X1$%!LQx_B0JkaASDG~FHIy|$g3iNX!BsBJ$h{{1vq<)w;xlqZJ9Il z_`;V@-AyE<*CITuz?1#%rcmWSbpE-v7i8RNeSg?3In=Q8qo}f_xT7lAT^bn61SG9R zL4%op(r(F|v?7J(R4V+4$Vt>$!WogazU-@6DC6ep+e7k-?7qP_+0^M^)!BFHm^Kug zH`&h9QW46@+jvO)yxnqTJpMcgUxz$jP8f&mbSeIc$zieaWxJ`x4pTTZM}%1-x)2B+ zlGNqZ;u1Gp`_J+_{?QsScw$~>zRT1^glT+^>t`aC@NY+Z67gVAhlBWBD0v!tT^t5S z@xH4ZQWC9@^u>Az12XxrzH$NFR8 z9x`Vu>6f02R0+>sr(_hcM0X>q2=6ZGUr|qG?1>aE>G~@IFxz*F9q~g8r*=ZZB&}rj zl>;k&uxH9y+1WMw=ydJQ%;{n@COyan=)#t8M+J$UMPU&IxSM^^q`TcR@cga6VJhxb zmF^*GRHi*xN1=$=^AMncY_2V89a_)*Lz1pE85j(IwW^`52CVEIKyVeF7IXR!cNXXo zoy-borVgN;b?j*uunRwwV^|r;5T&TY%wr#AyW&?^<+F%V$>$(|*zD4P6t7=POGN9P zp27c8ClBWTS%o+NC7C^EN-0f(=k#8YkwLu|mzc(ld$6}UIT=UD@0m~$;uSP%7L=T< zO6u}dvzCwPmwf6*@z<8t_bZy)(bGU) zr^*3?-^JvdZg=WkJUSE`TA;gZWF)F`)g%Kx45$jjt%i#e96L#w<5WZE5KpPcD$0x+ z2&LGtFFv?ch?C8B0(ab0A^Yjq*w>V>$n4^*8_5l8A)u&W8(XW(HUq}IrRXNV3Bp_$ zl4^UDCW=4xUXIm3L*mF0j2WdxUrp0ih|A|vcF9Q%Q}0Y>D~_6OJC6R%u2KlM=sI;a zYpGgR&3u=r4V8EA`wf1!=a1J-$<~XsRD*&DIMml* zbKj~b%JmjQJb(^Kd~u0j;O29Jbfh)A(@>3fK9O@(EnHaNH_je3Z z_~bp7T^tZ|01al333euyk>FgZTu|O$sIqYs91vwH0nay&@DofISdt^v6;DfVh4Ay} z%#*g{E!=#vHJU9KrZF;~uKMu{1VLRWC`)U%#lCXVX+Qqg1? zjm-k_wReNP4W0H@ek9o*c)TE6bJdbr0P4I)?Gr2SHL8j(37)gjPA>gT>y zDYhSwuD*|}n=Z)Rb{paG^HlK53nb-Rl)q4*Iwja$S^Gq3tpbk*(_)pYPRrD!it9zh zVnZ^S?D0l0`uWhG_Dap=KaKK`0`1-s9VQG>-p;U&!iZ&gCTFh^;WH)Ll77kF*(<{4rDm{Va7Z?%`%8O zE0AL(T|5+T33aS}9(MQMUibX(C@@fc!d;|+pSOtriPVsn`LnlKinnq98+*S;1T5H% zggt+mZ?6jBONWk!a zO$)1*L9Kk6*N3*fUKBmskG$SM%6rIuEpwn|uO`} z2yAMzr~Jqe)k#s0wLKd+qh>!iI#|lnzr_Aa%xuFF)Y+?pnlu2;3oSr%HEPo{X;{Cn zBhayKv_+}jy=Ekel`~e#=%saX*7uS!>zkma%X9fSl%H_!e3q$4`x860pE0BUm!o^pobHi|GYK~uA>b<4st^?QD0w8KY6B(3Pt4`T;1Se#zo^zoP(co4ssH6 z>KQmHBo}`-Q7qipg?nk5?zw?BwYvZoe5~TLF)}39*633J{GbsFz40}BRpelAL-)>Z zW0md&yBOhcHHmASN%^0(=#yGdb9}q?Im8e@g2To zUyDUhWd%fE2Q9E&>Hxu2>sk^r*s>ER!~VwoCz5yQ2RHv*e`o+s@+&8Rs_)?J9D8-e z)#-VK_s=0r{}$WDd-T)n%UnO?E`m??RC`74&gCv)AVGMZD=SYlwif{=NmM0-HX*@p z3?vTzFFtAD0FJO56LW*XA+6hbqsjhvwKo&jH1^i1SKZ*GFg2&5hWg#fO0of;>*c_o z%C@$)r9BH^4IkYe=Ii16XIlb}_}(otMC{WyPH{1g%3aD|{L!_THSS+F-hBD?MrIb0 z5#lus{X^5)3{1TH^LJjz`|aX?JHb&FY@7faW9xpMP5QZ%sE#V)+Q0B>&uheQCP(J8Y24%VXD z^6l$EAvf~S$Yjpjj>iek4EOkhvuO%OuC+CZNal2i;{T#FqzUhK)!1in^eFiw=-Qr;_BRn#s1mgh|k|uu__Q zT2^bE4x>@f(=LR&d`8rq3kX;gx~sgyhQy1j*5f8q2mUcJ*=D0)pz3vw|M$TGxTAt9 zh>1O12{T@9vo8rrH-!1PrfQgma*3cY@aA@RDG=m^3M)pzaScmU79RN54>=S@yRSC4 z^ZaA1X1>D0tQT8-JzDTzPdV5Yns9D*$)0X>9Tj?{Ab6$0)ag_}-^5CfAwH^hfqD%^>A7tC@ zDINCu_^-Nl<=&;)erMW+Z0x%otrEQsh@yHKd_vK)hf`s|{FrnHnZL$uSS3`YrW7}! z%%4bSzNDf`yt7%ma}ZKRq?qn3)v#o+U3nGt(_dGfF^p+{fAD+*xeNVXK&42QIM7kX zjB@Duo5O!HVU7?79!Y`-JU2trj5dD2l5IVEAJ-|;#E*M{DcwzIW~+eobEC+8hq2-e zA9#Rk0pP;U^}F=+^!xR@?r^s5dvM;{Wjau>&UXGhDBJmbNW8$SdmK*Qk2yno$^4!4 z(}oyw1mj=d5lirYT}od0P~UGKjd$|v!$p^z@&v9{=IE4jg;Xc6f)tNr@+n|0fi~E- zyg-vIU1lUHj2Jx6^pg2UV%Ho+$X{2!%XT_)^Ff+gQ>DaxUNhSxfkqZjaWcXQdeBme zB|0J>r1bL@hm#qo;aS#K_BFvqHkuz_YC!M(30?z6k&w!TXoX>t4^vxYePNk6qQg2B z;)Xk@P~T8XW5(vhV=k*AJS<`SXMoEo+WdJ2M_yui^n2^Rr!ycV^*W~JG~xixG}k`; zj832aGdV-%N<`1X5j5~SMB3#;zQ?EZlO;drMwCIh3SO=k$Bq%wI>}#wyjSv zVSpcnXC4Ul+pf}ozqjCFOrapiN_2bPJMTQxCFj-dfv13Hxu{>$LgNOi4rtoy!b0q%P3qo3Fv>#i#Q{I?(C z&fa9@+F2;`S$-!hhNNBaWdoa+au4E2w={);o&|Kk3xBu zqBF`aJN}+j!B{9L7a!fk{IcXRR3321`LO$FPnypbXOO@5Oe&I-^nAxu(gkZBOUl4431Mv4`}aN#TCct^Loa!-<0o0M^P!>D=<^QhR0eFM|>)? zC1J+T`4As&obO;@3?z|C%r_rrR*TQ8{5aAO2f@D!K~=%@M5W7_{P3t=$MBH;Tw9Gd zlrg4MJa}s)_K7V3E(EkUn(yl76LNFt?eV;iWzgvnSli~=9wGzmmR12Sq@%0Kh|XG*H9?fwPi zWYUp~c!g{{tZfW7lqp{9AbIW!LWBoRej4p|om0c+${6)ZCijQE&p)Ga6GTQ^zw<_S zl*#=Y2HAYrGc0DjXE zqLHWHGk5%}C7?%a*o=%?kF!Nt`BFMKligUGPZVa&qq&6HG{K!ASs~+8FWf_AR6^l4 z`&goK5m?5QKWgFZz4Q7l-YW^3I)DZ+b=h9Io`V+HkC1*C7x|4-xekJ$th!b4ae$LJ zYFLqcTd?PetWiFiEl*^)L&P6}!v7g--T%!OFfN{LjuWt9KEg!X0reQp*?BozK$KS* z{je5Wx@8uWaPUVr5HxMqbo7;H$0G`>{eY8!)lfn$Rh`Ow;}%F>*jiA z2M<~s6ek<#t8r5Y{#|z(6K1(A-r?L{h91f_makew|EU^FJ9zy-00rI=9$WQi3exT# zeOMVpm6qXzLYWBOw{+`DLw8w%fy%uY}0QL zZ&@+!*#JZwpp~`g2><>RXkQ&4m-4v0NAi1+1>d|}J^*#Ge*m+BHzh6KXFkYdYQjVY z(z~hCcFqF6HHyXGUVgDHXD9^H3RG@$Bp_^`G3(?;ZON&Nw@1N9zjbrZsmQMj(MO+m#-&e7uE>ix3>3Jg9BCB!06bd zfv>1U#hyp-Eis{GSR%6g+Yn`)mOIQC?O8%eX74_)?89^g%e+xzP?WL1WAj zo;_9N13K3400?N%7#Odk_aR(QVyxcF}-W7Nx`2QcnJf#cC*yMBe5|6+8=Cg|z*X)JCt+9h|FGofn>>BCgo0H!TFs>4*lkpSFP;@1jv+Xahwh6;x+-)@4i z$ir9t>-4-@wJy8%P90VzH0q{5-nn@KvN$8id+pi$;ub7>vA84Ow7%Q<`^AsnnRjnL zj(NL5Cd(e1;jWj6_!jb9$Bwp8H<+2Ll0SanQhB+0_WlzoEjBywSu_C??74R|YW>%4 z!?b0k-?NsSK7E`n7`}7PQ6@50(yUlQ=7WgB7#WguDy7mmg6qqX&EW$VJq7=soTZV< zUknbD4UE?Awmu+M!qN5r5Ovm3QH5RGpP{>z9zqb1M!HK$0SO7|6iMkJ2TAD;=>`P` zq@=sM1O(|GaOjTr_TzwtHi zavA#S&e?_!R3}ein?#H}XW(YP@nw`ghKANlJ&qJT_?)naL}za=Iz$RE6aj@}VcO=W zuiHPYqnl9)tRyM-j)$4g+7O^*19^y7XVdEc0-Ax)E6FaF9N*x71MvNQoO^%F!cxs@ zFFR2Y$*zK76#yjifz^ryg8+osBC%m%`NzBjwzBUKPnzmqtz3Hj({H<<;|OI?pP9kz z#6__eyhs5>B(@9|*V&(HhFDOKfi0wn`sD{OIrnh4H5 zKYdKxCVKBE-uxX6)tFA%3U8&jKXTjTA3=Q9rY}nH_E?r7J;Kj0n0IJ=-&48JAt$O7$tw`31*H z-B8f^UE$uXcblvtQn};JyFNDdZ1pnxadCfg839SI5P7js(rcR1=L4LaKO8ncDqm{d z&0KI&-zj%|)FuiO7_s6pyQh64DZ(w|xa-54&`>vIhp982;s7(K_h&`CKPhv0{C@4N zzOe`LB3$vpX!y|}dff30a-H_H6H!^@00$XEv-c)~o2QNv#@M29vVOm%LcQ)oBzAFW zW-I8&Rf6G5h_8rE}6R*_O+Sei?lQwg%|O z&>g7b%MM4Z-LQkK-q1SFF=7q%uB{hw@VE3i=;4Ac6Cr_ZKc1@u$UBrAKYx)p6Xi!c zrMH8s>I3yi~K4~`vs+ugi=hFz!;b@D82bVtVWrL zQ%}r#cNRF;6KAhPeTbWoZhe-~hL+oep`SRjA!c7?t&ixq$4)L1Z&xxMEOdi6{t#!j zgWq_nXg){1j^bb>B-`LdlxNLVW_m)#Mx@xon3BQC4=sMn3{aCzr^aB{81XF>oCKX% z<8rL0$k+l!)>+Y%$Lz(1rpEU*gJUHp`@!P*_uY@WH)wu~gI>2k(Amb{npAwbppQz? z9sEM6nhd_eoKnNYY2mnMxTQ$x=9uS$D=?Z+KywHUYTJ6v8#@5o5*If&kUAHdnD~q%Rb|WK7gwt0 z3qtWij=gY!mCm`{1+CMwmKYnp2gA&!z5W=i7hZMH~N zyxeY|3vFYNbF-3fXo$rvA7Of9N&=;%)!0Cv{MV zH)i-Lu57!7W46gn>vj0m_&UC^HIBQ#O>lh4^!P%{VORW0Vsg0U&wkWY9;i)plqzZ( zUOX1&IPy0Oz8#=D@MlqoBCN=E>o=m%BqyxR_7&pl;ZR8^ZqO@HHeUa{$4)CCE+If{%WGv}br0Bg|Rn$3uJ*f`@fL}a&c>yAVB(pX%F7QHSg3(i7d`~!8Qo@dw6p+5gqL>u?sV*PIv>xM z?Mkm6Kvn?X{LQR|M4^9M(QqM>xMqo5@GE5P!S3iVR@IbU!L;`XeYCHiNBW?gA6@`8 zkzwMuN2DYZUSP-5!f?7c5@AcV$ofIEaB2mHaalzwE(KW%Wvucf5-Q{*HV?EB5Dj7f zD}g}v@9IJg5C_8~y%HfeUyK$^1Xym_flwrytE-LJqfQ^>Mh!r^8U_}ez|RehOw1bo zXr=+z(VL5bg_JPBnBm78^95oI#>U2~j4QrK)zQ2lCqT@S?39!MyWTGEy5LKQ92P+B z24dm5+E%(nVuAbmbQsrAvaP3pCD!>9H1PBkw>(8furl~FJdB4(cpSxw1YCH^!pfuV zA4WvvjdF(HZQ4bZ96E7_FR)$61Zt9z;a#Q}Z$14O{KKv2)FiqmnRr43WLcWPhgBNa zYSU>o;Uj2B$&-VA^5=)~v~M(4HQH+B9H5{wUOiYxDFOa6z!wD^0z4Kum;H8VeXrKS zfbp&RF+hJ_1+KPx^c>$8<=6K*lq<+f7~Bra&2}de=9(xF_v9ojtEA3Qlexy@>FLyF zMj*p<`>8wW*h?#VrB3WZal5$ac=4Ka7uzF}I6mZyK$-N|r?7&rPC78jPp4*qo@mx~ z6f^xRYAr!tMU;8e{i}j}vO?((nV7;RU^H)n8Ut#^I<>MJiR$m`$yFc14lxBXn^nhA zE~tcQF8tM9jXJryJb%9?6d+3Dj*aJ30AJlnO6Y#xr2j#~SK8OimjoAA>6plsZsa+m zxIq2vb+;+NRk|~-H)(-E#Rd~t@PA>ufb#ZbT3?yaY^6il{UAdxNr%GPB<97yoQ?k$ zw%3yW_zW$$I^*3{0;N%EXQHwvk6S$7mD&z^gWXIv6QlzLmC6DmY``zRKubi5MEOVJ z$_X)aLJ~ex(vfHjecLOv((#enJa(cxKZ6CV`}l$OSqf0|-xPA6_r zuD26jKP|QFkKg&8eixz|?(oZ(3QG}+9SXboU^H?kn(lk$IU+3uK7I1=G1`z5sR#sg zi@ptHKOvUPzb0GQ@>7zq9?7w%SV5uhIe{4sgXF?a;09X%@_LoBwur#t{P^H=!-x6F zq2=Gwxe~|;{=P)N#asuP-+cfrQ8$Hsi+7;G;r&%TFwprxee;xCE3%iQo9G|18Q%6l zW#WHL(tfv&E_r_^V(fp9)9fEBiN}<|^m#{QE;o<`o)^=_LHNZmN06)I84pYyMt`rv>_OZomx76S4Z&Qm{^%%wVWV-(^kA;V-cumb`uDEs3#&VVPXTykq8%f z$0Cy4Sk{J?RxGl}4{?}2>0EN$-1~XlbIYNj{i~nobZzC{Kejb^>Io?4d_I$@tFuQ~ z=ZsfscxpG}iUNEkDgtUXG;cIC1-kL-T{nD}v9&*!%h$s>_XjMGJGaQkJC>SW@&C4g z70U32@4kvFLubz+SAUgHKmSE+X%+H6HKdyoO7x!w`F-S<|X#A}nl+HDf^9fBg%iZ_a4W(1q0XcyxLZeDsDb_zZs1CRQ%B4N|-D zDgL~oCQY|WfWlP#1t%ik+7WHL;=5~f_2vg5_#0|(0FI!w8rZz)w57*8?O zfis4!rRB$kD;J9P@7Ki-U*mmDJf#YT&MYOq5lIj-ke$YgKRsN{WN&#xl1m?UK_;Dp zE*Cyo@0dKaSl5}4^HvwG?qW11HZxa8vt^e|oSb|h7e0S3;VAfi$zG7=!6y=Ew zzT2UkwtAoAGy_+T!8_%HvhF@s-~hySjii#oPY~Tz!Cao)H;X=LnD~c0%q={ z!u3kfgGxg~Zi|+dmMs^V*1b`gE>wq-V4U!2P9*G~h{^AUOg&qocf%(3lLz#5_G(OQ zm85Zjo!D;+1%l&VSRG)mLfD;jyjWul^Ji^A;{Vdh0-v#g!sMjGx`Jfn&AnCZH|<0U ztGzI^j*@-NL7EtUy@hYG_^NtIQsiv$_)>n^Q@E_xg@AtG_*O%fO@HB{8nS|96|YUh zU(zom5ou0%XJ%%v9#5ADxBu)oJ|=!T%-rI1bh4%5d$jCx)f?8{QIg~PdB?;z5Dsvn zZ~s8DoSc2#f`=n<#mxzQ0f{<(=Kd=*>Gb)Rp_QIor*M~SY|r6y_?Ec9-K;BdV>@RR z7qzU_tvQTQG(}`)Z+>EEr7!3`#AidFqlZ_Tx0f+M;1?e=nR}}DQ$)yuz;_w410^^= z$BW!?q0O@KMm+OGn{;lh*j&gsi~~tYG?0DMvc_T&Br>Z)q@6NSmNP1f#JleePYOPu zOw*gLf$5>UQHMW}4j__hb-FuT(mXT5Xyw3}idQdb6$suuH>I$-$>*6@ZVkpf4+`Cf z%;)~TJoB_%&P-d)^cYI>w3PmUZ~8()35WYf2PJ+(->pjpbx>l+!#wTf4JzdXZL)Eaoa76#D8Xff%+RbkK~=4%D?Xh4cT>6dLj8ItKrm7@VBUdC)fXlA!to zKHLCI@9PtG@y8Q(-{W;V!xejqxGp<1aoD@o{HbL-m>gj&L@h6!Kyf{A{EUGn;Z%H^ zZ)GdF#g%o}xiEG0SgninK5eJMk<`S^1L%GO4$<9QSOt}Hjmu%dKhtjL8l8KU`% zd&1SK^~VxJKj8woS?dbz8@sjU`kYTfx$ucp%j?yNKidv>gY_@zeA_Z|zFfUA+Q9jP z5eJP(V%+kIZ`>ywrobLp?qpAYEt`d7GI+v_XOx@Zpz^>w%k5e*D%~m8Y{3;a=yH0l zXPm{V2+bIHH*jLg`JMSG!8z15O`b57KJ1~+hknn5E16IfOT$qn8=)TaZ+X;fUMBi- zjq_Z%bI9locKP>nd##Q2tmCGBAIsyG5});yeEV7lh2^U(8m3QfKSQB%ruW4V!(}Ad zfDjpEK?^M3F4nl;Ok;AJMU)4UlsId#yk{MbBjM~3X?c7Qle*sUetdYHZ;UxH^Bey(n#t=#2WheYII;K~{t}^#s zDXMkb2U@fa>r>j)4ZX;}^DhiiOK?77D-FF4U8d0UY^D`FC~_KRum@h5N4=up6^Ijz z4#gOXkUp7d_;Br`ACf>O7xSWA>zva~d@?{M_6f#}@GiEYL`d^W!OEo~Tbbq&m%5)j zbi$?o^6+xz7K+z@x&`d;miGBfQlIY((c}{Lt?GNf5a!T-b$Z}eQBpMhZMpY-!+6Ge zbkeOr;Gw3AkW~|O`kW_htSG?+i*D`vtBOAON{ags25)#LM$ufA=?7?k?jqT5?}_gkPRUF4M+j-TiN)h4DF31zgmyv#xnf5n74u??uJod%9DPjq3t=tnlOw!#w^WE`T z>HW8S8@5t{h3IfTvYqiCVA>0b*$ch5uN0bpS*5<)OEuj?x-wyNgSb2pv7;bklE9-3 zpXP@Q&*Hq9?h-*6KD&pQQLviq1z-pnc)K}^I?ZY%Ym}46;A?d?l!H}1sL1Jl?+?lC zlhA8QaUnY+C*!9##S$jcYkdY9U$_>@z8`xD82C&ZjTwSrx&U@z0SL|cR&L* zNT@XwiA6*9ohUMdfuC2373|8$jpg<2s5aH5)JP>DWt^#~#&UNQ<))l>&dd7ymBJ?@ zX84yUuR0l-DQdCKi_JW#CEPSZmpS`8MM@aljgn*WbM#`ey0K(J>~pzqThG+&qU%L5 zGbuAH!DaP1s(y`%_%(}`gq$AYDsi}|v02!|?>IJ+4f8rcl!#zqJc=H~vSX}&yN#*) zc(zQz=MzICr|Wp-rh*F$^!>gL`q$^qxLf4wA?jdHXS7vn6b$flc6C1Sei3vdp*I*( z^$wAalV+2jy#Azg1davHCFEZBrd{WIv1`*8c`@_dbGN*p^5?L~U%^ooL{SqN#uZf- zSFMI{^}7Zk;%wqKt=sqgYJDk17)`c6sXlAW&6fMMsPET4(9l*1L;}MtIRvysg~*)=DQ$|Bm8oCHpM|Mj3)V&B~H}#i;-1PX^Y|w7Pveb!}WuThVwKNaBoz>*!#SW8h>*?I5 zwEYmXTeE*bO8<_u_CWu?u)gmd^rsS&B8t*HC8H&F*B4~S0h&iyBQ=3;5(%N~PcAb2 z#7I_mVgm7stSh*{o;{ZrMl04DXmaR-d^sl`JV{SLI3Xtfs|6TSxz8;+cA?8(sS7*S z=2U-Lt2e2`w^1DYRax{&Rox$MW(@}K+`v=yoA#m&ZyO&v>701m!|u3=zSE4~-IvEp zYNUM4tm+X0CyE3CL!2&K)bAdgtpn6f@j~u&P+hRASnZr8?X`};h{j(>+{uLOBJcL4 zW-IrCp4QV^N$IFlNXm^z-L|ePglah4?=$((9J=l}I^=8!WO~KXv{hyA4PDzozf0_H zW@^Db0h#;vb1H>9{R&+@u9V%Uxcm;dNLo~I%>fg1;HO};u75g$`5-iWmn%Y&3@(bersnHWS4xqlOaGn@Nw#H^-Nf7EA^{U(Evr5 znq-vYcBqWH_y&P=j$jR!Q&WI-qIcD*XA#|XQ~Sof_swWM`=@2KUxs@MVj6WM^OA2X z!$kk~UWrcT+5|oB7JeElIflfjFLFJ_Jtq?=U0cPN0~~_(z%4Ae-`RsN_ihP#qBpgm zA@e4v-d6bRF96L+=nCRurLiviFmgI_VMV}`v*Rg49wHOgttYryp$g{chWP^vua&oo zYlj$c$I7)VxduJcI>Yr3fV8o$@8&~vy@QUK{k3z#i7G7uDlDeXPH*5C8)Z^-#p&G} z)#ly8lV!R5omML4l!qEidE8FKa?Gpk-I>+t8#bSVVOov4g1Z!tZ((TAiWJ0)PQF{mDJ z+`9sD1L!+|`RZ?vVKX>+$mgG*WZRR$riFSXRLu8}(roMt{(MfVl$s+bR2E%4XCL(d z&B$auC@dYgr-A77K97cO>zZ!shHn2AyYTro!g)gQtzU3r?iGBp=JXe+oKra#L=$K4nezt6oIQ* z-s^J8I5Qf~%&0f!%8Jj+zk9_lB0YXKd50t>T4ZKIHoRP;fWczr`_;(;h5v|C7qHdF z)TmQHY1?HrBbSiXh(QVMH=uA3l!>dSZL^hjR^ih1b+ z0j30sW@_~gTQENf_h0;u7&*8IX8-aJ8ec(v*WKZ%?@T^dAE*Sql+rZp3f0308U0 zdv`ybUsS4z|KKtu>bpqhY$M6Og+c6?cXq%+arNwsOaUPPMFwpUjex^Nys|tAV)}LP z%h^!?m_>sH$mO6tb@9K%+%4%>Q z{)Oq>M4PObXd{z>0$ufG$=g8j6MWRrK>|c>+*oz-tMZ%7mibQ9Dy5GX z4{{?f?HaYaSN3m}`jz?@c^@}-KGK^+$fI^`sQmrQKmGwt2K<@7%YR|CPNyW6+WuNLa(V-p?=J6~=!HtSXyNyL2<1Q^GqyjkEGjdje@Eud^B!c-az z2lD7INr#rP8>QvNd6&QI-%_%j1jkGshe-!9;tm=tdgVG$2vctIVEYk{O2cC1PXePN z5Brl8vqgb_I`6uF2H?=VevdhenxgKH40zHwMAx%e_SRQphdX*8E7ci z(1B{){4y}FchAgb5C~74fY(fsb1p;nhGd0-AX|tg9Xagf<9?iVY2re`d+bE{35)G{ zb8LhxOjaD-h{%g@$g?D&cJkB8BFUkok`=~iV+;KJ<>A}tlChONgQ%Z+?w!N_mFsly z?>WiZ$o6xVajl($B@7dlru%w6&A0bS&*bOru(89Tqhq)JX7-J1%Rc$M$c0mmW2X23 z_b)Hq>wk>SWJ^UDcSOnk7*E+mW%y}(A86=VP`}@}U?}ntKEwI@9GeECApu!PmS?i# zf@L=yAQDxXq(9`*Ff=(FsJ_TgKMHKN3;odYZU~n`-xB`Zr!7TvhK_CA z=h$4?v;jQ`tG7ln5WLqm;3^;9A{2a}WgEa>CG=4wm-omlg6P!s8kA_J&`>B6#=OvM z3(<`TO%PtXN$A==>5T2wBoJU96VAC&V3o!q}GHYveuYt&|EBKXad zB$g58mcyS{S~NV3lhcsgrX)?r7OfJpDO{p$oOKY&)|;s#mA>OeT1r*jyzgb&utGjz zgAhC)0_e6pqG>==Xfs4Dv;bY1{}3_9r5O!a5NpfPv6jJR(*7=oBw)AuT%H5F8$+o(epM~ zTT@&9?h}C7r}i=%$Kr>ZRZ{R>rtXh#c%-EFNk1W95PJmqOweF57x#7p>1c|uELXD6 zJtL9cw6mnu<~@d7=iVsJ9^MgcNP#=%kk!^s>qH6B5C+o@&>XVbCglBe{lYWl=~B$< zt^Dqfb?eTwxEqt9>K{rD%7Vor?6MYZZvPw$@ReEX6@XQQ}3W8pY~PjWyDqEnKi8K{nhHoc{z3JUEd|*X5mQ_ z#%e6y6VbIH53A#f!bjB-oksUVcgP$^TY@Ot%aeB_{oq6%awWf=Y9_6blwp-*wZ-PU1%2Z&|9LV#Ycj-k-JF5UN6!6UmDQV3J^CkyJ1}%5N>{6{1xdC@LNsBfY8A zfpblB-{fd~D5@vK>+FgInABJ9RT-4e!#)$=FQ?2b&QEoB7dTJ}R0b1)khZiRPQ2=j zA{}=DeN8tbYpK&NCQ3WL+?qSlSeg_q^=(VRQBizXwZaCa3@kHSMt00gUy--7%tqN8 z!b>k2)(5B#!%g^N>p?G&;(>i>@GoF(uo!-Hzds#uJ|>g6d$?YC%FmXT9)PBMbaiY& zLrcpb5=L&)*6~lIV&Z$nAbGcn>f5)L+^|SXh5Yo%BWC6H!Sm?qbJw~oCrlrOGY&#q_J3Z&3R3>X!LLPtQPn3}3j=jrL}<~L(ioVk9i#YVr!tE6Vxw^%!} zSCPAT&f>xZMNBq2>IJf>JhQU0>PaHXQe^E?@BN-wAY{a0|N|UoM_*Qa}^pX~lBuVm_fgL4DFuQLU<+|s+iY2^$N@zV$0POrGsPcl# zDD0u;=4n`0#y9TY*%C|gM09R%P+1gUKSkKESrzcEisHozbC=QG>qT*QRP+=SQVt~>6E;A>S z<#klW937^=ORov=h-KQjxBPiIB>*O)+)`{&B@OfL+Nvy591qa#EC(X19rOR zxh4@G%w^}AP{^n(dU();8x)kWjSO>bNe$_Znez_NKWw-5=i5zq=bjS`|1xVw7hHtp zrB;thB*Z~QE9jO+?-~Xi+_7}^b7UEveA(*yYRrsX?LSy21nj|7t~2o*eu>QvC$l@J zx4b^d8Hwlf6DcN#S@xQn6M<*FWp(UEkFstShmu}N&aQ}Z*I|_TI}0`>J@b?1l@G=b|+k0A0a>$bo-|Jx##T_>C4j^YG>eBN)Yci)5q* zWM_JQ|a)*Z@B;CxpIB1?thYqN$5+s$MB!QDZd2h+COqiXe|&~$-nHc zij|ok=%sk6-V~Pcbn{fQc!{Xx@XP^x77c%MsZh3@?%nZ`wm!2 zF>?rOyMDN`*8E0Rro{ryZX@Ce24dE-7vpJ^9H1I&7bwz@9Z3@XupW7QCf zZNb?CE0^c;P$y}+;@<+SW+GRfqY=fY|X85)nAg;E}1Y8=cLM+;3swL=ee#?BoQ*wBG|=BPOyvR$b}=joY||zGIiC0~%Wb zjGXCwA29*tI&X}Z1OWFnn$ABIJ*iLD6cjuUnhFW#abMOo3(;T3L$#c(d2h~}*(KsH z7)XHGGv$-8Ko}*>Jys)5xc)_@Fe)8tX2<>kZNduQ`kwQEOEbQorM=1r+HSenrg}xm~0*9Uk$S*5RY&Hr8bKi`gn+!>%AEd;)qE z96XpT6nzPR2f>9*7->yO6F2V zzZ}7BR-$?jTM6J#MW2jsBuS%Az)8?a@2^%6%#z%n!C1(jIbP8bgU>`1FflsPY%t~J z&*EDy1-f41KYnt?$=9Z&&fck}nWxWwYA%bA_}%y2mxy$N8nOt?50ybpvSI7DznFh- zxG#5d8`Szow>ecU9?k+Zr%oWcmEQ!YFCPmWPIhuv) z9BZflt~EVR4BNF6F)rsM6&GAYg+9@aL8el%-KFrh2V%=0*&wIs@+Bet~Ck+f)~@ZwFa(33gB zf%H>_}px{Zvhk%Hs}eK2DYN-7l={MQ~^01$z+txY+u%P7G;{e_8DMI(t!5#6yokF(DUrLcfek_FAlv$1a_BiyVNiy@Wk7FtRf43PbOea=I;#f7*Vwvmu|Ki_gXHN!kY=(S}0gxayhnK)^N5{o(KZ{jQbi2(u${qoocAqRV2($~4aD$iAisgc};00e=Bf#i?$4E8sCf`aiOyhuGl4#;EQ^58VufxjXE7V*t zHbZE-;-g~7enf7YU-Z3p>#@T|<&}S3BQ34hUD)`}{e)>nn{b){#JG>jtsT><2}ewp zx2hpUpmV8t&$k+hrKMko+E&@lqh@*1kkpr_0#>_5BZlW7adK!ScByZ}pMn+At9sy( zg!G_Do9mbbNkX_mgS@L+vLk`wu6;yUckwjPP#646^$$NCmWjh(|KiQMoJ7(6dQe?Y ziu%J#Ww6ioPvBG6aG3b!pde!iS`O=s3AW-)Ajd$UPcsU$ys?R$6K{{$VIC}>>viD| zyP^qMmyT7~D(GYidy5`SBxN6&@yplxy&9QG`d#$+s=7M#=qR&C1&G<&^Es zeQ(Lh-sAHikS}bkWNwya&nJR^-SR4MN<-az;y4yY;>qp8Tkuz2eD#9C)w!| zG?z1_Y!mDj>)}w8ltag7%)gP16oI>|`2%RAN}HOt$Pw`YU!oUANoRJORxfv+e`53a z6MQ6vp^q>e$$c`YzV(?Eft$8Nyc*M0J1n|J2I^5eEc2v@6X{XxNbM{5)CQ6zjq{S` zgM7;@IF90-U{alT*wRo@`?vO@fki)Mkao#ga&mD`O)EpDC|5>TbcY zGl!?_UV0lkbyBMDFIUzl$+y;dg`2F}Rh8YcV(TZ|DX`^F->!n-7g8^8o6PT}{b#zI zBkzos6W?b?e&t>sBGdZI(h7+0ru?cdY7W3fCVrKMY&b3}nwTu9Fpy|@Vvm?3lp=7b zjNs(shKMTMD!!l{M+v?P?)6W%ny}m#nW7%qZAVD3+Bja3pT`dQa*R;&`X@!W&kjWu z|9u7&1+m+KY<+mGNfspp{L(-_FNGoDm&z4vw@03k<%E~k?HH%l_1ohRroKikCjElo zDLHoRA|FhBlPA9QL+lRUqiX!+B`WlW2Ia;tb~MIP8J|4IlAHSKE6wlHTe}-j<8tb? zxToBfbJdPaSh2e=R{7fr<2lZGToZ-2N?)HMTTV~u9~f)zKzSNhlWY@1xBrq6>6KAAjZL#f*rmh#oUL=$g_ zmY84OdqcG(&k*1Vp)4l{P}+>NDszD}>&rO%o*?b>r9fM4_}uH6ccEy!Nx#l3hvlGt zl@B5v^4GrFg8D8kLMWRhOZZ_gcK;@NzLoytbYjH*bsLYZ;4+QiqiE;hy$=hKvWR=x zSjbVb*xqX|algnwdwbZoUqA4&*`uk8XiVIK29g<0tof90G#Kt%#N&k+5QiDnpLy`NQgkgNf=B z=T0+$)bGqGk<7mRCNf|8%Ff0AST0(5nQ_vzpQ+^pL!48w01=&1Qo8DXek;!i zfX{yltm};C)^>LlJEPt#noe?-`Y#n9V>@!46Ns|3eGMe}NK`6!^7EvXH+S4JY|1pd zg8}Va#zNNlqIK~~$JR70FQseM_q{(e%sDewQmDJch}mXLdrsWMhcYdtVV_^LOzIn* z$=r!@8#%kAdGcQ^O0{3ltS(aYpjc{l-1ASa^H|qzDGIv-=J+Y3kxzD-8Zx zT1{C3Xhfkg*DQ!<;iXj^uOQohwE*X3tpo%p&-1y|*5kKRw2_`PE?C3B=!69MCGXV= z;ifyc;vX8{oyjZ#ikM%!x3E8s9oEg==jZswMn-GaHN9e<^6}2K#rK$G4qgdnqM-vg`Nlv)3YgRQ^24#G!0UN%nQn}) z7;mN-YO#&zMR9TH4~fIFW&BWG^n4gYH|M95#-&jjOZDZ_uKhjsSDVej` zc)I%s%M%Infx4^7pQdglZo)!gQEInD1x{6ObO>3Y1p9~GKKqMZ-H=|p zkx&B`D2wGng{t)z+Bfx7rEGmjm!)!>M!ZeZ2mRWbZ*usoZd^Y5ZcBvq1_n7priUc0 zi$7oE*GltcZ}U}gG-TkHKJ95hP9no-{F~``f~8w`PGl-t+Np6##zgStiaXY^E>!!> zKK0g+V=LjMJkJ#h5ny>{w>Wg=ono}GsQMn|I+GM+!Qb&VJ2Ctf9s6pC1bc+1cKS{V z>jAiIDs9Z~D+!FmE2HNzWrW&pcMgs>k~lmG?qos3B+!-MRsZIe=C71f+19^T>1#h= zBo~2M;sd^VUP*_xTC*CS4rCub#N7K~_=iiUT{jl?93*>ufbfFVWO+)^`eCJow?f`Z zKdUzyS2Hc>>{HZoX*uUCx8CIPG#S1n;u%gEU5?ZV!2Ve{ z^H_LL#~C=+dmxY~zD|rbj-t;h6?MX*LD?V&acSX8kkkLFKr|{1d5j~0zS+KxkYDo) z0^Ow9K)c6VJ$=)jt(;b_d0-sQb&Bxw=APsK?kjL$G`FAVc{+)C0^6cBjQVEsgZ2ObU9pkd#p=;%oSTt}FY4QIyoY&^=vj1#+L^fv9vBvjL&Ca`2L{57M za@%R#NGm2M&tZ+w_Ty4tndP5p#Ou}vZ2Di~Jm)Dx*If#;j$(khjU&fOq7>5gIokaZ zHR=pYuzh`TD2?k>#8zdr#H=M#`4309Q|C<;I_eFRX6R9PsD%D)pB?2C9d>S2>lkl% z#oP4n2!mRq?@cuT^=8b0sy`f< z+8ffcFUzR>{jp4z&ejEyE}~C)s~sdasOzhBll; zX$f}O(O0X(+JtP?m;3CP52V{b|J^ zg6Uxybc6GX)gDt-(x&|N>zeFb-xecOjEKy+4)8ySrU#h5g6a^FfAV2nYTVzx96rzg72ATHtNyMKt*W1w z?Ro5!{llLB;SgaGeq#KNEZ^ejL(*{Oa97a(OvP2Gy}j@ z+P(C#uYYd{JlOwnQh*L2aQ(uEzb){R^P)K$uM(f_768>$Isg{(kV-_AA*aCIUl*m0 zw&L>;Sz+q%k^~AAYqAq@45PV(_y*v8u1`#$SJ-q5T2}+9+$K}E%WsAIW^n)vnB4^{ z>na4BmklO!Ym}nyu2H4(NvBk-!QwN+(fGIfn8j_QV>kYY)9N*ZbM|+PO=4N0R!JWUla87J^vl1B9Sbp9-`q^<`XYqy^HWYRxEW1&y!boX4ypNc z?iXx54wz-v+FwtK8(P$x&nUW?mzxX%%;E2aJ5>W^xE69r--HVqG@zv=#+|s>g9N!y z-rza60XyiK#%jH|%Q=7#4e-}ZDKP$HjsNE^0dN4H2?LH9{$XZ(uh-GdvGm+<|LJxB z{gKzj8Qa)6;D@ZN+7+$s3)1D!lP%-Z&>)mCaK$nMedO_sX~_j+vpI)b`9Dw7I9A(k zj@n^zW=YPR$nNUf&k^dWM@XT(vHrj3bS^HoO15}*xYd%FpX0!Omhpo0TzqOeT7Kiws zF4p&-P!behkgFEqZ4bMA_J*w403j}JI4)fMf@MOAdFr^T37?2_ZU3roeRC$Fr>#H^ zzQUv6Cv)d#u*Mb_GHw6E9AAu$?3LO?-klyrA@3>YwaG{48s_gCjUf9#xb zcFvx$-S7Lpuj_ho1`(Z2ZChv$7T zcW|rcfK%!FP4+f)rl1asq#jO=1wDdzuMeBjEjnQl&>pEGj`91Rv!>A)2NpA8mf%~q zSQj$Z1!A>&yTb4+G?WFvZo!GlGra?Omu&`?pSW+m|PW{Mx0&2XDvo7$y7d;5Pkgh0Km_G*$g57Jo7vpS!+Ny24v)TrgeSxXvxGw{;k0R!Bh^ZEee00p#;RZjHf6?Zka_dUdM_IuT36EU^n zPcPo$CCB9TJ}DPqb~+^1eQP%8Q+Z*h)cz~nuSGO&Q-P@Q-eakM(pzN(dDX5sDT=#B zM&!3Z)aNUTvO7P@kB;x(Uu}`he|90RQ>o^{#EwjgkICfo1~sBBqbInNXl;(UYw$?8 z9a)U$zvY=)%!@sgLOk5{$~~L}Ud0f}UafVYt^TKu1&V3N#J%S@(H^aa+`oRa?(qTg zI2!oyU$#t&0SP}UqdCSjH*-MtKBwcnU7H7~32af(VIiU6)s6e2wU}R>cZ^v@08-Q% z+e}B`60TX8^0DsikA0a7epkrle4H>iX=A$>P*?sjI-YbTyYOpth?9oopZW%_gH=aK2Rd*w)xleL<9Ax$HNrjG9#PLGGl&vwA#uve;V&f&oWygD#myX zzJPS%$`6CyFea{y!@a!t8jI=}9gN2>;p*e<1I+NZ4V{KKQ$e z|1h6sv*}6m0ntYV(J2lQFML1++rXMP5|2N78<0@{>3p4_f;@9kc({?2&klN{ zxAt%#Ht%H^o)V9G#6RvU%Q(!KAdyUn^izw+1x@Hn0MJ&R3Jt|1hNd_e&2;y34C z|B3V;Z5K@t39**KJpcVXhaeVEeulpSQ8}Vv(@i`qg8b_t2JT&%rzs&mQnu2Kuc8FT zaUKo{7qbYw(U%Wv;H-X=>sPzvFj)G(6qS(?z8Xnc%&I-NjyU#x4pEdL?+7PxPk|+7kn$cxRN!0Q8$%_I``Z@3fy2KlMNVB{}Ls zefRh{380F7(%x_&zLc7pDM)m(5vB6FOY!_i{%osJq2YV^2(KZbd(QfLxDlb{+a&*Fwj)d@iQ__#yU zI#lHHV)!p!Y;46jCA2dSxo3;BHPO4`RA#(nu$LsCC{rQJnsl|a>i_@byN54fE2Nm`5r$v3eyH)_@|D1Dq#e9wI9$V%p%pTKQ|@5x<# z_hAPu0>}_FpUZa2{YKe3Udq$vVugI_y4I284e>p~fnpYj!sI7ANt8p))o0t=jfb}R zVy+)d6YtaR^g%eS!klt%CG2I{!|{e!!ew*~53(}ATPI=h4abHz_3|Y}cQ4wZ-JEKw zlYns6<3qybf-di@SGH!9Oo>*%Z^K~V0HPdOA#2kD?Q`lvw(@zWurfgoWU`NJdTz&B zD7xu9Nc_ZCrc;B4bTS{K(j{SZ*`~B%PQa;obj`df%afs!(i~zCutS?r;*4p<6XdV~ zeuJfZrHqiK!MX~+>^TqEu|(y?uv$%?y?kdR^w83SXRB;wxW{PXdnV0qZzL0+Qkc6Z zwMyyTx2Lq8#Vi<@eiB9UVn629SWbMVYxf*(j*@lPYp1WU+T@(E)_R2n!x`UiRVl9m zrqC{AU8cZQxmnOPDRWtNGp3L9lxyIJyz;e~)oK48~k-492q6Qn@0OH-Y1aTChef15}NWYHuM$%;10AX;yabRJJRA4mUhK#Y$nQX9FbBv<6bcHhDH z&=0xSdE5Zs14c!lrj^Q5oF1%JkzQuky}UCfZW}h2V&8>2-qic9NeRt z!L0Iq`WL#Fy1lbUkm_A~=T4mGgum9@{E}sN^?zn#XJx{SydS#u zIU9U-UkSPqq+c@CPe828MvU z3I902fe(1jt6WoS1;ll66-E-uc`#bi1IrUx+yvP{Oj0}3lVn07{j&plY?~>US#+2R z;m!$FpK2DT=RP&e9eT_;)*Cy`fP%JNqPi`Dw=KB!Zp01q1xU_2lvI%VNson3a&-q-mkMc;G;loth9q=TW!hBmqF<~_y zW$CwA9iREJkZ_2YOV*2$(f;5?lFPRwx@=d^KfKz??eO;;Zb)_udQJ_$FC81{)Xsy16cz4#{)2J%?L zb>!~J)6%yoqVW(ilt0qPlBremAk9H$I@T~ZUdq<{$n8-qX z61nrpZyXt_P4>stc-9_Ga*WJ>ZhbCA!UO^i-fA{!E}C6B8%0ux56Kikgeq zxONpl^|{g%wSy?RIqnLL{ZZfP2N4q-t3xBO9r-!FJhBzMMHgqgWs}-4RA`}|Q`x@8 zDAsu89z`Y&Ld6N))L$z#;zR#_yWu3N82yWc+`@vKK1$a{^H*D+$ex$+SD!>P^SSa! zUxNLnuaVtbUZ2=eA+xm&SckNxu~Xb-wjg3FD|Df zM7#pKw_&O}%e%ZoDC?`FpZ&e%0XVY%T1ue8!ZR#IooUbMgiY@u%=*FW5qRoHdd4n+jbKDJF5lI^)|Nt)Q8xkN8n zbA90(Brd-nFb|f;0O7xzsh*2Qz z0}IKO__X)#DBtSiHu!NEe18FHd;Eb+Ai0X)HvaE=y)DnzU2}&SeSL|9A`2f6+HUF| z_ZC;Lj~KUU;<2lvKzMp%`Y5w~S-yVD-$T>~Bg9{=(SPrJ^dL#cUUC}StqHgltDyX& zoOf6GY$<6;Ub15C>9DYj6!va2Mi3vLWsq#ZiW5#yf;#x5^<$JrFxaRq0(QG&9hobA zbM8JVXz_<$AQTo~eC|1U>(9spt7n%~tui`CJVc4X2cgdNFfvaA$L1C!%1zJi+S*N* z_=2A_!cJVUbmI`kuQj@E^B4hUmtXY?g?7-?vZm*|`PBGO0Ek_wnfY( zcCDBAIU#pqyF^62GwSXSIE|KRmv2G=mu?z*JlBt>0MWcQ;5VxWgwACdp%9PP%4e&> zfM%fH8jhM*_=#&_4HyiYwfclj+lBee7JQOY>#~mRm~Xwkx)Fnh^&$e$oLVmkJ(_6{ zZI80w>bsl4kCNJ>0P!l-vBr@m)jDi)QV2lCk+WCMm)HYso(7O2R^181fnIIkRfy6~ zY2gv&Inq?1=~lttM4#8cTeAn>(yaI*Wc)U1SKC8wiT*`bUpr{)NlO$LqyDKu`@w^& zS&j>grM{`ikwZS{MUiXUIQK6<-85hcGx zqG=w3--5Q|Wsu^zB@>FuLVKSit&4CBnunF?rM#*HKX(vl4LdtgS|>aMK)})*(gs7t0Tz;!IX(Y4E=AVC+R&mMri0I|9w~CCRZTJ zpT&ADO$e>>FD~2IHEth6L&JX?OF%C%r$t%`I%~Z6E z)z6q++|Nm$Kbht2Q0y~}; zX^RT{QK{u?Bp;LEA|gp*FD0GVyHKt{D;q_JzBskR3{8XW+!d_iFYveoFx=7xH|gbu z=^&@Gp3LZAZrM6bBCc~-VZB?!{vMse1>y}=I-EDQ#M_AV8!fLrt}1TS5ec_XoP2fy zk6D^ehbV=zvw2hI|=yrKJ6@cpH#)Zq8g#1uv0^&*&IK!GgTzy;% zfjpjlOd!n(o+SrTOyL`-DZ$UXpaIdQ)FRB1v6#u1Tza?Ym zMbEbW_;;qS&=GE$Y{{CJcdOASh-XbsZ}b%o)Ahn($YG5haiGDYhqUB)O0TeDj@}`& z2{N+-V_skl^&x)c+`EXKi4%t2xhw=4`AK4&Uk6{dy}y@+OVKq#*}lV1VMub zQh@5^Nw7Ouy=nwTv>ZIMg!_YiC!L$2^tacS`9ZRxN6eb*$$bkk%M* zj1*cgdM|WZ(VbpTU}~T$D)nA^)OGm$R-P11-l*i_mYnpH?RAjs5^lN3?mJc`IHq|u zzbIB~dG|~#uT&oTAbl}fC!`kFx$6}xfgiqY&$k(1q@RoF@qH%>ZLQ}^t_%P8Q|kE! zV+c)IgBaL%#wmASWl7kV;(^#av>RO#1d~IKXMTM3{%Voee-s3Mkmf&U}gMQ{% zBj(N*(?IlX8H?DBeKX52`Xa{#W7~xJSx!$ z;~Ko}OzP?$5x`iAJhE(EUfa09F!MV>{qf_;epLrx!nga~=^)zG4ECi2-`>m~ABiz+ zo*$5x@PGFd;WY!V#qi~B7J_BEZxMk(kFeFpw*QLF%?2r;Ycc)&<*of^7nkUN?M}j~ zHx>{;%lnT;JXt5ivxBEuj>GXp+Jy>scr@;c?SMf=j~SkObTIM$xfQm+sP4L6#4#dhH!JH?)5nz4LYRkvYbmVG$25l zaVPWzad03%)pIODMXYz}%F+8M4dfZzAPg2=HZ-~`+X#yfCB0EOUy~ZRunp@I>_8Aq zgn;VHkWumC0!1kt(FU%`BBqb!UHc!@-)0mR1A|{v{kBs@7i$DJIg-7n|eH&ar9o|Brf90r?YBK{7JJ$ zK@ii|e@dU@;+}Yh4q_#F*F@NSNRggS3E-_$)1*Ke+%oLHy#+J-WM7eoDTXi~JE_I* z{&aEMOT*U1bb`vn0t{cLxe(*kizZgocmOow$+zEZM`52LBiL;Up`3>K+A)k`^dq+WCIeM ztA@~7*vH;!23^~>m?4NyhqPilxnw%4smb@&P=oL{Xit9gDWm@qEt>d^EpHzmNo|ny zhIZCM&lu&a@wB6(HWXohLvGe}mQ&0%?c6WQbz@x%iIlS7tj`Drq~i-Fu17tEQf*|a;SvC!xS{BZhx%x;f&I*k4S!_&I~ zgmX%SwFU&B>z8B_80YSH@M9R8A!o06P9bLKLFYLP3J&JAU}CIh-0?rwJF3MvNxt^` zw(Cw#BKx83`xgcp@av~jc$ySpB5M1t!yytIe~N}2E!7eA@G)VLH?TE-I)ox84m@Y) zDSmcvADe%h7hs}u{;+A+(g(+n=8*rbVlolqlG4xCLj1a*yr4A+8G{VGj%j-UKb!_W zoM18f9k-cD?e)6w{Lh7zb}F_UWSL|EMYhUajR!t(2HsS+-7g~^Yrao6vUHadKI3y} z*-qLzb__=V)vHc1#em5ZRv3Jmqis3J0GDFqpUamVnv zJvO0Nx7E|IXoW;+?}yQ!d`n#8a_soY!Jq=o8N+LB!Q16n)v8%#UzM478IK4s-@UIO zc19OLe#Goh;L>5!%%$A+=AXKzucmtR^O3{^z2KZq%ry9-m?Qsgj@sy1R-!L{pBP^w z%HFX0YWw~6P|B+1)gM!TFoV`MW`h*QkS`GxXHUW}ewme~)8Lz%w%!XL|299T_Yqy# zjcm7riPhGj)z?2qktpX8@xG4Y%_Bj!Qy!uYeX)mhWpdY+pIMw<>C2N!;6?dfS||{% z295=E+|R@xB|V!zw!tq^3f^-FH}J%rl~7k}Tzp?wOr8m}Q$MDk)GyK(8!i3jYQ|O4 zAo(-LY|70_C*_GV)m!GtT}xG}E_^)R?-UK%Ju5q_<-~$(JG;?F-w9@FuQw46cB9(Z zAjhVDE1KIaVrC7~EFLPa*yd`N8jqxBXqTwDg~?)T6R}9)7ND`k-t}eU!=GF~kOpIv zDM&)eAf|{(AJ-eIrCI4U87cKicjvcg*JDBxa)K{>-Lk!)lQko6a9HCf9PYFh5?X#* zawmM>Rni%(E``lkK>Y~~9e;T2`iv6s%kTUwfM8dsFh${hlKLtfoju^zuv~!SmZgY> zlSlb{W4FmS9-*f~QSgFMuPUk?_xD3fgcI7Dx;%%}lslSuo*>47RdhL*K-Msbio7Hg z31}WW7Ep6sZ5Ijaxjwrf$YBYL>!ygG&^PO+(->v}C!~Ckw!bm`8tT@w^>fow$^DgK zh@jeU8{<+=>*se23^D71%6qo`C~D|$F}j^#>4&X)w0t)FW}mF(D}FJ^Se7y z`7enS*m~vqpWs)UwRHk}wi95-#-BBMvOCV2otz<)E%?ZI@flMM*~1sOgat-s@gcwfL`=%nn-}DfdO?N^XdnLu#T$TrxK|g};I_X+xykknreKmM=bs3t z2%D1I+Fj~p_8PT}pyp9IS$kDVcucW^T5^WY^y>G`G2Q(ERen{T^B(aW0gAd?bL>Me zXom9K!306~o)hi-`W0imR7%nfwg)NevT`%E%IYM^wO|%;$m>3N%6(NN+EJ}5_oMJr zB_n9am101leYQb6nx%P5$OT3$R`y_!pNna#ukR&KjeYlniz2j^X}*^xt4PU)({E$& zl03MU0QANlf6Whd!ScG|(_1gh_3-acL&Gj?_g{lH?nsqQNI}&+8Yt1fn2W{M#ziap zRGXLMgSKY!gcW~S8(Ki~`U)oJW3Rpn2y*_d=0MlY)p}p~^&T%*H6?qAVRyGgn$!SS zH9G5??Mcflw?uze*V}H&E$C0QTN%bs_YK3G^_Du!k+)veC}7!^B8>TGAFErHA5TF2 zUr^Q5-M9$QHwe!pnVJx7#1>PWkKK{W3PuZjmLTXkcTN0VlUE>gWzSCzbv4r8QW31S zWn$(j8y|;qM!;@Q@N4x)0GoMOJN>(to_^dXwDp1Av$6YWs_@JL@Xz znjFe}Cib5?il7ir?z|PMl)s_~l$RZ#BoN(i%pk43r@PGs65d2`@8_sJS=i`!7oS79 zu|MgxfyVGKmB(8cSX-Ug&cc2+Q0M2wXuWTYh(@ zpza8_CxeOwfU}7lslbq62ZEr)*J3M(&5Jue7_m)jHhjCE%KE41gptJ)p#s5@&7{j` z{@C=_VE>3dKP*Y%a0sO>-!dsCV$r5_%XsIobk%$49q5$Vyid6ksD!gY&SDhNZAU{g09%7kP zl$n;xoXIj5lfX^a_c`kO4(v!TvxJjoUXnkhSCu>lC1G4(&de5LD2`t=k`(iJ{8oa{ z`lA2=cNph-n36#TlN6r$f}Ho`J>)S9@^Id(lY6%Tn;pHWp&R_4Yj}X95BY=((AR~? z-Pk;yw%zw5+K~5wPt{YgR8P%=wWv8szMfy@!>Q)dY4_*M?P5_R(d^&0E6Rf%sglNK zmsAC=^hlcHbgYM(Nv+x{SnOupPj6KFoz!9l+IAiuW!26Nos0cV)34?uz6z4Gl`^o|Q~$ZoF1CBs4K2{O z@j_?bt!7hgPPn_1-2B}=!G4eyJfEdr30JiJi~9wxK4FO1I#$mMY5Kaa8!o9k9|r2V>h;cC9hGc}`E$)mg8Mg4D}&!bU2 zEP!e;R{vakkzyGw9=#6uJue=5S3SdA{FZebL*grDa_`U2;y>?CvX`WA z7guJFB$EU1O{4a{C6b^DdKn+hi(moJM>kuWQx)jQ?;PQ5^J@uz$Jc&4*lAP0=l9UI zoxIHmGluCW`UOz+1-Vfj@Y7Bvhhue~*r=?WK8U6c)O1E{2UH2P$=@9$(kxuL)du|0J8jcgT8lSME8&?yINj8zY>oArqAo^M;u;+)pD z4)ASCk-$(g+!K1q`);vAjKPR9{pwuK57QFA*!RFLl`Q)88j7Y3S&N~}7kfH0nZV## zKFH=7Uz(Ty$+vb}cQO_R{a@PZtWY4v9QOwn(eavJ#En^8U5XIU^DSga@0!N3$^7|> z{c&rKjkEuM^tb(1U(RlkCuYKQ@{Rj_I>HNXmjydWzeGJE%K?E*fFy3*X#^m6iG%w0SC zv~C_BXhpqXCsN`v5=tf%0+Qv$!s@28{m~RQ{*gD91f{HTKG@^0N?8(4uuh{|d=zE% zFR3w2aWY1`BmI+)gv8ICSVng086^7Qqv&3qku1hRIX6ob+wBdni@h#uAu4(JAzTjM zN4x!*vGaN)+-5+MN|skT@@jPB+LxuWYdHB@>zxjeXsNuUKyRv8#W{`1{hn44Mj^D6 zWAz`9ZG(2gkP~4WvR<~`2J|4C0!y=nL#|I1LW!;VEVUmac#y1U?9p_^g@l5i>$%J| zqA!g?`}{^oEQLi&7K;T++-7Bq8i3Xr@b)w;Y@8D6v`;}~00UrqR^pq%;G$iwAY9YCmplpfB?+tKFIALNkifu35 z?O}=<>Sdfjpn@nrw&JsGd?1ug);R_B_#AjC)aw za7uQp&W#q6K$hRAPipSy#juP|G!dR?dRKv&C{Lj4ph#rGWSkKAvyW^h;ky<-W!tIK z>||e=6CxNhw{G#L?D}b}%CrlH4L~1^;GQU-qhTCmq z(27we0YU4FonHL9y*L@!Jt6b@O^+Anxakwa z?()spgbgq0lay0;xCQm87Oi$BujvAa$Jz1w_wJT}jfRzEsF@tOGf&J|>A6YL53k`M z+u&XjdD826);^NaQG?2TcS7p0tGGZSdYZKaA3E~cuO9r!pZiZK<^5dRrc&aaQo&bB z>AE4l6p`AYVQ#>&>(|*Qp0HV>~D6ia8Uya5RAMT?g~CJhDs{Y4iGlUGRnz5-7KxT6(e|eH&D7nkM~vB zxFB+c7GC4sUmo`%s!Q1lzuoimywC#}H;BlL<@oR!Fvd*rx%M)DENDIX33o!>oxJ-T z*t!tJB4VD6dTBeOMt}3CfgNjR(0#>?CBlI1^3AxA-$5&@)QTa_4m1RI@?lgiL&qlk zrZt^W+ChvCmUPj%6L_B!FGiOT`|!I%#Cv5;d^McmtTrKDFk}k4AQ;gB^?t9ir-duW z3_&wr(w!}Bey@PIQc$T{wK>svGu(2nYZhXU$)C%(^0D`*Z64}yS)ou^MKV8>*s&}T zO>BUm0gMtAfGPgw!oFe_PE1{bryZA36`6A}<6^f=I{8tl?30aw<`10KU@07@wQxB5 zlj^CI7uA1dWgMbJIW~P8!${>##U?IG%DSn|DA;$-FoKg`Mr&#N_bT`J`|;`PL61~+ zSl>}!_ws|`XgZB;HEAzqI~lH-Bv~e5M?$H+S5)7sZu}}{D-ZmfgjMdTKL*a#P%C7d zy|)SoeT3imIpy9U_f`$<_#}i5%=1D}LX=s4vMKYao#z0;0D0^YJxMz4j|=X+pq~?} zPY*ypnV&mU^(r@x{O~w}@a+gwgzKjT)0bd|;Q-l6!y{oZDz_X3Q!#X0_`A;Y4k{W30oF5+~7^J;| zB8V6^Izq6#K0l)TVf;9G)j{1TIzIAXUg)0%p<%h>O$eYw+3rt{kHMgb!QklV*Gnt*D=+T^6e(DMHbp|B z+d;P1O;CxOJ4#(mYVdqFJ4HA<^-X#K;W1>CYq1qYx5T%S~QA#vSz}&Z9~JW~u)EszoN6(JD#HeR;x; zC~9mL)-VsX()VVP!|K-9Qm%pQQCb>!r}heL!^#dvoaKrn6_{Rk`BCFM7vNez5Bj`+ zbsn@I(I=LS`v-emud*c%xV_1&PowxP%&izF-KK%U1{Yaq3O*w=1)Ux4(+3}VG^4k} znh2q1CXBYjw(TDbla@qs^i!p0-GTI9W57^!x`7J6z|}G(OXQ7xVMu{fovE#A_9L}r z$Ey{9L&98_ngfaI=3@g8boI^8_Y--c_HR+!!-&S8PCh4H7(T47^_%uA(SYH^&w}|# zDyGr$e}*hQ3woUwSXwm+f}-n+6nH8&YeK6_;A!5ueeKd>`jyJ&C%WiRXr++|j|4Sq3?bY<@G zV85cI^?I8h9O_K7k;}NhJ=KV+i!WH7Btp*SY^fWhf07nPAiXew_a1XCbirBLy5|;3 zKV1!1Pwl$B+js*?+4%GZN|h|+*7~ip7bN~>l(|V$h|BAG*FE{DF4;#+j?d4uy3kmK zN-@7|&M^nqSM^xm_iW5-?__s1TJbH+S<$$#7TUG&L54S7Bk{Dkqc3+N9xC(tyd(dJ z;5L#w)wHPn&yEjrC-!)s&~~4Lc+`Crw=^MH z!t^l$GK-o?I8Y+?MZY04Fe{orY;NGF##QEjLy z#2&DF12&@e=h_@mc(w=>wIev<@K1Yy{A$*(+a^H=e#u`4 zZ*3YX8&s;OS66$TdI?O1xRe*%*L?cle{=S@j8$WTy{=JG_eu?n2S3j=teG%jJmEwKyrld%*9;%^I*P)V{IG|Is zHc{sP3w4f<<)lYe+}CQRvhwF9$k#zbxNb{!;(Fj8ZYiW_E>9q;2unY!P)3{6C0i+< zhhT@i8IfG@45@g6OWqz!#_!60W(uASdBf6gQwIlQ;nX7&UQ)+N%5)Y zD5k*dvFbG~P*^PLmJ8sLQ(7U19xCm1&!RhL54bFXkqjkVx?jn7C^VL&nj?S`_Mg2C zu=4%e2Kpk8{(&y)=7m9@iRsdE6tC>RDHoidTs;ZPC*Qz7e*Y6KGQzRpt(wa19RSh> zNMu)6g$XCuFv#XK+~_;}O@TQu0PVJjs;d*yEEP&ERx(M;cufv`rVvX}h@~tf|C{Dt zlE07wo)jBAk1Ko{jwU|+PU2g=s2G_h}s|2OSzfic_jc1<>V;} z^_%~r1rSmvxBzCasPegT?WdtEXf*Qr8YcFr;-6yyYW= z3F)R31T^xxV}=+}E|UJ8CwJgs{sxBTo+b~9Y)D(KnJ<=*oG8;p&K}~(KzT1YFww8S z&k4kpxj!Xz8bwCHTc@btR=tf0?O^(ki7>e`BLc-OFn6Hp)z>A;VC4-y&0*=&EX0YGP7HI*deGR(Rs|ccZS^#V6s;A3Nk5G8EkfZWT?zn{rVS81VkbrQuI4$ zcqS*hN?!n5tna00s8j7vX01P^l(^rp$6QT0NkYW3v^48hJWvTgjQzswqQWQ_$UBGr zRiMbwCxSWPHrVZAKSz`Z33_u^QjX4ChF-{r+xG9cvs)D4_xdj51FVs8?u|V*bOgL_-k!ktv;$1|F~gYQ1+lld-U;Oa?C8ghs?Yx zdb^Hb=~akF-@&_U;`(y;qGbW=-e8cS!qs_8&Mc4)VMt_p1Y0XCiX6R&kYyeW`g?6i z8d}i&i$SCz63z@$34sp~!P%pvyY7j747tBAgX9PfJ)#jppu`^Tn~@0*p>{sT#P!Pr ze`FHMhx-j!*h9Z{@JiRXTG6g5@>^S@W_1R(X@uAj?>at*;HAb@}S|?uI2O%?Q_C z@3pms9FP{?0UYLlBjbmk=mJ(_IuIr0b|A#2c#^(RM6@=Wy1YT^eK3;l0Mj^b@OiYHJFtZa! zPjt_gqFNUGNx)8RZ0C+6dy(;+{xx^A-md`^pZ-PD(`GgJ^ec~6zd(30E&i7DGcK_T z*w{@QdESi3sN63)6#r{)t#0-FQHUEs>v64=m8KI~%^diygXHS+E0{8m@3c_N={)gl zy9930a`YZ;O-sX#|KtwlmizR(rQddYX}(Tbgwoog5fB>lzWZi4Mv!XxMPpRq=~w}Q z)hS)>j##C1Y4h8v^jwtJ@m-j#CXhR7+EO$W|D<>)sg;Ncqg7&$!)cD~t_V?tJId2W0L?>tO;_q(i7#f;?Rx#|h<+uLWt@laG0;W=Ax!k<# z*oPy+sDt1x$Ct{w=#_}5%}aFwC`9r?2GKsng>t6g&MWKN%qucuNF;55i`l{_zs{`F zeJi@FtUD-#AsqCX1N-Ab2ccrbp)oaZ4x4(`TCHi5!dMT+zuBJQT$hBnWAbx9a_G5O!2v ze)Q$8^oj!{qnM3Y3MjgY+RTZ;#~==KItJm$lduAZ%Fe@ zmlXr-KSc@}ub*!LHg(y*^Yhd@XA)@|s8l06u0RC-IC^`$r?yw4$lu3rB|RU=3InP6 z6Zs^6tf9O$RvVpn&1Ju&W^bsQ>}S&O{dOvE0+wjoEcD2hAet?a52d3LcAQm~yq26d;N0on|<7@Vda7-(RKEas!wR*9207O zCGpvvgzrPt0CkUS1hU-+AfL2$cr<@?C-O?}=6JG$@>j*5H)QFh$V-f?Rc9#9W82d#C|5&dxjnnfx$|1%hn4=15it{gn8r zIKq5?h)7>P#GNFbA~K4Lx^e=o(8L(={YgE#3LDUV$PF? zoH!sCATbyE6i&GYxeqwtQ-Q>Cqgl8=b7foGYT0}ATU<7moT$T?vi2y1JtIb-B14V; zEd~5#%PO@zOW|3U|BBgf@JSL1droq~h9Aa4J+nn_9Frq`l71C3zfCkDltw;?^|Upu z7vEyv+}{13?!A=q0*8-i20A~O`z{_Sf!Y7}T8M(Ak7aZp?IwIjWV-siUbY|*e_vrU z2zvL>^6=dV#G_DzJYk$~O4X@IA9ZGvtu!LlDsmf0;@oag?|O#MDIFX1Qxl=QkW;_& z%^43bth>j{FqLe}M4iEPXx4TeL-HqSK9MFRHCW?91QOe3)nfN7OLH|NZG%QaD*gX?x$=2acp|(guJ-%nlLM|?$)uC$)8@&pbhvfKK`R&Hg~Ri z*Ty;^k42HgB?5tRef3bAm(IyC$-Q$%4U{Ed-~c?Z_QkG!0_W`aVs|V0g*a}lZcq#u zJQQR&J$?PgsY&PPxion>_Z#RhW$Q7nSkP7Z)49WPR70ilX*JpBMf*UEEko%}7m?i6 z^=QCD-TzmGey7tO#P_-^p04;l?nXQwj6O{3K+jf)0y5C9Zk(tv*Jayy?F2yuC@)PD z-<4vNGGll^@?W6;B`MW+{QO=?2-mF-N<=GtRK6AMjX-`!EPaP645lwvFQz@NqTXO$ zbYoW!+Eb6;stg*ll`zob!z;y}^%N4_wPu}Kqudk-Y(CTQ4zb1`6RS`~298DuVUeDQ z_;-60tyDZLz4te={uRiInIh%I5{~~Fe35(<4{miKqk^q3k&A6j4wyGQ4jg!W4(W6y zY}T1s*SdDLvw=^i^BqWsZ5vCS3fdjVa{44RtKH8obvze8*v}70SYl*rqa8k2KkE;S zJ=zL!@BOZlO;|=OPbcBg0OMR7 z+d48{UfZ5lpKo8UAHOd=E@ONg#j6{68zk#dB&J1%;{O)4gm^b}LR!|7 zVKw9$F{OJ;s?x{o`lO0Y>MUa|RhGB(%N<6nLU3e6)w%2#-(-lUEVyek6*1fT`q0@; zDa7yQkN>TeoA`%A>hYK!`g;LfaPGO+&-+Y;G9!px;KqTwz^NLgKKvJHO;pwM7}Uu< z;h@*3asr|=n|&RJ7<4ZWIeV>RkBzBNPrqVRcF$XdZ#zWoSw$CcDJTwq33^ul1yCj) zrh&NO1o%Od*QiR7Q&UqwbV3mKF@q_n255Pj>~$NS1FFfYs+#4am*31Hc*Q{rRb5pp z`C(Wb?3yO+i6nJ54_S~kE(Tb)Nl z3s_{YX4*JncD3Cwk-HMi4ZP=+k)=|$(*K?6mSbXE>zz9*AgzifNB1vfYphZ=GRA8a z&Fj((ce_(<=F+BRUN3`#ulx=RD+Z%U9{e)G7M@J2mGxK*mT@~Xp z!E}D;;d8hBZN{TqAMxfG0_p(};9a47Fd@@zsAH#qU7-f@N}f8T1oz40tlNxo^xl;* zh*CqCdULi}c?jFriw9WM_rMj_{XUUE{AwCBry~%hW)*gm1wO7KtovQm~-V z>g>X7RKW`~sywUkzfj&(z~gZ%zRLmph^|CPxWU#^%y*^MbAI>Y!_;Z_CaVtVEFnTF zR51LwQ%WEuy%pp+rQOK$3Qg5AGKUnpFd={y;>FS&l!lN~aN1?Hy8j3-JQifL{KIwU z&nK?f7(Y$69Py`L7s{LEGorn>)-{?vc4~l#D$c6QW1^8i&k(=9ONATz{AyZ}1xBO# zHRXm#o*Oc721(NR!=gx$#14bmmCzBl|0ajW%&~{`aLjExr=r|VYmSTsIB(A|S2cW0 z|B5uf+X3JyW=C=q5>xus%udCG@)2zWkBFl1g&*(`up-vZxuBD101^XNw)$>4t()?by(|ZY=y4eykS(OkQnhU0JYPS%J5z_Grl`%w3K2&Kl)ma6__uxyO0; zYxi{Q8dk6%jKJhua7$WhE}ElUrZBgQwehpW2L$Ulh0G94ScfcCC*0=Flio>q;EhBP6D6ylk&YaN=-zQ=pPCQu5*QIq z5WElwclgE#|BQ?oerY#w_W5GlG~`wUKMLW}hd^az?yDB%bIDJaKzKGYLWp&(XqF(KE)~{#&MUw<8 zYsDIvpdB9A?R_STyVs@<^w+?aAGt8TASZi=OY8p>`m^GMCR5&j75p~=GyD0Z`facJ zzk`#Afb@po|NgAu|Gh5jk&t<N^)%Gn_44A^GlpEf_9pk~A z7Jgy}75XlUKiM&pe={raG{Oi3?wZS<>;apjkE?dFepwBc=M#?Zg26m~KijCpx7DzA1c9xQN$9}Zv0KQz#M3+<@_wkQ*=j+QN4o5!@1x@K@Wqe}%P5`eq z^I+|3rI8MHfHJZQKVE$zV&gVEA6$?*7H$!0b2sF?pG=Ls%CZr1v)FkVjF5S4Q}i9R zTWKCI=sJGl7LD5P7ys~7=!%fuvFy;fKI|P`V|@yUKTmbim?{E^eT3%?&+87#Xa2<% zBPG7wk6pUes=mE>Xdw>%Bd2XFkZR0sxMAuMzUUm@gS#UM7GGBRvU)p zb{8+rlYVS-3ZEfLs+4+KTNlfyPvwSQD{u@h%E#d0K0pj6Yoztlcg2)S5>LD z;YVFsbR=7N>&qO{M>xV+4~9)OMgt&i0tLI3W|?l$q_zXZiM0G?FptFLS=;&69qNhO|mduiJohHtz1@RDRp)~xn+$^Tv9}mj{!(2xmQ-ZSW&yE(pL_1h5yG7feoWR zm~6lx{MO%mGd~uCL?!H7hQ2z=wlNvyb>+Fy}%p^Pf3n}r9xQjoy zAl6g5^!T!7=A)kRZ;ZY>XRS3N3f~B!dD$%bY36GZaC!zJM-g?vsPeLXTeTm&G%Hs? zqHma`GY@SLoie1z=k+}2c*2d9r|=@{>m?V@6^DQITIft#n)iki+X>BNAt68y=kiB_ z%=ndwT6Nxdn(FK^_zn;zYW$Mp{_89d$UN-)8Wl(IUIAO&1rBDN=`5=l1QLrefVhfb zOOP4#qqGMX{dtR~O{oB^xS0HX_ShI8Vti-w$Ip^85(k-Ib$Bh(@D=5)F`^%}5Z4AK zVFkW3QvoTB-sELZ(9(H9MEyhV52jw^*{C4GF zHI6qETC93U<&@=Bq{zw`nrR&v$S1vXj3W>u7N;~FHGwDGJJgwWb&=@Fy*{_k>GK^h zSbU03rH+acIade;uCBUlJIMJ1YRWgeik#j6}lK)8KeaG96UnAM-)%ODq(xa@0btgOJaS zeKDC^YN5}_p5A!MXF$gSznSbJYq)OSBno~GwHddG?Z8&#OlTt3Hs6hz@`W8SUpf%3 z#V_7>g>njyTA0284H`c|)vUWr(pN>dP3rF*ucH|SFSD?XC^Js4J)cI|hCr@GNJ9O7 z0QZ>GeX6^dF@V{>Ey7;3nm_s(DH_~izP>ZEZMOIvb3t{gx%GD7p$F;Co4;rDFm8_u zUIHa7Kt0IlZij2nDc*NhWsO+6YM+H4t4Br5m`JE$gih>F-^sPPd{AB`XTF!c84(lB zzz4H{L&7JLqv#u6S)WCO!%0iBNSKC~((OweI@%zt(((iDW)#CvVLw#gtM2Qo7q#Y? z`NKhx*v6vu)&-HxFmKjo^dikk<15Q&HY4`o_)@*xT}7}nmT#Pdn73LTiej)%B_}=Q~(l>(VjjqLxFVxe-kl@df`|d zp|eg*`1x%vN2LCG2zOCMu)f9!VLzfNMl z-HgA6WP3jeiaz8zO_mJUx%>rxr9@-AP(78jN*U@i!%n$kjJ%}-r92Cmv2E;!VkiIN zpiENHmUC*=AMOrN=fjhVOG1$ZauL_t$p++w5Wa8|$9saJZy5GRFQA5+o2jH4{9OgX ztK5|PVz6iUHb`zhAPHrRN^4Q|&S0{%4#o~`8&B88D&d+#t$BIPzAQH30fx^KxmS@YHP zyofhZmm$kv>sQX5T7`eUn)pdScEp^oSdd9WzrQ7E-6BLYz1q4 z%~&j_e2gZW{?&e~`z1Vo@n`t-H0=-0aF&7YuDVaEvSslrA1daPFkh~RpbbcyEH-Se z24CMh8qSq-r?tvG+`;fpuopk9okz;ByE6&sDnVF@RW_gBKW3hFnsK3-zYll4IP%;z zr@en%AUC<6BoO?NqO>rH)fwaI*lS$9Z7myfEQo)H=aU(dm9=>%rDgBTKygDVvUj3; zXE(<*eVuoH;xL13lxJ&p+Q=LzMtN+`ldhUZ0lIN8O=dwHts&P-!!gq~)=^~3W@XsD zaSpF5*;v9zp9N_W5V+qS;br+B{kE?;{?}(dGSRm829~)oGb)Fc)VN3avjKcs`{&}Yu_Du4h@MdUV(8joWI^uPxNV%#}%7)NETza z7a1l9h^Skpfzoeb%w(Q|l?ui*O~tsjBdpn2Kn4|FMp$Xg-hTlDCAL(BA$G!_@61$l zww&{GB}3W+&ojX0OFTt`3K`aGRFr3Z4r3Vf56JEc{tg*cN>R!SqFgUS?GGZW3EK>a zL_1B1Y!!z-?U-m4G^203+ngxc{CQFAayllip`1CgXBw^2S#Zt=oLcJ3SHhAf#vL!l7xUx1DW3t-zt8oOgux!7kLvu+Ry%#DN7TsI26|dO%1F#a5C9=S`N3TL<3? zCs$`Jj)+|p0WGa-a#lK^t2p=;h25MyfS6E~vqYL*=}5(311o&^sbCqC5&>Qw)d3YNG6k?{%;6 zSPM=;s&cEP0PlagxG?Zl42Hlj+mdzhsbj00Fax6-nc7AAnCXX~~ zlm^pN^+?vZtGTZuzA}v1$MlB$psD%QRJg!-cQ#U=_WR35ABWzE>hG{BKsbMLs9tK+HIJwGu%%n~}^zWWylf64FS>Ig)i{})pSTAmm zX6q#99O17jB0Xab6%74QWZckmSfN!r{EEsjElk_?U}eMnwSu+Crhg#K&8{~!5$34h z79b*nI!>li8!OEW=T(XThJSxlnrL=n$lqwf|GpKf}d1$+axWi!+4 zWZO`>&12y#Z`rT@dOyb*(2tJ$YR(sK*A%}j`ry(vR$h zutGwgwFo_djURjD4U+)(o~kJk4A;^v2{ik}Dj(dspSW-wR0yfh(HwsyzHMdHv=5(t zsz7HoV_T;n9XgSfy7PvQBRTA!{aU9o!5_gPxtYIz;f@20Yfq7G^}X5*5q(KBgVT=>u-S+FEDIWjHvH9Y|iwS74Xh18ubR7+k7&sO~$k35tF_~OMd7m zwzyW66V&lH7l-V@Rj6aFA#eIo8qlBPrHd~7gd`;YQCP$Yi6k!D! z^B4u?a};1CS-A4YX6?EY##&^HAKvZ$@II6Vi9r` z96OfJlm&D5H15S-xv?2EuvtSMeP?Sb;v}{%((7@yv8IX9sr0G-soEU6O-JLQ2^MiM zMb1`&^rjH%hXBb=4mNKZVWfTn0)qIxc$zl%7%c7JqsBRvvgQCaj}qMG>r~04(z1_m zj182PkMGI&b6JUU_r%PYk?1kF_hAHwwVXBV*a0Y(O~ps{^l_7$dH~m_VQLR29WM-p zrZY^QzL*mVljunH*UXV~FX*_-(>F(sBCc2))}H&&AXhfn4<-=d(s5N{ zH)Hf6Ylg`>Fhn8O;zqY*qar@=o#Zfl?O zHYU$CyyzU9fLJ)!SYwd}`tRs&(B22b-$Jfo_2Jo(|L(~au7VFuzYc{cF(hQJPlP92 zcEp%b)pLdGYX(Yf-Y=8|v3@!!kmS!a=6KgNj-SG+q^eZ3!}l(_dCBFEl~skS?oZgC zn;@49NjE#$+%YgW(Hu>qes1p%Ubj?kI2cc z$a;e~_^~(Gq1?x>!a^|W`#hC~I>Ozq_cUbymSECZ{hI{PkO1gYH&=Jb8=R++W}ihv z^W}#0Jy6()`0fP3O_bUK1QdRyB!G4Bk4+0rLHnT%BNWPz`GE6bS|9WeW*;W!15dWjnDS-o|cx`2}Dr?+@+ z4XzI^`9Z*^hGh`o>_^BC&3xMSnYrH9P`oi*c(>=&iv9I&4*6&$>c3(gGZBqH8 zvlJ!Ld&k7%ufX!+>YJP78Q*kxXk<7BNYKDg2qSx+;`!h14M%o|@j#>27>v-C;vu}s_U89w_w7Oo)CJ*lDB z^pxOr_w&a?tRWsGsLWdF2cP#e!M_XRFZrw-02`kBzbHo7BeaH(@yO*QXAn}V@BP9) zq@JC_r3JoL-6!8jL2EnoPV)|lxr0sZxRJiiW{VJ5F0IxWFuZtNRF>=$VTrNIq5S+~ zhuuA*xT`(`_kqhnXv2Gob#jEuhp8oB=00!yKYaHqaNrW;wq?&M!jM;?OAgbW0ic}Iz=aBK(a%k5(P7d z^U|YM?{wVI)eJ-xI6BA;q>}q z_oi|h>(YBqPhXWVtRdXqwKGC3g1o}@B0sD-?eLzQbwjl*1Pa%MrSTiFYzRT4pY^Nc zV(hL^{0nvL68@)sj%-CJQw}(2;u;SUSWU4rx<=nc@Jlsr^47`Q6-|f(fYGR@bl3C| z@bIZ4)HA1))0i^ZB#tL>wikYkSpttyLPR> zH}*t3pJP$zCdKQd-%G;!Q^@&?y+Gy`wBG#66}~X4Ms=ue^Hhlhk@;()AfIO=QU$DU ztwa>*i4idoY|LG2i1QZ{91;MR5@4Zr(;CvwBu0DJ^l&aiSn)J4Ywx}BkPYYoC5OjGoztqi5CbfcXM{20{0T@q3 zbt71_uanviH;qlCnG~zj?-wD*}gtRtLLfX z2llJY7$I4_zEMT<7nA~#ixijzF>8+~*|o?%UM&p^w^z4fAZ zl(_vFzFMbrvNtJhBc5zI$xQvwAdPwSZ^zsfjVYiSRqjk97)_5O^$RhME2t)yv*XhLPH>|yHHlC2SfmjzkK%XQsP^PEBny}-j6mJ9ctYFSa zsbq-z5!nHCcZ1fJ1fKHXdpOz@0;PfKx0Js|0w|QVfQ@%pf*B_z}Z`{xrs?1(qX z*=;?VT;)KZk}UU>om7m@9m%rZXyIlmhLC8J>c84xUV*7BdXK(I-&1d+uGCKzO0>>I zAuIIQ4+@Ue%AGX%+gTaAKF`ahHQb_|HvBBR2#oeK=`+p#a$j^IeGSr` z!xKf!*V!LjM;)Kp7Dfczj4O}X2mRSRhJYTVn-gI{$ZHP(lZ{MlO8Q&Y18^RuH03YN zIC8{_4R|c|Tls->4}mSx8sP+wg$r`)0B<8|aM1DwH#0m4e@&36Ue8wH2P6e>&}flP z2UO%dZO%=lK9f0TB*d*H(lSk0nfQ92+|q@fy7Njd z%*3BzmX-M0LMPKsz0z$YVhef!Ep%gk$~)N-1|09U9rs{^*~yGW@W!!Kj34M>@0BCq zmy=LG!o%M<+=?6q&mm~dzx%cD)sIueB@l4Yy_!j;WDeTUi8adnN)f-Cnune8J_=nD zZVUg^q5+Z50mg{kesSj$TZlhi9DM((qRcek#q|D^mz|?GccPcQge0pVZ z20clbR%+AWhx!j6#GWKV%a}XxUIyN64)}b!`jz-57c%`LtTX8dg`L{4U37m0!Csz* zBN?waF*BAK3HzDECj1KpW)t~bR0X<-NqL;qit%YeKE#z`?`K zNL4TO3?3W@<}x{=6Km{9S?q_8la{;vNj<>?J)v_QZU@AkoB6g@&idtaE8F=oqOXhV zFgEY~b_~pDXb16f{eSZ_ok@mroh0!ohWzdF{N?Q4?`m$@@TvFKGvr?MfmTU*47NEj zg7pzJ{_^wodW+k|#drVB5eW?V6_Xd#eA8q>e@OWl?Ee|y1Jc2Y3NZ3iFw-{Ukv)pR z{2?9{L^&xLAO`W5X!t9iXhrea2=cg1vE|PGEDaJ4jG~{@!695U8oQ5D{KwtD zTJyc%rYpix7hqUTJ|}usW~^7;aNZ0*K|teLm>dN^W@}Kz+d=j%BdxkX#OxwWOkXNG zwCpOEmfMEGMAETcKaMx0{!$pXJ6U-|AO3Lw_u;cY1+SlxE%M;ldMkrGnf?7cA7vu= z$CHjV)6?Lsr}^1rP1fMC$j-#QDs5D|~Ful9E4d2ch50g-e3(mj`;tF@`{ zjj-6}4LW2y7~I)F@dPQ-Tt^4`gv?Qtdrw1&&qU?Lh3{(jJD+>>Fd~Zv+6R^!uOE+} z88-WmAO6{QI4lMHy%!Vl(G|v7w{FS?Z&}@J>T#vUD#!M+7dbq=dx5d5U&0( ziD#S6ZS*TgDNvZm&Sa{SIKolKh(Gl^IqABKzDYf-ivuHntbT9Q&j0j9Jpr|TkrY-$ zjp(N?s%MIlT#oaQv?@ui#qE6>Y&C)m6E6M`%PTq8Qw}ka%1S9|{-mNJ8ius&C13_Enuh2^%%XOZaAsD&ePflB$W$owgGda|{2fYGCRx zCy!rl>n{SYo1zc+N=m;MoXKG=A~e+6S!T|>&tnf|Np!&W8g#h#^I*1{-2o~Ot&oC2_k z_ywe<>u$X%AP=4;_0AzR9U$azV9>d%f=9Ht$?Xu4{BEWTI#l$=g!c7x2xV=0=>L(< zoA$r^-4lXr!t;TXOnWY5*m8w6&i2MP`E-`}CU-aT)iY{E_OXCNFlczkcYnHdaFhI0 z0>Pm9#*uc}r(I@V3S7F)FRSyZ^5E7>Rw>l0HH?Vtj|@LJpsiGr+%?>K+zbOWGOembwj8Iu0X#Zu+5Y3lhb2?*(e{2RsPntsy!w zJ+bgSOA2AlwVxXFzJ6JilWLk}k*v4&4y-!eAf|s3U*=huh2=;XKDQbv*^OWewMDz< z0H=wDBtyl^A&xs++kM*In{#Qsv)EDb)pX#141&2B_(JlKc+em+b(CZ*P}H z-NBk9dp^JC>$lhu_T->Jze!t`vYjC=u2Y=I3p<_8an8F)~4IFX^klTVot zf3mlZr`v~+$!(E7RU&`_5oMHnrEjzJjvw=}`$Yuu$E{4v(|r%#7l%;iJa=2Z)*Zo3 zM8?~uFC%1g3Gc?ku+z6Y9NHBqwefy2UECqB1TQQ_v7-WDFW3ZOm1_z2O<|Z_1pt!v z>~@Dgt~~McxEaay`2_T&zc%xXYkVj7HW>H&`{RW->r@XAzNP2;$PNh{2XP4Qzj3EB zk{pk&rLXym!Sm^K(TOZKoeS_+{d94pOw%R>rwa8eN|@cHx0O&7!$a{&v{G%o+T^&2 zQopF}Tk#h~C*XxUf)1yM^iTMB541}3&qPqHE!G|t1&%?Fu#OEGwQyC0PGSQ(c6N@V z6#e*Hv8H9OYG!W!iT4s9M=34N0VJ$!Ov}(p`pmgN10G`$|CF+{`A^=YZlHs!UK|fx zM!$US(VKu9!cJsEQ$V(iV`SgY9*c{|q2OhR{IBc-jrT;Djngs$ZB=}I+C@(szI5L7 z#q-o`DsxLffCt$=Xprs#68zT7E$?NMy`*v?+;g@Of?v$@N`p0dP^Jdz!$zzP$mHiBXy^^KWW-dHr1JFBU`FM zcb2$1s1|uWsD2%PdwP3}i247wmj=;dow|v2887xtuvXUM%^Id=IrEBnc3f^nMF5pm zbV7pKzaLKQ3Zp+Phs)eeje}mZl$g|;g0A(|50bV{192$Bo5P0ryTl35Kj=8f_3gaH zbnqTG(hiOFc7~GPiR`bmoK+rK4JV@YY#9Zx{d^e8nL)523^pQ(HQ0HR$XNtG*Go=< zDbV}_7_`8WgJAN(vyXMwf9|u4F;j^~Fs(!J;!@44$d%PI+s217iHLf`@vI-dGpAgs zQPEfoeHVJ)_mOtaiZcP_iqRPxK~a12iK{{6I2tNI@>qv6k{h2+y0nO^gkNA{#-`(R zF&9jG{f_#b`)ljnspswXW4sKMpsl3GpnRrFmUbpQYVv%0ri)no%-^{NKbKXbTf0nz z;%obNmoA(#Wy;jQe=!JtcEf4-IY#GOuyN%o)X@fzu0e^p)~sJ>{4Y{8 zH%rDQ2MejPzpOl6bDDMjNO}18`noN7y-ChVS2&$~cgs^_b3E_2B@Ys@>@>s?!5@k3 zTGgxi9dFWLJ?^pcdu<=Hwx2iO4$pkITYXJRzU5W8I%xg-Dl>=CJPan~!b^(uiv+Sa zA^U_RoZ^pXi#E&pz!t82qHh+KY$3)*pIZk{!jQN5w(R*}$&+a$!jj+TektL3-HSm33d{s%vz)j76Q)BM7VBJ1Dnwg5$Ary!iRGsMi0?x~ za@dMBHiF4ZF@UfEo4_EK$EpaJ4Qbi%9?7GtG-a=pmwL13y4LzFuN_#G7_<&gptsel2i)#5!U=>qq;$)zhSDwd z31_~9A_v^_!T`xDa!FDYOF}V7KJo!D7v*4FX(BsoqyJb_HeTe)-Q`#BlM^Wm3z4^* zOTT5UauZ+6(uTVbD%*$D`q)siNyYdR z^Nah=Hxl=|E83Dn@NbVhL?=)L0Y>MK zSGy#~K&HxBzS%P(et(^9H-Jq*u>Wv$Tz&B}-W7B1bM7UT7}R9L7X3aDsR(Va9yfz( zO%B`@CX>D$y+E`si5v?qgVNVHF@^`G`NL81WKgT`>F-lw8xs?;;WcE@QTB(*ySKT!aYg4eRfVZ4kQFwZhUpIgy+*3bW9Tc{8QcRb( zsp9sJSI=`cOfN{J@J*6b%Gp$GoiB@(r*jvHa;QT5FTu2==NkR4z4S4|5ibH6<^vu2u;Q!2NF9g2lBZq9?wI2e9BmqhvI)*RcyKwR z6(#u4Sh8k#W&64*?1*FUJ!}_=S`k|3hHy**{hNYvlTI;7?DiOM8b@X42yHlbld_hu0??mtqJ3f zVoFnihSJfr)zMbIMBkT`13PbFRLnZAR$MS!_WASPS8uUc_L>g)?jaP?mr=UtVRNRI zF1>M6o6bx_dfYCVTqnehHPFO9Eg3YRdcnUm{P%5BtYu&bOAg~BqX4k<&!L6RoUsy0 z1(=R}q##Lc(U87uw2*^{H@Z_Mhs|F>BtUA9W>+yIl4!+>NZv7$&(sfb$Xz=~NxfkM zA_Jw%o!CBdnD-oAleSfy@*b@^tZo!#bqX*YhtmDK!z^QB(Gi@kA0_aze~NG7M$Qg* z(yl#-xv~OqT{Hc88AP`gM-tx=A}G`rA0;0wR)v0dRz(Pm@}8Y-mw_>~$NTO+zGba| zEd6R_m?*i0hZS^xewzIesciWI>3hUY_;$)CSR_lX~ z6690AA5iV`xPMaK!}KPZV>ry+?%+{!D_)rjPa_*(0!0eW8HjdCk7GuO)jqDt(X?e{(=kWuMS**RkFGA-t4Mfdg| zM$fd~f?Zd4ZCWu!3szI#7D|F@#*{Ok9ZkGo(o80S5};UlOgU+dqaU^pEw7#Qz9p7kE>BmG6Z&Y1t*6U}M!2$&4 z-b)9yRk>X4UX(we!4T$V(9G)96Rn3o{+Vw1{lJU+U*NV~{kWij!1E)Z=h={l_uGA-XCO*F?9(P~-LynZ#cIMcXVWKki7H-T7XgLAK)wqPSTkq`M&-RN>wi6Ne z@(lm8m^Yc2oLEB<{ovl-)9)LyY8)~$!UU@^Z}o;?KI|RaU2gWu=)r&u?m~`_Ep&P3 zUh<1%CV>-@H|fk{FuTk#uiXXoUKG*>8-aVbBoQD~KyMt7{{v-P$t32dq{%6f6zE}E zhVEGQ1&WGC$5pF`y~3CGMO;K+oHcfxNhFj(K0HyDuPI1CxtBcvHC>g365U=*MiXaX zz)a~lMu`yl(w=%pcBr_tf}l(!9N!15H0i0&DC>6Vpqy?c$1aRmsQzo>eX!%39&Yi_ zc!*)Kldj_5c^h)hSmPnFK6!%-Puoue4t<;M4KwAGpct-rd?o?PY~YHXY4et-o1tws zMfNbcq||nXQzLn zT26X!DWCvx)6$+%OpXKxeyK_>jjS0*6{f8A#zBYTmW?z+CiA;#hc1hw13Q>Wa-@0 zp{TYB^CT3XrAF-!a)k5M(F2s6@RO}0L{04iE4TU9ncz0MNhTj8F5c%@FHI)D1Q}uLzh~5nrMZeyQ<@gG zE6!f{$)duqdR%@OVHpQi1Zh3UQBsw+tag&KVs^7u^`4HDhz?=gd3C1GBYco@Ii(o9 zDd@)RDtfoNTA3R_@#oyfOX2mxC+Sr(u_13#<(-eWMrFzU>F#aZ;qPG|y<6?CFQWJy zV$R}Nfa3FmYj$Lo6hhd7m-JItEJDu>So`TZ7b8Y7cVX0>|+&8-psaKmV;0<(J;6&3BvSoH%%o z$7rSQFk%lwh@Z|x^D`B0)J_cGc~trJ(eQQI@0#Fk%dXQqy!&4Le@07kc|{qCa)0t2 zMTqTnKGw3|zks9+cQ9(Fwk2k+cqDpjmDK$0!4tY*$D?AL1e4%jKK)tPuh&mr5}pDV z=EtgLXF~n;Tv!@V-#YGa<{%f&+0vd?bwSedGaE{cv$tB(4(7%G%>vwRccQ2pRN@Ac z4pq-N&xld49}TIn8qH@X)tu8{|4^hgRHITtRC$j~C1Grw!z^E-6!b$Th*)TE_2a;1 z78Bjb@jO$FHKxd&MB`#xE`JQ7cdNB_ZWTxWU-)4ge~-H+B=lZypUR}R==&wU)zg=2 zojHJajK)!7@BAv#%Fl!)+M`Iyyc!S+;9TNJ+9;?D9rUzuyiR*+VZ&=dQ>Q@{-CydUufhikOsJdyC-4Taf=-d{yXyTR=c)Un2QU| zXC0n80=Xf81=RiP&|G zuB5fs=vWu%duovzzqyA-3fHoL&qX@@UZp{OU%K(NTeP9G#i5s~nhu0zF<4lWuZ zl{r$eNDIznW6whYZl8h6tJh54F5#ZanMmEdNHLH=jmX_*r1W73NYM>kk>7X)jqxVt zFYrYb#Ud@*(0O3&zt=6=HSa6@|GZoVK3AZZdV&LG3v1tq3X^ zQWCY1kB%==m410N?PNI5;IK%2LXp?TBR#LTh>M@9FPNmc3kj4GLj*U49qF zVm?Q&{KiS;94}^ISu4NZ1N!tutGkTtt4I2Fl@Jo}wk}i)WBzm2Ig5FZ0 zC)_VO!xJfS>@(>68oLC7sFzA$m$%UjUrQ49Cw!tqD+k!IkM{>%cRL##!ZNJWCs zoP?>oBRE@G+0A#wo20>TSX7)p5Od}F&J#XAv7yLBO>}>rkzr)e2@#)sp9&VEds1vxk(5q3{L6K=HiHIKLqoQ8r1w~tXT5<=%(yBXkef!`|z zxUY$DSKnjo?QkxSt2B*X^OJ2miaK2_F8NwLZot_k`Tcm(I1^)6;!UNg@6;0xsZ(Zn z9ksjh?sf*}ynZ3@m@Xb>zR5I8GdMDgCeEN)K%`H2baUDZeRf-}%l2gHwIW^)&G6)% zhxoM~Y}ei4AzKj5+)QK)r*f(oHzgdl%@pgB;#wobF8nqU-tA%^_HT>Dyeu4&S^HPl z40m?BPjC1-3M21!Jv0;i|H}iNNZFSv;O>#8Sf;$Pm*<|9|*K|O}@FyM|xa%iH9 zrt`ukospx0A*zo8PSH*~l^h?XD!!6^ojsqGoio6Y;aRZ`5{Y=GjpkGI>k<1b@~7_< z-+VplS>cvJ^bz{PO<@d>`;F;z?P7T0sRUaa@K=o7R~mLPZPZl7e56&_vIoRz=5=Xw$p{ApW~{5yO6iT17J(w9&=Y>n$X4n!Z#Uz`@C7ndlc zR)=hR1fF(T;6m4dT7HKYh$b9kWj8ouBgNo5!(1T4SUA7uJHaFjrYUmhVRJkh;)+D> zH7y+=9E4CxD6Xb_-Quc+eHR}RWp%iRY1*xABsAMy9*vS@bofS1?~m8=3rj7#AS0ZF z(5#)aI{3PTjjUp{y?H8Q{afV#gZ{z{72ZRXGK~?R#&!3K>-kwTycgy0QH4dvtq()# zl^TySYL`Iq2byLtIIF#ZgdYJZZdVENUPokMjlJ2S9IIGF=TjZXbHN;S8C9x?O{cV5 zhkS#ijm%0)JfMYW_8${@@I+RESbB89l$3=>8(TOvG$TKkemI=9ScooK%7cs$usMu2 zJUh!=>8kP-M$1fk8VJqDt#pr(Nj%oL9Y=+z*YylhHUj?)dKG{%gqi+b$(0(WkWJ{% zl(pjQ$|iz+tlqc8@Z+TgJbs@D zrSBNQpCV4-7zhRy#L>KYQm${t(p+jwiX2YcliCZ}e_W&E0b!hYfr@OUSYT_l$Ie6( zp7bb5Q*{Bi$+6hxMh}pHIeiHX-$L^XE%W|ez2HZmfKP>-i1)%!SuZEb z>^6*OzurCDD!dPGn3oh7{$;Bw^BUl#>FC`C_&p3H+soeVP0f&;V!C^0>Z`rjYwl?& z+~vsM!oGX1Cbgd;rE-0pWEm1U@P$o#F-zi%bxpB9?e3=f=?~B-DA;_Wa z`x3V0@5vv(7Hu6aKJRm*_i$iB1Vr^B9~hDDuAaWA&@fa}orPei)MOV%sJG#Bpxw$S+OQy0Hd4_OMH2oz6n1!T$ z{S7U*-o?)Q?=||aKQW^)?lvxounIPRU8XcLTKrf20}dJ9Q6sO8@iiL(c8XBzHjoWX zT*9vBG#7I0XG3buBme1kib3+ZKcW7J$n5q(S4HAtB{%d$F$nxxv~hRgH-}K8tTBjk z=fhCf^N8O)!P|aJ*YjnU4(ZAN86*EK$dU_I3e29i1(bopi+*#dVYVRiieIz^a101>2g%I;x6wd(^7V zV{N1GD9)XvaISY_O2*7WeM$=;X3_I^K+X`w+qFe_Yx*0e{+w?rb$^E$x8@tT|rl&IQ&0i)bd3HuPYKFXyck#WxaC)z@p17y@m+~x_!jHd{6>d4*^&nLx z^RKq}oDtMkoP=nR6?4CK2>Dt+#4K8D(1|iGkHrX<_pC+U3)l<$u!n+l!Pu|XUimLPXB+i+DgS0Dz8*l30 zheo3pr=pxHM}vofm=Nk!{pqGDo@nVcH?r)CyD@Sy5@^PCQehpXp*HXDT}$%o+uPh5 zH9^v9R%`3U#&MzwpU?Zz$%0p2l_H7J;Y(Cs1-VZyxn%~>*VEVV@Rxj|M6~9QZ~ra% zw|e`v#QZO&-ZH4I23i{pF2&uwIK^FyyE{cn(c-RwAT91L1&UML-QB%Gio3f*`0}1R z=g#?+f0@Z-&t7XiT0Lvs8YqO+AygGHZ^-qF-bG*0P(je0P^#u&>rez9Ilj7)cPTVH z9eL74QV0$05I27Of2v00PCbRuhG|R6$Yb-q;z;Dqk$1<@OOkw{D_^4WByXEU;j=FB zemdrbhE9fgZM;yd10jMYT|OaaqfFtTwSc(sH~dc+!l$uFWItiTXyts`JN|9${E$6< z0hO=C(*A})PBg(CNsv&RR)xkEk#@Y?l6SqoLAw-Azyg8^@&>g`hX4vj0wSv2yNmC9 z*00tm$Vm)sh_`!BY-Ifw<$p?tY4&w`vOY@W3LOXAX(>{Sq=9HW3KI=bHksyFB?YsZ z479jn(+9Q+B`j!gOoYs`Wg|2R(X%W4JMxZrGQKI%?v+W24xx^eJR6VfRCz3K^oHOG z?7-g~sn3<&F3PozVE8{Ryo7WKce9riyU!jl4_7yjPuL8|3EcFEDel{|JvaBH)w%KN zYuA`{TT`_PNxF592?@Z-x#tyS`}$P$_=<65A)Q^RA*QO%hi(aEe(9N>hVdsxqkXA0 z72GACK$RW6QGmXF7O~5j#xjd1+co1 z+DGikbFh2yzIW9=;qFnhJ={&f5AC^>F6X3Iqj6#I5hk}-Wq135|BA4R-1%z$OYw?{ z)WqvFzklOe{)BP06N1sWI*{6;tMKk5GwlPYm*&=&(N_AgqUh>p@U*)Ld4^C~ltkVp z?RLsFCP1l3xFF`cY2ohKRA2l+N#5IE9}Un~8s__m?CWK)@u(T~gYhaXSp0fYLa^#i zY*XpntH!5+Gx@gFAe807^*u+Z^IHP_YG--sQ`%o!l;D>H})cOwkEXrkvn;oduV8LV2Sj)uRKcBYVKUapbxKF5~T!^zF*pn+@*wL>Zv5n3-?@yq!lITPis>Y zJ3L)G1zsP#L!e#5nB9*@TJT-}I~KZ0_I!^Xz!eQ=_i=nB>;a+0Fa0jN+FZ*Ro2q0m zs%D@wW6rQ;0^@2d-(_0UQY`D?J!dfUz2^J=-FlwDM!U&dAsOj8^sE(sCJK{y>r8u>FKs$@y`oh!01px@v7W+PsH2G z&cok#a6gJ(2|Km7RZuo>T&K>M>!2fvqB*^*@yT;I~PB%+C+~#FV`rn zaqEqGPZ;TTdHO7G3pxrAT;P9fCoa}&_pbqf7OF8>D}Jlboxl0QE2?Fk-+>Z6TQ$RB zn3T=|QyR|#mivN3F4@H9FnJEbx99QGP173L+Scl#dA8pFI;4u+x7mm~K6J{SUzHt% zfBsk?Ln30s5& zE4N$o(^#7AlkZ)+pOi=7V(c-Y(oxB~_Kw-JRv7`?p;J*uI_5y~S<5(L8B0jH%Uz3u z-Q-tIVF_11Ju;$u|1ziP<4W@FR_aUif=$~Lx;ng)CT)q_;~$x0a`VXsnH+Gc7G}{$ zaqv9ww^|Y`;~|<*82}VOW1p&RZ|hqO2h)Jd(|0ta=7PU z%D}Dr--U5|3t)V#kg+G$JD=ZeeN)>Ybc8j_U#7pJ2wW~OKw<^zV@K@x0=NW+MklvS zX0|vhET=dMfG==Aze+16&3vK7#-zrWA^R~(=1y=Ik3hI4jK^Ah&+I2l_6?CSK9|?* z$FlH3XVpDcJ99!~WB?1mq0Yv9zoA0&IVo)iGALfWQYB_n4 zvKmII^{i~XgX9$b-sgaS6vS}=fF(R0oF-8qF?XKR*iBOL=-lCV5=TT{dbl+-Im!g5 zI_^oO_1{7En+TkNfsO|7%P}r zBa3IXy1#s6>vGr=K$pk?r>-QN4aVZ)=ruH)(f+)lI-qfBo?8F-6NgntHrBA7CDHU? zeX5jqYy;OauQKj60|qG4Q|2vxEv7Z=tMD*-Cbxa)buB5n(S-@A|D?U9rwB~eLM80r ziUXEPz-oAdiXb08bvo*AV$xqEUn>oIM0tpHch?;tKAE_M_02BQ1Zo1zAyuk!`4I6GphplWF%V#N!;zNz z)`Do3$|+|pueGPS2{Z3L$L-g>a|JPOtQ0#ADxx_~iT;Z3P`#wY5jR%+U?ZMiUS`K*ktn@PZdwbd1Me*ajG_PIzY8duVE*9b; zs=cF5)M0hflr0STC}*!_xTTjc3L0b4H_40)ff?;Gg}vS5toM?R?URFcE%+_v;IO&o z-pL>*{OjPF+-)cWTvOvwTKZ(hQ`OCId?hLI2YnnOUNfi%iZ}eA))uddxO}y2op|~p zI=$B=xN2HQMID&B)7veF6p+IA_a%Mm!%@pO`sruQ=mevUfG@8P8bg{|Ybzcl)w1tp zJ7o{S^~^lx?2+hl-yF?%^SHCt{U;qxxcZM^bW-H@n-^E7HJM;qHeG$Y_*a?(1g%%Y%S86c%`rg96&z6)OGMNjX(IJJraz-~VmD z-|iBXs+boyK8Jc5cUP_yP*67R73gDKbQOgX2Fm+0h&J^#2AQX8!KUnse0AcGi>P zv|FH`!S8b}jW%T>l?$H2|EMgV@7^D}e5fj)qFBYeN*zdW9CCZ$3pB4Z3U`(~p-uLo zD;rk0LJChTb3cdpEztZdeA!M4Xab0_btSg*{zIcGOt-?DVWhIRmox)P~`w(H{+$t)XSb z>6R>fA;zMtHiwKL{<{V?`*ho{MtvOV4I||THCD4c>(mT7aNn$Z{;TUR|1!&8Tcm?D z7TJq^+=FuCC0b~+i}Q#0U9tT;!|3zl;mE;NYn6WYuWUV{u|@;Fpz9;_{4WXr^d^TZ z_qoTrU-cx=_uE-O(;EjWef=CzkCP&aFoFWSS-WVjRsG-z*r{d}S{`t%Npr`EeBdmQ z?#6<>C4kn_)|QwwM{*>a@A1$HbI6q*2lXGPMDSO%UD22c_GOafk6KvAoXJ@`EZVy zaH&|686pm9l3yxRAo|cUvREZ}cj|3;DD?`3w|ehy@v1kvdYwhKkGEm<($b(myf2`6 z*jd1Ah4OP4jP0hpeVG;&<$IxRABQTDr?B!4sQ(<5QmkWm1G2WUH5vDg=(GWhY|ah% zNytuY18yu?!XWpYgduccKTZ5aPW|zgbJJper$&6!TYzZhP$1d{)|m{-|9>$Pq2N4y zXnDMZx#)f($n5||dHu)2M5Qg|yCaAUuRepEN#P z1ADi`tiyKNi5h%m8}`BMXTsRESY=^h0`l)Bs(O?`8j?s@t(G}7A+Y}lPl{J*V{B*^jNHiDDgPlnS$}UFqx3y^2 zlx^3|)N}jw4;MSqC0HoLp)}--RNlYypGT3jY6M14_Q(t;W@|(cEXk$58BQV$zNZo_ zTq`kSu~0|U6kd83-aba++dsjnj618R-|(^8>TDl1WE{7npqfj%>&`wY480 znNF3TY9%_F2iw@4{h9InONwQ7#$ySBDkv>5u`fPzCSR1@k&+{wlp7~CxAOM6M(uHiE_jbj1lqLw}!Clv1*LtErIKIEsSHpB+++6!5c#i z?cnPKb-R`?;sUghXj;%wc&-Al8G~soFS(^naNnI*4`HI|UsBsK9Fk8|Si;sw5J$#W z?VR0^v5e*JTcrV`Vp5?BcSMwx{)*}DrZWKuduuR1)(;MJ{zi5^oH#+wr{9m?U%bR$ zkJJL6@q#YO{+pIiCa2ossS)w|?QP?^QvA91{jnQz=$HFW80hWc5%Crf_8%DweG7Su z;C=e3|G!#*%jqr9nq%1b2UQPVG&zN&{v$e!Fu0#CBau!eCF4#Z zAZx^+O$RhJHC7QHrA|&O-Jiik49*(YchOqoD{mh8x#S0%tgH1Iky9U^Vf9>B9zAc7 z_st&-q*#Y6SwfQF>8$@v`b&P;F7HuwMY$Wen_~BDUxKYozzopm(rF<5-$iJddCRp)@B| z%DcoGoXAG#7 zBlO!PWB$<}DUU&RN6;D;goXwXpg=l(kP|Ci;IU~ZU|40#`St7fMSGvZ?yo{SjHA;m zt>>GDCW-MoSC81^iH~2BX)jLUSYy7%Iw$OznF2jGpB`9~@kOlz0*k~oe2lAS=R8_m zn6u9QOy7!trT%7oL@^!1I5>G4zJ6q1%f;+?x;MexEFbKha9g03rc#$e=B%mDzxeSf z&Q%{X&sI_%MQenqcDeQVWE7jH0SSqYOiEIzhaSP+JVdNv>A%NLv^Pqx+Bv>qxxJhP z3M!I$B9T>l5`FSS9>xw2U2rz6Os8owj-zAxQM^Wxwi6DO;KfmjZI_q=f24^&ajtg( z!=}aF#Z0<<`@I3_7!=;LG$nI3~3z<8hohxKA?+QuW z&v09eFDxQws2ziGsrsJVN@aqN!o=xfwjbX15N*;~6G6RFA2J ztv|MtJdFl8@hVX2!C^e1)-YlS+z5Tp-st6!&)Zcs51F9_e@0+HV^D!Huj@z;SzlqO zKK|Z&MmPB5VGf12a*Q#25mPPcN_xH!S_N0QrloZFgdI+Tv}9t#R1=|vGohr(e1yER zi_e*BJJGGx1(OAZK~@_P_chiOmmP58)_9E0u?5wqFkZ=F;(8-z$OE0ZCeP(0@@$?2 zeL)7n6&lJxa7}V`5%uXiMKIEo)ryW$RS^L_7m!O_s08V({BG@zZG7{3QoCzW0Yq}>|iFi`^0vLNkkVMs%t7L6QbaTy1L`TwXXZ8(7Gb57FDW8ukh z@sVT@bmEdb)NRQ6iz+a3JHL99_SjTx*tJiTj6HU4pN-R?~d!k1*) z@#VO!RlmV%PnYEBQ)FW1GW=KNGNSpRp9vmD7`JoKyka#>Q+qzr8_XM+sBkRO-*6Fy zLNF*_x+#36%uR9-V>Zj%W-Xqho)QbjPU8<3l&4>T#o}LE26MA*YoF5mwn(9`R9HH3YFY+bzdQogIbkH140y6-RpACMGON5uRf*`Iy;vFCdj7KVe= zvN49?Fv3JJUPPgz6siTgZ)f>Wj(dIGmu=VY%o9cu;|nYEql1q{5GLFghXFpl1D0!W zAiDOtjA5#dO5Vm?njQObX|^Z$#;UzHDvkXLT7PG+)|5K+=fY35w{bb|!fj6t?%0Nk4zRn_)Rze}@%2mi2>jc5h|Tc2737DWf?zP**V>;HjmW+{gXC1Mn%o8xAN zBj|-Q8o5<$+;$Da4~Z836QEcG zx>5NU=mr_OjpLez8IAkGEVe}U@^92&xa->_ygcl?YIXXMjXgUV{XOX9S+ZKGeq4;X zU_l==jFUNRpRdyI`t`4SOaZL9Qr%RQU+~=4+01oXDe5)v=bmq6o{*%58nOWg-g|=q z7X3^97f?B*`_RDssCW1Lka#jR24B{%iRr$8{fuMjESE0o^#P(kdlGZKNUn7Bc%vF- zkBkAcWbbhQnAfgWYS(9H>Izx`s&$!OCpZb3B{H1A7+ft0pi)d(lT{F0lK z6Y1E4abI<@R4SyfGRo`gb$ya3^>Kr8)beD^{YWhCND0TJv zqV4Ue^<+<#O#$uIt(C3i0-VdAVfxdxak;VIPNvo1#H-8X?88*=>4_2UdqrwKdH!^S zl!Wahi22jrUmll3Q4bCz!N+3NY%D>;tYDjP0mOHhP|wU7Vx(K-L)wzWb2Zf&M?L{T z;eP1QbL<|5d=Gou!~a<>TD%4`pGUO@ue=$qL$VCQnY#)vw;h1O(}Pcf|E(iVT~8zz zVsB`2F4bjV7FuZwhaX*j*6i$YPnIvp=p=UBdi(l)VZEt zcj)4>4kcwiryPVRN>FM@BctFE(y$gGE278KQ%Q#wx&wAdgNL1cE%tHOtIR5SEfi$J z@6k}Zies%k_T|ztIYMgaqtkaUY+NlDpdJ;Ci}pFJUzw3*OwP)I)05}~t^LtNb)Na& z@VJ&{NUQ1tv-B9yHjm72dXci#QPgJkA4QEaBf|}T-0A^nuJunICuwd!jy+dY>47OQ z-DkuuNz^uNJS6DMkv@*dSd3PNZ;woX;_C*8X79+cKuj^|#n@*9e&@CT#P0PXa;=5< zTpYNmGZtwyL>fAzC58PSYZ9z>>fMXvUaK7T)pMEr*5c%#{%da4QwyCH6l!F~YTl=O z2P1b^XR~=H=Q_)F^OC$SRSc|KoF{1SuYZ1qeEw_5*F-#uM)%Uy(PaZr=v>NT;Cs8KwZ#XB_7b+y5k1=Ed!5Y0ru$#4K zcI{o1`I7D*z(A%QqVJ-DyBEwr+5wyqtb8`E9rAV0??^)k75TFuZ8;45c(u>E2)XpZ zvP{~-K5PsNyJoKwG8{V3)3%N$FbmJ*olANj#dr7w>{52R5pUhkav4LO(3Iu=@cV6| z{+Slxduki24;9)!-aV{9oCzhuLXmV@%&~I~yf@JQ;64EyTY(y(-ghk~d=nmsqlkn-DmIlW!c0V|jLk33S7i z;^d6Ip(wa+f!fKg2k($l5gj}hGDiCWB$k4J43XHV3*KDNIdS^kOf_xS8|N{Z81c1h zxjrbGFrY9R3B^}Gmn-uB^^`aIeDB40 z=w3E)rwHsw4O9v+_bXVvd40%8OS$0knE(=;l|6Pn69c=CHBb8;XPKYq_)RoWc=kDC zYd^Oi4T#NKKB=5aIe@K*l}$#lnHUNquo4aQ>egniOwXFr`iV#6n)tGcYooD>ky?}I zSOZ2rW0SgB&V05>AAW^4487iTKbHr-_di^8d;gyS3eJBugn0^hX?{Nue`a_;&3!*| zdeiHEiBnd`s#&?W81D-SeISnwk!epK!j=uL$2I*9-rR>uu&~VGB4_86YG98LfIb0( zAU?_%f8XRlT|9NIc}J3s=iV&Z+co%2BR^SjN+?txV7&vH$vWm03T&=eFFgpD^pQYW zG*v`;@bL}8@aU|#8%I9GAlHi`HIf+fe0;zrAnT3OazwmblmVwep15-l?U!2m4Li36^i`NO%FY6I+*F-RsgnQ0%O}XGV+;dGoMV$mKEGadcKHl3b=Pp_X z$UV30@mcIS_B6U4jDgp#zu4&w9-KT7Q&|@w=4bmV+sEs?so%5_{|xclfXY_*fq{Aw z8=3zSILj53cC%Xt?@f!*Ukv+|M=S^wjA-mPYKUZ{p0G^_BL$$8pSZ& z2{ZH-2K=@)99Xg_@tc=lF^)LwTqDv~$9(0%;T;q1H+Z0G?oKW+M@mrsG^%?{pK2nbUa5Cc#6CWhEqjWG?nn#QXzURdS_ zR4{tD{wj%nYG&s@8@IdgqJI+>Ie<~0VuBmC{vKBL_uF0Tf|iG0`2MSQyO$EgAg|JuApO`{as>~G%KF7JL}f-1GtF0Y}SCbWEM+O(r*{}ye{Dx~;CpOC&} z7}10Q4_26xdP<>Zs1E>4%=G+0y6-g6O}}%|XvwhaoGX$SH$h zvEf?2tck?IBuSS>Rjph2hk#Ex$ZFGgBPI54F<{b*do%=OF8JD%aHsXm1b)CwHew$8 zm&9u+vAid8T1N{RG#JA%>0~h1!Fh5abp(MzR$ zSPe_ZLZ9^~X0w0<8B~EUjIt9z^C!nNjG4#T#8Yh884hnT0J5#^rAOs7QiTaz-dt7m z55eoj-4JcnYWyIssAR)Hldv4jl4K5zu>|(d2zJ2=WlF|ag6)ZRsb^7brim|;za?ISUUa4gz0M&EG0+FtbHsY^C8aECK!~c3f^3ue}RvPi>p^2CeHti=**WkqS z8%L8@?;#Padof1LD<#>dh!`E`-Hg@zx9cE8yu4|RY1h#H*A=siW+B|ibs16m<^)Q; zp^_J;I=*Ag$cP6QyQIGRs}ufZ9{JQn(Mh zmior2o%&~dm#Zxt`O9qwo$NL*!AYX01X_&#Y5QCWFRFy<_Xce45>BRE(rm_Hc9a@q z;7FcOhRVPQRVSAIKJt7h3JRxmArUs+@iN^D-w!}2BU2K$KBlYaPevG~iXDH-$D%?F zi;&M1k^qE+YMND3 zAr!!TWMK1=Py;z-pN(*AMTMCpD)o)pys?F{!?J)FYv6t@E{NjF8kzZng-IE}cufix zHWQG9B#E|fv?z)^7h2u@v^@=(4}9epf4yJLg=~2L=Suz`_%|SCtQsNy;sLUW33<$Y zb$WkQ3wZGgd`I%+>VZ#G+&uT~3g{bZqx;$5LNb{rtb#kVH8T6mYQ7Omdw=G&M2R7A z`jDOYkf?Qij)`>YF;Pg4Q&$$(%s^M!{8hs)g87(?Rk-9(WhN<)`7y3P zJnlk#Tf{{EPt*_q=m4%waG3u#?-Y6He>ZK_zLnGfdsrVoZp`wNUrb>v7F`$7|9hmi zuxUKPG;dfkvnR29F<7S1q>j*e`bm)2MjL$c@W*U2cUj%4#I6%m@t}c^!U3RGG5=yi z2k-Ggg*XwNX*_aRWpE?mE9x^iG1Vu`9Q(OW*Od~G%TAG9NPT_r;jo=aa-%NwY&G~8 zlB=g7G}m42^kC=)KD0zUoVUIEIrM_Z8_)a;45n=T2Xzn-I#ffR*3@2s0ROw2XX1Z> zJvf0KZhO~TtZL`ar}x5L7fn5dtFVxB@P=hbJG&PG*?JQ>cYkvg_O)FV7wdXK1UicX%4Lp6Myoo;og+=T!7YeZ%EQDW3kX1@Qrx19Z4^eJjJFILq~6S&(3reK80X zgTvBwU1S?B2-t8PTh1C+zG$h`;nG;_|lnION)pc`*nxVGB5tRRekTMXH?ZmRET6(nbO%5hL=;#zS=Lj zn4W>7Kz;#H!9jsoq9GWl*&0e*K3-nYisj_G(e?cYJ=BTKp^iwB17Ln99)O3Jd9!0C zQ_3U0w{C!?0^TZ9GB>mzR`1)JU`#j8d4aaNL2n-Y0j85`Ly{x@I<|ll7sDTh8NYwo zQs2z)`4|EN?jU=2-9nDsS4J>V=b1vvg_D`z`F?`%P?!*47A?#$LTYg27%pS?dt#B? z*0H`y^kJiXRkR5UrN<6AFb|pGu`wUm-^I&1izuq4qX|vG8jgUbpTWiUgItK5MKFjk zuuWgz#HB!$Z?7H+cUb@+pQM#ww(h2XQ9}c z+zc=P_1NC6#}Af=IW9869BW?*_Xqv~&+}bN7jlmiguOt-xQ1 z@(-R-Qrs)UyUYOE=ItzJ$E1{|8}=TfpAe<==-k(`o0&%iv{WG_q@H|;&w-tm?7Wt` z-aL;hmS+#o;w=Ze5*6E9d)L%!hd&=GBb%=Tv7*?YZzZyALfdAsb0pEPvM?Vpc0dUc z$m&RCg5o#c$8k*@atyP#trG>w&4&S{Qs3NS&?0M-tx#nAMB`{&mY!`=T64F}Qu?P+ zcjtYM+b~wo{$c=5O2%-2;M#(gNh-0oEkV6_)e%qLw9J&OmJW87O>5gu{0BIMnF_#5 zi+p&hq}t!CVr?E>$={n#nTZ_4abqt`t5O>Fi`?<)V}orNF!2>pBM$ck|CmME!_}Gl5 z0u%)DLpZApPT`7Mc2;SZ%D>XRTI2%K%rmBuaYd2?`&@`umhV!E6v=%rC?Q3x2Rs%= z26@(7AL_lHfHmh@RpkwSNTGSTMPG{U(dzA5#yq59VR!V=p+Tz+0sjiaxCF%HLBT}% zXIjb|iDV0tDis)02XEmQY7uh08aNUS_ks@`t12m%I*8hdRV(Cw?qCx|SE-~V(ydXs zIu~{^yZ}R2uu**_M;^2acugnB%I~B8B~(@2(oeb4{b=enYIUvVYm9g|J4Yc0 z$gILkOYl_M36HM079D$O7I=pK6H93+>i%0I%*Eqbui=}>dPL&?7SViGe&lrAVV1`p7dHJM76&MXP0d4WQ{8pUL$8b*a&0f#<}eqM>e1;V zhJz)6BF~u@6x@)JrY~)B{S8OilL{MJzza4FygGP45{Imcza77&y%YX#l7~o&Y5z3~ z`tHlGjd!PjOSSjq_p5@yN8#@GI4u2ivjTrs)v-TV7Lh4LxKg;E9X?=v)k6M8LX+9w zV+Y^8qfuZ+#z}^mx^nC+px+>-I_$>;=oTGHQ0t6^lRG2**{hkPk759$xueN9P^%GN z3PXqA&-$#XNTjvxi9x%4)$>!)3$@9?P*|aT&5`ZwFBIg3dOXJfJ-Xyhoq~|2EVec= zxL4>0siagg4>qeleQ6LEsa{Yk=r{!hz>TD?%X9mE5j-|xskZpsLh}5f6FeBm{e!i; zgb#LAB%bI42X!d+_mP9LF@~O79y_#U7z2{AY#|Name`Iod@&JKl<$Xzd@cW)!(Wgn z3f*(_=_7?CO?`%6t8>Lc)vT%J-(|sHDE@u3aLDk!nDQbx(Kw0^~L4bS-<;>md|y# zLAjKQzI$Ha&!0{GW^y-g-`&*K`LDqlN=n&bKW8JvQC6c>{*5GE5pOrG-l$*AIIw_o zDHisZ!+w@u$s$Kg$^Bq=G9`@K3RHSv$0eQ*dx?5|Q55oE_dKKVGVMy*ix{J7K9DY#BPh3f9Ap)XHW1 z??!N0B;tgwWnqv}VW^AxzUnVwetA|y@Suwk!>gyI`-vP0!vs(EO*$PXGXjf=TJ>~y z1xa;!c?hxA@&>KkDwK`JC^!V(c8TK|aW&oykQul+v--B+Sj^b3*yUkh+`jq}3Z z)x%Fn_;^}BeVNt$l;wSO{jtxpANx}q!I@4JbfHlFy-eqM$%8(G#Zib&tztuSQjX}4 z9J+)EO&4K=Z*n8UXld){d3t$xyg#Y_&v@Z~zij>Aw+Jav|GO16pT9&+;$*WxTO9t} zl!3tPK(3S|Qc(Z;Lp8ix(DVb^)D|PKcaqknfyf0Q*J&yN$60qKM_W`h(9_g(65pnP z@f`z)EQ|=n4nxF4aWobWRAt9Gh%7|*C{ZFClO^!{eU)c>m-VGQSEYr#|=6&foMx3ubxr*-c>NNM0PFuzko)}dCFl9{KvWLEU)-HKw&H%~; zHWY6T}>(uPu+a~i|u3Z{x(jSj;UFkoI46e*G# z@l#IKZ-|pkm1jo%98_d+vJC&a(Y{A%tfVge9J82qbt;|;i*78Rl>-V_EDL5 z^i+=!Onyt|u_lR7I}0FA&i(8U+<>~FxIon>GYxDjv9y!`f$ePuc5JeIWKL}S&e(ps`)hTT%o-t{ ze9{RxHS~vphim!$ z`7R}lA{3ckcp|cAB)k)4)n!b&=aV^NX~W$qN2$8A%`=WTHB=WTPU**l+|L$8*;_n* z3x#duMp5gNn9lWb%{0$B0p!TQ!qy4Ls4y$((u1UA?6Z_lMnDW07`%uF!H7>4n^Z9? zM=(B(uVlfpy8D~BY;<=Wjof2Wd)^ag8$ymPma~o7d!z{!s81s8UJadXkz6sm5Q{3D zSCO%->u%?ld?$=)%Z4ixr_L!WlhpC98p}?%uAj8t5c-59^LY8(`2kly``=~tKJavz zPT^E=mwN$N0^ibS!%21E(#D=Gnu>Oa&Rc<*F(>XI%O*^9vBA^9eixI2SLkEf$>CgyhJT~ZKHSr`OUS5sTwND#+{m=d zv|BagFJxF+LTp#EeS$EJ4ud`<4eLbN!A=N?By=2`@FFoWhr=tiB|q#o`c z^Dts*(S0)~NsOx6v2K?oM?PKV(VlJK^=ia!gpbuW)|R{NPSn)`tOl{?2B$oqx(DqB z9{xD7N#>^7>$mIOwdNoU_k2sPnR{QA)&1i27`E+Z74OVy54kt$cyMVGXNiLfTa*^J zT-h59C!X+xPF- zZz7g&_-BSy_PRh_E}7~il5l)k6su>5>?R_^tIbZ%E-n#JD4$n-BOox|MvnF;G?{6H z$yX=#qK$%(Fh*ea2{i4QH2<$INPqw_VB;J|z3*Lp(NTB;rw1GHV`bSfq4jhQG>gg{ z8u3hoi1m>S1Imdz2?j4)^=}4=g`nVRYeXAXtQNk0z`+?wMC z|CJkjW?I$a`XfjsC0+%_9SKkrOH4{hy{kSV=ZCqz)sJiaYUTT&SPMz%C<%!C<7Bl_ z;`)W4y1vh9;|CT1X(B5B0Livl9II60*<5j|m4G}it{_>9PCcB6RFW<)VIevKnMVbg zHY7kO%A3*|IaCyf&mk%af>-hz20^u2h=NDBClpH0-asuQnEvUPkX`hy zho^)8qA_jj_vF(`O8#?bLQOdwXmSw?GkN5+;Y2k~6#F zUI#4#C_o}kg4@)(0)6q%h?^maSg_*~c<@9@LmQ=lM1y{x*E6c`IccXh z(^Oqu7f%mWQs65FO62(NEKqUKYy2BUmKjn+0bC;6vHX-LL0(TiBOO(Y_NEB#qkmx8 zv))BN{6s!2Y<&O7R8`52&ImfObe%RTQab?L5+Jt!$J4l{8{E7+`H`7|5LttR`>Dhb z3I1`!9=Vj}bnh>itI%{uS@8zASiQPjGU>nw@}o{prJUa;%lfPPbm-#?tUO$@q5Arc z!B6(|{3SbQ9x-8*JkwlrxYnkImTi41rPxv&OAMDW4?E^_?3T6dpk~Ok$^M4cR~Tb5 z(Dq42=x*u<7{pX?Z<_+tKO!_wwqygjQqXZy|FPt=aemz-dV&hEZBHbo(8 zpz4D-lrD!W+QbuxaY3dDWMW(c)y%;MTZ&vKpz84O0NSotOGMi+cd`Pi(9jw>a`m(t zufeYpXv<1J+8o4jpR@xo3;j!LYvHeRzRbrYXnib66M-ed){kARt+|(>ijTH7@mbDs zhwIfTLacfIQ4aD)MeV79PV!#T`YNY9B!6OpRbSA>qOIg6>7ydfb6N2 z4YN5TXkB-3<=WE(m3~I;91V>?9(L(VHoI=RW}tz&53(dtsf^Z_J&x*?)A|vWJnk@` zy!A~HCp+{Eb%)1{OfErY^ichU0$XKBb2Eed`SM0%QcV!D{8Js!Z9x-(*TZlk*mH!? z%GQ2u&a+%X`Ym32 zkjz5}j<2W-pll0UtZXgqA219$h%j9pZbEemIln^7QSUR!5)*w4{4w|+lP}5%>saFX?ilp zYfypi+G1=q%BETns9=FR#@q}E%lunOcV`;E{xq{0^^y?bl zS6=1E`3lw94<7=JrdfVmRsqsrd#qDvgdNZIb9EZ6{#9V(fHU{bUv>4)*B#9|yB`p~ zPmE1KE@wQevlu`KZR-89PY2(h_7I?wq2o(Yq5Czs$JG6A3Rm5J2E`|H0*_JJu6~`= zyTZV4S2-`0Zka}>4OZOQu5#dAaPy|;@^#$Rh5i2yJ;_S^Q#tE8fYiYsvOq(WL0ukvtsPE#+UI)` zPsske$EKor>I;T*VNPJKJoaIB#1u?J!@&%x#8v!qervery5IbyhFW_V`du4_f+r7m zci_S0vdY%|2|2+oPCfxqXhZQRibR~Z%bYrxH zsq$E7t1Egw|V*k)5EW9T|E?gT|jm5Zu$6j2e&}x zyO!uDVPzl849#GnSo*^2OI=3NG=Q>(H_t~94h}LcvK-7O-ehuXy{|ojG)*dT*5oH^ zYo1X_Gc~lrAESq%CuExU`xRUj)WkmzB_`eo+TSStE189^47F=HHS45x5YbpUG%2%9 z4Zu*(CM^yiLFm**1Xj+Z1Q}h@9)!h7cHg3Gf3kGp3C($F{%?{(^|P0+drH}z-a+%$ zXvcQ#u?|dJsnPOVOdNg^oV>fB`46rOywBeoSuC$>*l2`(v6B)+>Wh&Twa?K8%t`|4 zw?-HW6VyrEzE~mo_Dggn3&=2F7xQFPO8qjblx9<6f;!<~)%k4c65`KP6w?stQHjF| zzgd`|6tk$79doOyiG4`6eUBPY(MeROmDNi;(RYs2RI>pUpamtTpw12J8UhR*w! zwu+UVBr=tBVZ7Gpch3ZSQ`}`3{2HbCdJlBCyGU&Z^cB8*+g}BI@vn3+R{Qst0n>KV z;a0yV>`jDDRw(C?tzrX0N2IiUy-g9RdfG8 zs?Iv7tuOlaf#B{|oECStpe?S&-L1I0dx1h*DDDM{6f5pl+%0&ZxJ$60FW>ijZ|1$3 zlbQT=Z)S4moV)j0>$92f(FRy{J_lIcJk;M6{5mD=N`0^U4c6s?x_J9;S71T^O86)l zk!{SrUOZXG;-;%xgB0(xI{Y(IP>z}nhxuYW{Cv;X z#kBx%$*T|fxac}IAo$T?2m4l?e#gC`&eJ2E>!VO8m$}1wvvKEIKCe;ojAb!^I6dKA z6e569X4$obP|aezJ=(U%;TO-c*{)DX^Wv#d*)wC$$9;l3>GYtyHOr1;;Hp8*Fw3F0 z&rP6FKJnCozb=I-s{!?F3Mx|kFu&@%=6oZx9BOS8|K^1GJ1Q- z27Ax2uEygt%n0ltjI1KDu>{tAe0JKksvZAXkiv*^gm z!%VHP;;V>vE!B{hXN{L#_&-GOax({`Wsoi+-bY5JZ?^=9{0lB<&KqP6xpd8>H!TT4 zLaKyvq`yTKF?4rFnn+n8GEc9|fq$sSew>J(BrNrl^B&_kc>>qs_c4oV9M2p(5<=S5j%64Zw3&w+7&iEH0)*o~In5CP|H=SHCqQszb zO4h&$%r2MV5zNq?hdPoLT0}s61owV!93Ept!u~%bsNt{t(7eh!LqnvCg%Kh&PXsTH zH0t}jvDM_Mr=(0cyu>0fXSb>LDksP!UbwX>mz!@Pc+&Q= z`kpFQI83<06}T1xqE99dhMKVtfN3c^1Q|QxM#0t<2*G?kp&`?0$$i2@=iMoxs=j(` z+RvB0kIH|A4!z41IOn6eF2qdTn~k@2kKy9%WkVMQhn{}NA^gnefM7BlS!E(R4**@3Q`i z$nIpyyt>|S()-KV=tr^Oo5bx+>tY}^4GnV8@KyY1035LDC{`YO&UdS_^(Zi=s%>lr ze3`^r5j`gzWSe4_-ySb$7StrcVv>NQ4=XL;C`)6@*?@j%xna7!>o({-@^8D%BQ0GE z{Ntq5`g=0^=*`|pu-dQAAlvzg!J40_e}&uB!=iGKr4aKzx^mOmXaLf`4G@Ac=hW10p}w(GlCQ?rcR2acLiX(_>gvgUettcdZc>E6L3}c4+JA2C%lb^t zD8l0ub%nJKVk&cS?k$@h692sX`W|Z_7R|3LXOOk+mx(tgXXmx;?L%iS$rC=Yr%m#N zh%!!607guFMo~hh_!2H&|MWjj-wprj;@x!B`6y`p+f-smO-g-*=~GEITpGZq@T>F zA#Z?94*tr)Kjjp2?R@Eif<_({6DLf-v?W+*d$%eX1a!<~ zCZKi)($VS?=}=F}eT~oW(J3D|6y|rv(=$FZ+nTFxOYk6FR-y8%;sC48<=lk#?b#A! zPfB(G!suAqvQjvnWl+Rh;Z1J;yAUq6G!cB{}8!k+&{7^70H$QEZ*^^OwZQgLUpP zHz~5SjQQPMfwv}C9LNrgD8tL5I?HO{AJa^D#D_BHr8p)wWSUbBs zq?VdD*{6(|?#%bURJN}&4DJXMH&DnU(M*xv9&Z4@r>fVvJ{A;g)ggZ98H_!&a46JQ zgmP9s2-PSCM)^%y=ctHqeHKv=$v@bbfTgIsj&nt)3@IQ;_)pDVWnkbTLgkUC8JF`8 z?-KCBd^XxCb09^Dddp!iQ= zdZalXp_pYQgZrL4)``&?*O0nu;5qH?AWO$L>3fsdhRA{04ZbHhUm}563i2&LcV92l zS<&@Gx`d^T^R$_lLm4$kyoTi||4C)xDPw}vMriGI+&68?29S^H*5*rk&8uXWnz-~N zMJ*qkylsjf_>_tg1>mPecc_5oDO=N;Ar)G^fT6JoHzUrN;o)BIr6SQ8qJx;}d1%MQ zllG|P-tUngS(^tJi!Ja8f|YWUdsR=}N1?iR?DEO%q|IE+oyecsvUl6wFGtqA$<5iO z2VIJ*&5*TV=$#`6_SL)-BV%mKZQ8nM4XUkY>pPT#w&d=TBChpTy)8@*ehfae0U<_+ zjrTuOQP!l~NND;M+i#>}PK7PJq=hf5h=)8hhu#c@zU;q(aYL`ZXQOr*wUzwOD!KNh z7zQ`3LN?Z)*OFHzo?V}J%FZt?{QB0{shU=ux6rF0UP~^%OQ&}}W}W@sa1_G!1)d2Q zsu)xKeQqYn-+L2igH9)k!-O<2EsCu9F_>MFAcDn^R_TR#q-WiS6Pa9 zTYw>*FrS3F6n~q0%S#;7>PMz5_FuR_TDR_62RVl??D^*Z;Aek&)$`Y#nu6BD*;}X5 zMjZE4#1n&4@$gfTrLBZZKJcj%*hp-I%aWkhZ))&9l`!+R|4YR7jI2bPp;yTMS7!Ni zBgesQ7>79`*@j0LUwdE1vo8dkAt@b&Vu6U^oq?Zt3TYy4sE<)71$ zkE5zeZ&S`?BcQACt}9r|j5&{QM0?+4*$E1;bp=EJ1iWM`Nd^MUa#%GtEn0?1vE!6MKkF-kC7Zo>bM}0a;;AMSug`|XEC<}3TsT?u#MOJKA z+db^1O|ZD)8O%bjb6J%PVQR5SH~ocU+W1xPEh#TCB_%fx+D!6<1TJO`={|=}p{^1UY-)pD zr+q-Tk77AfcE*!-SpUk;kA2VaHoApygM;+~jxaGhJTwJZLzyZb%nofzYVWA27WwWz z!y1E&=!Y9^gKhFN)0)f=7<*3iJRgUZVKC!77FU~Bqp5BeSCjn`@4Yys&KHu=OW3_5 zU=MJqgk$8S_kl1iVo=Vy^H&Vbr7bOrBki(utN3d$%yYT^;=MdxKeW_e#BApT9~&>WTyrYRAl_7o@oqjXnMqX z``o*6%b!^7=agU|Szrp2!E<%nE2PnQ8%N&KrsgGcLi{yu9Ev_wskmY~sRhs4COW8& zQ@46?1_VchHXkr8lOD$*BZryVN1(nhM}13s74#eHz%xXnR}gDOi{kgxps)c_QuUj0 z1{1+r408s8f{lF2%+ZHJaiI9{+FWl~54C`F*o`aB9SIiFS7`=1gu-}(*Z10fnXF+t zYI=lm00b5kxAyj?NJP$+(%qD{Z8RyI;5N6f2n7EEd4DoWNp}PiP~6-ScuK|=z|9RZ zK&5|~)Ba*WUT4eVO6cOAq;%0mIMQ2S15d$joCBvgWq6?yxsE7=VPq8gFe=U&(!FDb zklDQHVB#6)Z#MHNfTz+MIQV@yRP+bNu*!|TZa3z|w_>W0r3BFrOMd`(Stu#)3`L2- zDRYa`_w=*RoHo>RJw9*S;~Ud3M}r*Cz+orovC;@tQ_fi^s_D3v7Y*OMvBw{#?tC`X zcYT@VBbb449>K;n!cv$HFE=f%{z^LgB!Q7M=@|r?LDo^LLrZLkDP% z=h53$Y1Ic;P?w2v*G|eJ(hXvrM6TE8_`6Hdf63Q0%5G4F?+MdacoIlOoD161Q0h zB9;AN$`ZrZkoY;gGQ<7K1=V~oKf^`LA>V_w+J7NCsT(&6G;uPGF04wg)_TPG3w?+c z9EnYj`@dcQWn6u~;19j;mLi{sWd+VY>?(^C=_?OF;6jAs30hZd`NRFn&T$kYobgEX z!B)zen*Kt9kB*)$qNl?r5eeyA2s)qoDR}{hO?(ia8i5jA+bcyPP!HPcH3By}`HH$8 zrF6CqiJM$L0PEE0@2ometKJ=xZiiYx+R9j;^;dkq1>bjiJjv>O(`8AWV!sksb_jpf z%;SkV37?WV+#5!#$d1?S-#?NjV{iE2@bjvocK;stH!6E_f#|zT1~*i0-h0VN=>@eM z5aLni8skvGKiAMFz1JhI7q~6olW6#GUk2~-!nL6Fkl0h7SW_&uU~n-p!<0+2omFbsl;CO- z05MZ>_B+RWLV#epjV)UQ@mgvcN8S+D=r9k%NDY2g>EBWax0XO1y|5}vdu%>qA_E%~ z<+%kQ#nUW~UFGXZg7Bo(5f7Iyj8BWY&rkuLj{kf~ZHY%oTT9&$I?& zrqw~bWwLf7&~sR(1_8kjM6aU5sgpx!JMw0wmPxa^KpvQtLPGUH0{}_rsZHBA>sC|# zTXePzM!cyWd)69{6@{ebROVMwf2n{piR(V_%;jITEhQj5{+?W8OfR3rW@l#HM>nTwmW`SfjSXY0M3mI40oV zx5Yw4x8k`NINiq3?y=nkWYhNZr2vDmyOO(v{WZfy*iB!cb-|ZQ@HeJLH?_&z`i9puZbz=kdg?H)# zVH(x1%ogP{c%0kh>Si?fvhSM@@w0y<+42-Q2Q;WgE;SPTV>T~{;y2beg*eZ+2p#yo zaoXKn-|h!)bcfn~nQe&%0+6*4==eSCdFT=erO+8vg*E&5la^E%xP1z$kxTIvLAO-6 z!V)L7p-_~e$3RL*hlK{jCARb!Pgd$P7K$JjO_;v+@yz6^9!iFGko!BKn2sLjfz&-e ztK1`D8QM9P5{Ewiz5aB{QT3ptffyT`IcSv13=)5;j0^!q3ISA9l>wlN%o%a$x!P1f zCh`fWTFoM&O*3K3Gj>lW2RxG(!u9Sl{jPwdz_)Vzi1=^ROUj#~qIhczW9cH;Lhf%W zx7t4o)^ACT0T5x+uDtZv*%VX@hk?aY> z?3GneB8fVx93xAp)(f)GKbV94MyEc7YuA|#a)tW0P{O-IOuGVk_Ae{e^HdrBh z>d<&dAA*F5BGjUY3eGXJ_Hwvo`bvvK3=%b#I>vW<2BSg5Ko)Fc7p%Q-uJ7U8s8X%t zzh3O)KvY(b2X3k74$r44u|R^}eLB&u@i%)eDIY9)zS1^~s`C^Wtof?SAKce4a=X=> z8qWP$$-&4>E@`9cn!NC8y07n6F*~rY44t&Cy*69?Zfj@(aM#Rt3GVbZ%K5yU6If&yjG1PCv9B?9;FY3sPd= zS#1t7CX>e|q3+@xBKxf`Ah_XUSLJ&ru|2zQIF0x_PyIB$9f;;Vl3@N8z|3Ti=6r~@ zI+iAAgD<{H1Tf)4Mi?$xnNo4}R+kTp0;MeyQY33%U<=~ z8r5buNWa62KSv5Vn7Z zS{=RbMyCDSth~Pl`JY04iQw~B8j9~nCW3J7eg$@JFf51_&eI?j{_X#dvI(UCwLj zyLwO3f4*&0B1y8-VrssU6wleV|MhA9>%(MTubK=$ z1)pEks@<2s)w_1*=WxKx>9lvQUpz2Nu;BO&e-f)4plF!sU6O@1%8>hyFVb42yuY{? zY(7-;>i-@2@gD2;J0W*ECh#uggMLjNQH^@w7e(Dm>$d!6zE-s}uTL&N zP?dU4W${bGVhxT`_72_KA3YX9`Yv1pm4qfvF$+gld! z{*LweuFFBn%$XL>2WBC&gN|U???NYEEX5w^v1jgVq2(b>+CO7Ng>Iypd7-vmP9>~U zG{qWiA3Xc@46x0(_xBRFqN#&zBm+aJ0~nOKsjU~8R+!l@7zM1%BX0;m+95R?G>dst zr}h-sC97L66QEKa3o_yHGq?(Pd4CbNeHb^k8(~4VTzoJ5&r70Mgc6G%e3y&x)U+DJ z94otiYrnF1X`^V}Tykk?!#j|(iC9fcMQrsRUNtsQtu)C)&TCiKw}T|$yxNQ2(m8Z^ z0qXbq(n-aB^w{+;IsXuR)PB}&yt^Ch*!ZehJ+%;I7P!8Xxckj)MejJ6YxU1)KhDjk z9P&8Na2?omj&M_=kL?iSPMjF-djgiQ>nOyf%jq2DA|M;lp zMlPbwNdlQJ3*vkHRJ46)Irq!JQb7rdvt@Fo7Pv58iV(4s-;xr|WX?RWd&su?@2yM1 z`hQ~yad2^Q;Xe@s&w4&=MYxmke5R&T#gN)+`%ceOJveQ!c^Zun?g-daae zL*`wkpd#IaR|3=TQGOgg&halt@&gE4O_UCmG$O@?*R)sbV~Orua>p-9QNvN3=!Z%oK3fMKC;YCKncs` zA6nY48+l^C+EqP_(1 z@1L>OvM5A;5!z4`IzVBa?nT!EaML@W%k9^rJK1u<1nV1vZISmiM?p><(*LNEu~(%t z+QY&W&=sN_qD{*;hMSu^xacTk@oGSe%5mY-17W&-bts1nmCfGa)jX(P9)ZI_o+cRy zZ#hb|#Wk;r12mSWTz8p7h)m)@V-Kn0t1hLlhWn$d>TUqlJ0A7mk#OZLFTX^vT9Ch7SxDDOgas#&B$BF6 za-m#*Q5!x#AY%>t2pZ-gd)LfHOOKH&pM}MZyl@)BZC30OSe!~C`;FxJd{F6Cjd*j( z`u)e1Qq(;Y{Y7Nh5TGKw*JNZ@hiQ%r?X{?&w$z)N&cRd-B}*xDX3n|vs}@?1REErk zq)wMnsry$$nyD~Lau^0(qP7}fk2X(f&?Rrw$jo@nK znuW}+?>>fKy%dC*BHzPqwD!}Tu?orl;AsGkT9S1IbJ)I9A5__?FV5PwS#TI{7TcnV z@>Ay3_(b9Hp=F}w-OT!*X&IB-t-e`v-Stf6Oh1Kd%2BT5dqXlI#$}q9aUSo< zwMjl7Kx@t8GIrui`5w=bVzO897L5 z2ukw?5gJ&#&=VFGjd)*A+NIF|(yYh3YRX4+>9kJ%wNj%iwB3Cr{K+H($KG!Zi?<== zoPdXY4y&XwC*|k(-Z%6L)zy{y-sSMe|18tA7ft{Sapl%GyY`V3?ev_xUjQMl zXkaoinTLarPi=d6Ts0A2b$lx|Rq@k`ZpWE(-SWx!^!%y-D*N1Yt*t{qcVs$+UTU1!}abls$mpW^d#BuK@mn^r?&}6PI^U?^ ziyAddwkIqMy@!lD249xU?K6`&NW8wT_M9WiosF8$rybto{q29YJ>8DDw|ebEpC@Zu zu6!8Q+;8dX z^7HS1&lNd2TnI$(rza3A;-l5*tZBx|h~8eSLcV2uzTxsr} zq>+Pf#<$<=NQ|ByJf|V5h#23c3lUAT4RYT4W+<^Ey7XA;4ZwZ#V;`22bM(dU1-XK0hYuMqr);0BV58k?uINQMWUAQ9G1nJy2^QBko!RIlf0#)jRl1ug<1Yc5a4<({0zQ2#i^D& z`k0uEiV>K8o2*trwrqs_Zu49JoE#GR$UxY-Dx?@bVYyBk+_Ypa1Myx8^+`Tm|6+3~ zbms@%!-fm0m-qKkV~1E-a&Y{*1KGQV#bN%ah7ffA9G)-07_zT2Qt*LOPRrX6pTOSQ z<)Y&NN_D1bJ+nfH%jI4I*TsLIWl}TCP~RcCI^=0mS){-Aa^-KsD*G7X`C9aVrq|vU z`ri2HPoi^|W8@m9lC$_0N`Rk>dgs9`~Zsc($sK`%R zi*zU!XP2VAV(-u-0#cT*R}UH{G6wSK+c_BW+tOc0=(v_0#IhXkU(@FmFhp7kVvNfe z<~hXCHIk*3u>y2t85O(v{9>>nbbD^@Nql_-sd>ARb#EU{2;UfUl6C~%;cN?kmIm?I zyDBO06K@d3|GLos)q~4u7KQisKypM}AfV^V2BXlO#f{;tQSVBjIrbJ&RZSc`wGu6R zC?|nduwh=WoiZc>{4?D1X=E3*0PtPa9OMch?h%r#RFdG|<>donHH$l82L#k~2Px2@gsP1aJmhl>rJ&6^jv}n#07|bDAKB^x!YBW&jhpDk^vBU7W{!|M;S5`P7irz>0MXEG{3FBK2F>PhEYH5y;xAE zrUxjxdausg5eL{lVtn;8o5%Q?%5mzMh9$N4x=#Hyxvh7nYwbJ!`)~w*T9n(!J3b72 zG!7Yir%-h|+SXG(Bn4rIJ(>(xt4G$zTRGBE(NM;ZQ-dL|cC@x`Wf&1B@=_`0=CfbQ ze-^JaYYMW=MaFoTkUYWdA=S!wZj%r{1HY8wStLlh&5Z^D?s8Z3A{e%Dmkyd`26vQ_BS1d;$@?x#(_pk zD0yYcrF89)fi1gpHbokqG2}J0+>DBS%`rT1rmLTgEaBoNR>X=aMj&nP;3B+RV z=0FUGu5tOo7Y>iyZFs+0D_wayAoY`TT$9%)(}FY9t}t^^vZzcuIe1PuUekH!oF_E7 z)LdfQPqc2Rs~_&tL>THPq^8Mt6OFG^#xkAb??u9Fs7kSPS>~BEKE@k{s&RuD+S;iVZ#_< z^DeXS#CK&!tj-mGFp&kgFXjhUK(x6QL>`p?X*V6?M^V_74F0umL-(nKQe<(OA)AK^ zo%=h7I@0{}WZu-p07JxT6P<9^Vb8TngkZf}`NgM>YHBWoT$PR>8{c`1&c=>zoKYv*3xm;VwbBKMXvZ#dK1^b+TrCAOecfzCT z*8`>TFG)EvP~faec)JGmg*fOE>VL{}oJNW^hYI|qcYEWgRc)qd=eYS;rgRe$=sdbA z2ZDSq`?;Yvo!kf5BHGb6JzvJt03Rc_afcSRQCFO&9mUjNQw(n_UH`2LG;Z?b@YEXA zxhcPm2g9lGu=H^?`@njHD2>_Nh#IV?RC2#Y)3<@P^jPVdI4D%^!s1((m-z6qNtimB z?A^}K7{}G?H~c168-goMf4DocPf6NOae^U*niuAAdkAQB+Q)MU4hrKn#Os=_Oekcu zC|(*_D%7)6!b!SdMnMw#7Ra^z>X)Q-jEsx=UC-jHK8eyiichrr1l^&kA+2^^#>f5* zgIt>x$3EQ{?gD}5CC>xYmAmw=dD)V#e7gI`ji+_z?<%(Ux_`Jl|Ng7nt+ygT(|pvH zpB&KnV|!s1RbH*a|KppB6WX*(h{&4J#cA;qoe~+7Nj^f-fx4kc&XO;cPjIp`Bq1ac zcMRUfg!v7?-1;uv;BK3NtwZ#5DEXYt06!L4OhTBy{N*eu-bb86QG9oe4K)5|l>hqp zXFdmFC`WXHByyjcA=`hrLUHck6ev6s;GX;`Wg<5`GU43vdIOjg=QG1VdXI#=A3lWi>d%c*gB|&aW`T;m6N@b zzl%rP7XBC1x_NjQe>Xoz-p{@CA`p-)^bbKE7xLu=P%U>geZB)wxbbBaA|J5WrWf!L zrFUWAT{5};WU^Z1Xw>jKX7P0TCWyK1D;mYJY{G$sRc)|DAm)vEeG0fT+eo1MCvCX- z6NU$U7&Aua&wu_CHfmg>{$@3}y9{0-DdSwY1Qj=)awN62T(tWJJI7G>Ym^T!{!^Kk zNph%9(k6#f!-d_EbFp?k9^PS=XY_t38QkjH)w#C;0_Vhk{yol~=N2C22jr_DVi_FS z6^rRe?uT4I=dB*x&E?R%g39moK62IK4DUZI$a&Jym{o($rLd8meXe8YA6Yfa^^#g8 z8!wiF7LuRyrmW_dQ)Vll-neYsKY@3$m%9|cy!yD#AFl~|6h-98!4F6Mh3E2X#ZFM~ z4b!GLcIm)lFZ|%=Yur$R6|sdfzV`S|W-aN=azRu>axY!8Ah<7L^`!d#HMbXgkDZ%r zCREUtRIe~;u%&PLB1q@lf!Omo_};4X42J8kmaT^$6JTnHE;B^hzOe8c<^3|X%R_X1 z{^#d$u=4riB}QJJXxrgRi8C{d(xkgOhYV9@9U4u&0JC?FoMY4mvR3YQBlp z7;_iRucy)gweYA)%}}dD#B+zQS?<(1aM@?Js(cMg?QB>JkN)Nc0Bcc<`Z@g7tKA80DUWH|^HV zL=MDfLBosGN4dHb=8iPr_EC_%0S(kT)}4k*rQs}8>S5YQ?HK^g+T&+s99XV zymu=LTXPuN9LQ)4Qk`*;ff@F*7grwH)tI0kj2#~ybdaYCS3;3a5Knm2uE&48u!@ZTt3YEv5}WXvVl5Z zG?=;vkIWN$GD(0hOeUO>QZ(_@Q`h|C9zyl~0wi00d0StA0ssaSxZk*il zhMii?WxcqW(wMj|+}N%9Vn1s{pRByptK|P%dHN*_<|I-+d+6wJB&s*%=@v{L4G5II z!W1EeRHA|^0zyAYK@x(pez!mU_DBuw<_2UJ2|>-@k8hhzvMW<2%l~IkT5qrU&#naB z9hV}(gL_1$3{@Gf4EwJ%%|fTWEz_-nl2kfTcWH|FJX&9^!wH4I6 z>oo`)*s4e_W8fTOh}kCZhb3-}A3IR!zv2;8b;J`4z9*9sCZucNXj-Kta(4f}UI41V z8CQyd(hqaq2cowf-Rq~duP1zKo&J%}*+MPt-9sUvu@kllaA_}_gpS+XjzB7RaxQh$ zpBH%58qPqEu#)OSEGf#7WumY#-C@><1JKa7QAO(={0Fk@X&se#BR9>?$w#f`vb>b+*? zqQebQ3;lD=E|&kF(zvpjc^O>?Mn?vy7@1xf0TmOl_-;xpaM?t2CM zo&Qb(EU%P)U^AU83i$TT|3G>EUn_6*eewDWhs zoyqQJQv}0(LT?Emj$3ih+f%z=U`kwZnM+3-#w_=0Pe;1ul`RWk3L2@@t= z8)FRoyc2XyAivo)#5;vNj-;O5jsvm1b5zH#bYiwMx9lV zZ#4=Fr5+n9)C2O0Liv`U1pwW1wvoZ;rN2bl<44;Tjq766K7`sxbAPk(9^sy7IFZ&O zvp9DG7fdsVi%)uTw<#AUBrOHfo@lnL@!f^$-)qzcKt@EOC<}*w10^|Izw8Fo^X6xV z(m{v(Ragstj-FR{7=S9TK7~0dur?!Jkq>61v@w@BzMSe zB-=(s$fk-fQc&y-TZ~5|LpGTu`E~Y_0Lh-?94p zgqIXJsS&7T7J=#gyTkUyC5uFLwXhuL+fv@{El0OH3ft734qyQ2plPOFgBS_osB-;| zYsw575s!J%eG^!!U>16l|9a2$+W-38U(?;?zuEqO9GXTCM2BL;hIi>9u=LQ2dvE2(4n@u5z3W;5Dqf zcfx!br`L1KvB_m-lbQ#m1uI6ncwZ#&7lG??XT2eZ}Kd>`zQ2%jND@lCohfMjt0a zq^H26j~z!tP^j?Pyo>#s52D1i&qgr;7rBZxm?U(~;kB3SO8~FY{gNMZA48hgE!tNt zn<0hAVq)Y@OmkVnq=Uyex(6<%)iMaP6wLD6ZKgZg?z2wnoeC+j6&Akp9rDoIPx4#66wN0L{VzfG9bmOwu ze0;m0<>S0&ragT~ljW?_De(87fFf~BRn`41AlP*4vV6`LvnL%g`Dy>1)MO54M_Y)T zAggHo!;_)dOV`gTH|Sy8CF=$=Jg3lacv+vd3J(lapB`&r zX1TSWbkP{_uPX~qPTJf3J>f6WA}QIglEA?_@RxlzQTT%z&dL5t8S45xj4atDr@gD!=CzPvyQ z@~z|MhuPI#JeK%>9}>FX@&L9xZ8UZ_CN}z~VxMyDGX3T}+AoE%L#_rty)p|_wlDA9 z@J0uJl`KEvDK@R#{B_tlq+%Eo-X2SUGLRZX{F_Ft-8PyvNBQ zLe6x|!SL`88E8Bo8nk4x2}I#mnW(vKLYz-Ntz*!^g%x003x^L8N?eZ*+S zr?{?9C*pu`1q2RCUedQcy;6%PQ9Twe>w)3?UQQ`6d{40}>pBA|{AsdE6xvzXCiZ6@ z4+Z}(jbqnZJE1bSgj+%lA!?J8X+k{hPJIhfNgVM;@g_Y(%v$(gn zS8u1Z&5~{p=eaIdV(f!`a-%Pz$7@p16p19U1^%l28JPNEp4K6B^>TQis38IZApCRx z00=%Z;9@;^TQraS4#xilIuSHWAUvOLbey($V9(*3+5_$I^K2In!ySX*Xrz0aSxebh zcL(HUlA&pFNLHHl*4Wc9J#ro({tB1`9(t`u7dc|oCY$LE$WyK?iQ-BMnAann!8%&R zOFt+nj}E47>jDw;=3d?3=7y08TyIenOkHZ7buIAN)XJfJ`f15-`{;>wGyg5P5YZ>% z5UlNHe72sls--5NknDc^nWkiiJZgWY@o&LLbXQ76dQ7He+>yS0!Rbzgqr4UfQAZ!OzQ3x!!QWrf zy*M_)da9pNMd*Kn{J-!nwbUFTf4Y2or~Qs`4;8c4>}FNV3{k{Rdjn(|`oi|DVN;^AkV>lnoQTEEpxCd_9QxVUu_ufw~X@gU?V@{@W9 z&ufh@)arMIL)%l04lUqoke~4q<;Of@F49xFJM;P0gTorfbX(0CzQTXBkMFJH2?->G zr2d5hwF6d^k>0Av#WJ?;9Wp}MR4TbBwjAMfh+@DB6GFp&r*mEBgIG&bTk!Bn8sMYi zZ3@jD%x1;l+zy+fm<7qwGOzh6M^@D?7-ZK?TuW+uwXc%@{ha8AbPo4(u(HU{1N9beUyQj)%Rji?WN8%X?4 zu(u?|X|^lyG5_@d4xq_@>0ND>{Qr)|s6#P?oyP^U=a=)B+t+*b&}*~T(a^`_c(gfw zjFc00I#Vt(PT-dzEM_sYNfcJG+{u=lDJ*s|vvE%v{K#dBPxW@9trDsXPlp4{pG9ll z4!!p&V$|&WiB)zWAnZhxFTS7-u49U?J|>%HqBDo@kC;{(U{B_at|{u5wmfY8^%!aU zB-YZj%)|f;dJ^x6zI3~jG@dcU4^mR3VqWt~3USz_6UKEMkV5BfUIg zq*TqtZX3K$4i{CkS` zun8&@W_f+c;0Ip+X3;jy=X+}fgE<^kmh0ySZE4vUKgXmpNLHS;k`!3BW?dMuyp^Oc z|CbuQqz*TdLnqljN_s!c1G*@B_DtvUoW>L4YC@m02uz314Wlo7-pwKonNJ2+rRhz^s+3j2nB}B&*r(<^BpuNG zX}VpI7oNq8xO4<7kL|oWh@8sXheq4nruH%YU7JI=4$_&&e`E0kL`AV6V-~O8a`-g# zXHRXIlc7+m%Zmq}!~Z6~o_61JI5A}ajhjBo9HqsA?7ant(s8vcMAEW-{hv$d(8kjM zRDE>^FL?1Y0D#e=!Qd~ri&{h`STql?fd35H+qF&6a%KG&nk z2>9mqpF2EVs2hSR_wnsk314?^;ESxixoWIZ|3%P77n*+MRi$rOCaOdQB-=*+<$dcJ zw1bnpG$;Sd$W@mnxSg}iQr$CJZ^KC0`_+&QLr!>K5{NeMbT8AI;6Xu1sLQ1tCh-mS z)8d(ZfEZs!N#WCz=Csz1_hJ7TMQ%wOef3l?invRSpDCR=JQQi7cCgB{=Ipa{+xdaw z;1S1pu3-K8;DP$_Q4F))TY~cP{??I_nudJZ&h&x6o}QnOCqum>1Pg%-pF6_sD>I<~ zFtPd^KJZF7U(GMTPwH+#Z)qK36&RX)8j{@pC*fD z+p^dVow;(z5H+$2$A9f?WH90*X+==$q}oeNHtWo7%tF7)9p@^cLqcX4wg z;Sr3hB_t>EleWYDja`YU(C>y>Q{;{jY~li%gvSUKKF8ofoX5Og3`~ATcl5ZT=Be9RjvwvsX2YW(1gM*5lW-IKSTHmC)lcYOqGgo zg1qpD2{fdrK~~cP9ho1c*PDyVmTjm5x}dcD%iS=tjuLTWX4&XZ`41k!G?NE2hJURI z(nN!P>}aFpH6o|tc8pN(?H;G{1~d0`hh>dWK5FxuTYx?p9pBpLLH)@9w7VeiK3UFI z_ys;H^O)1`FCiv=>&SGLa_Mor3WC<6H62BrC!*}%=QM)AI$DMWsIe`h#DQperEpgJ3>{3fgmsvHt-Cv+;?7d;Wj+7A1(vN8?ee0$!{M{9-)c`It!*Y1FlU6 zr^VgfrN!Ny;_hCgxVweo4n>Pgad&r@B83t>6nD3voA=%Qc6Mi;ACQ^Ml)0EhA1{58|_x{|J>-#^gcn?L2)Sy!FUeo7z@Z-S6YZLf=zV3DC z;@ylC@d|g098dHeYKgzY_a>Sl{7eA%Ggk$5S15m$KVS7fZFjN+A3wqRF@6EEH)!@{ zPB`C6R-UYeuPNFhqbd4YRb~S->)~$vB_X1Gr=60@RWr+l2z%5OGaQB_cG2GSo_*fD zYs2C~a)3F>nTC9)b&c%&-rvC+d(?Za7|eNC=eWA^C2kAXyb^N)yXj*^8jyL~5LZfX zLE5}q=mQnIJ|mVhdnUaOXH{9RYmQ3?DnD6AJ_QBEZ};sh+B{rUq#PAF)S;2o1!6?$ zTkbhE92YAIyd)rD+)a;kfS|^Ro)v$n(7>Nz+5W&&KZBl!vy1!3)0^1_0`Wbst`X}l z36Ogq^QCIYf0`0qU1XiLpZ23VGtobj0#oW3m7hNa*jA2Vnlrf(< zh#Ap<&=6yGFqj7epa}WsxcOPwPF-f^(An9_sk0F+-P^C4)jY8I^k6kA@S!H$6En=E zW=T?`32-X;WK~%^1O%%!Jy#qPp}I^~$!HcnEeHFg6f9XCmdOM!syy;rGu88QEdG~n z&aQLT#(VkG!rjj6akV|dc^dgs?}=^Ao4t4oaXYT`!qriy1VI5R0?o&zJ2rMN)ggKb~PW{W~6l67x`TgJ_{%$=31c?i7IF<5*_&)XA3*DHq2_Ia1Ix}ptskC4PGr#*i z`%{70zs{A&GQYvDAj_aGMbnyzCK1ixvJ*>+XZ|4kPQslm!o(h~aNR@gjmWcSIl+y@ zhToZqTs8$9;x81Cb;v@@ZXGE#pVL`r{RZoQWCuM~q^5bY6LmQEU>|2*_BG4EXeT@tqBhe?|{XehW z(+BVBuj*`p%Au*)2?tzIbd5-f?QMVX~ zZw-$kT|kJb;c*iQ90%+(#h+eTX6cm`o81sc_1PSi~awnMUJUu*#y-91kpCz_!LW{jS5I0$XUP#L2x^K;#}U z_j;l)cyaF6`Ul|*pM(grn5=HTFZrsPaAE!Kut*fGc#E!{Y?y|rBYgd`?&Fzt=y5Dy*b~Mnvo-0>- znC%DF3GKL+?iHEU`Dqy>zaq@Gm~8}Kg%{eD4}swsJu%=35@mE@N{oihfTDS4@7hEt ziugT#^hAvhGOl(SZ`t@5UlA|$rGaZDe0N0zS7;>#Y)-sWW2X_reMsU&oL7`6`ic zIR6Yhcu?$Jn1t0{=t+;7MIM{n883DN4cvTPzPqxUJ_wVXWVmzv>>xg=Jml^i;?&V9njl$whZ=lp`UcJ+d zyMW0+=tZ=JuhtTus^P}kb$4{yxwvgWt!G}H1U_;9a^7MX5usqpNTS2p^$D0M0iu8x4&U_$fm(XJYP=NzFwL$V*2 znttzXPdp@I_P1fvvTwh;t-^-|+D0fBTF$U+XPCS_(zSl>kV$#a)Cybz#W&t>t(u(V zEuPe^c}o2~Z_(N`T?W&#AzuF;Sfj{7#k7epIPOJ3FbTBrErg${_*`t;m@|lk;685t z@pG0Do+RJFMTozZ$aI>?`0L06b>wY4`b(X8knyq+MuLt2{Fb0__w$nEdUP7nmUjG@>MrdRlct{;WThI7u z>+-CNI{>LtskZ)k;m(p&WCcO0m2`I&vF{HC1!szcX#vvSa>geWl-B|c#5 zjY2WYc_44~hT+OC5>yRygY2X#OR5Kj(&v zY@W5Y2fL4LKCa55daNi?L>}&4_GJIok#z9HUm8hO@cScbZB@o>Zx?P+b82XqG{BNw zMe1Xs!!~RMKNsZEL0Vy5Ws$kwA zYQdnPIq%|+-_M0EQ0rHY+hIO_eBW-<0z-RGy$vW3_AE2WJL9RqbQWCKt90#L}#@+&+CyZ_}DB>9!xrA=HE= znt?hx>{IwOMW1t8rhaQOs7{9%vEZ}vC2C)x^zXKs6S|1zLf>?$7yzcJTi@5ZGXfr< z^V^Gpqsg}1kehr1HAWvroiaGhZ;z>E8mSjm_(Nho-<1rfu(6d22h62TIM?7r$fatr-k`6*%_@I8q_4Q&`QdTDrvfke`X!()g%FO zhV~c8#U7xAZ@&D%gf2d3%q;w}8-%hOqOzM0(qX@?zsfeQz^I6AQXxMwb_TH?U2!Xu z3i2yUUZ{;vv5GA?FmU>sNa&SD&SQqS6=>X%PfQ$Z^+_T6j3f5E%wOGK*pq2wv48xe zcx;Oy9NbAyk)*`buqk)g7BV|cSz%Uc2BfGdK8I_V_$M+|JARjKZ2EL|t3d_7V(Ru@ z!Yu%2^C3ZfhpUZGE@nJ%zcpw!LhDs`frz))+PSf^%AQzMZ4y|s&L*tmChtX@92JM5 zNtvJUP8&Ge*}^r$@J1dnFzS>=uT(^HCu{sSH*M3v8a`^u^JcRxKT;98V+817z_vMh zy6CJXU&=S$=BeTsmw;s!Lxc#3qVsOlBKL9X(fS{aXUNW|7Ev24=i=yaE5lI;Y6mEYNcxe3i_n*N~?ptN5!X>4o2q+cE;dKr#_ zid_}{UP~CuoS2Av8j2#Q3jmxHm!N$)PfUp9%#(Z&vGv!gbIP1`6}eTPPSZ<>z31vz zw_G~Ko;oQtQKjqKIm(&8PxI9szZidZ>g_E`473(uNz4(sY&Z~syROi+|5vs=<<~4~ zydJFCv&4d!j^h2A(sKsGo@9dj8?~IE#39&a2wkG1H{kic?(I_SHJA@0;Quz!!8(2> z#E{`5zM!4H_W?0z915a%eR>GKK?*O(-lauK#!*w0QDSPgkuXIF*8WUfpfuQ*09{QS zIhgE_lapUU537g%eH$gjds!43=2k9}r%~I+p_fSfWiV?+6&}14r^%!zEwDqD!^tXp zMNYug?%Z@FU^EQ{z;u0DZQZ-97rG*EGk12i?q7AN-*9MH<9wW*{IQYtKeqrXPRKWg zoC7Q|3QLUz_;V=nXV8j{ohTx>Cj2B zA#MYZfB_eBC8D2r--zaZN_Dc2*V%SeEnGue~k-gL8ef)?*mNc&Hm~lE@t`#p(Qalh|=NGQF{!$E)!If_m9v&wL5(WHLDx zo-(JzwWaQEOvW?!+B6d0j2Y_#`3dYJKd!!U7vos$?$+zBFHQ~~{80pkK|(=2EGjN;x}hZD zIGptBYwlhW$q&p*#jBgu9bWBf4ymR0YZ)6P{wBa;8r(-b=e-foS?U`EHVL%0BCGhi zE2D^>N%XR9QJ>KTwG3k>4wH&U}vkb%| z{q+(OkUPMbyo`qWd;IM48Rf%zO5!rSk$VP1w<7sld@FW$;c=n-tg)-f}AP$O0J|Cj?%8!~{amOP}z?g9G(2dsvD%JSpDL z5e1$@9vdXzV}K@&>=+x=HL~$a5&+rDfM$}w(gEq=d3fna%&(zNG=eFT=p)kwm7B9k zgbpRLyduLHqZ1xD*5V8pm{2}Q~W|>+rPq+1~{mmcJ z#U$eUrNg-6_sx^y8yvJ8X#C~qV9ZT-FHck5mcOJt{~OHg@GYhk<$=wjnuG4FOM;xE z6Rh46(Ej;-(?BZ`rMNRFBCj2F-F4=XS9OTutyfhu8Lxtj-x-Q{O?YVT@KcRO_0Ce> z)J`FZO5JX{EMlGv7OCHpmPdF}qsL}z49Wll#&#w=(w;uIS#iJW!{`|SpacA6kyT3T z0Xj0LK2P&!;2>aw`&fj}+Bu_>cU5QU^`#g~!T{m+=bPMJAm}R59`Pm%%96Gb0Xqb2 zyjdnbJxsl>E?F`kNTTgF-JM=n*V#1uUU;>l+;R(Um-^n zqx0S!Y)ha$`}aieLi_fU06?SToEc~|x%acLTJ0(K?pA8-XC*J~_cNL$+4neqjNOV3 zf1Lwakxd2bSl`r}t7p3nQ{Uh8Ya~8RDEL1Xrt0!27!Q&m;Vqu{m8u(TAB8KSmW{dE zLmDK0Zb4(l^F}4DdSj;q{Ogi)brhwaM?b8<(HyYUnz#U(im%8sU+F0G?u~X%_>gbxTOPTYx^z09tni&HzxEk#}hbO(}!+v{3dLR z0n-5{17JRw=A8FC;fe2dGJSVWJP1Xxsi$Rnh{I`tnUECDPv>0bK_VI25b zUa@~fyjNzDN}rL+10k`7KE=?#;lcW^XG^|)L*A9f()^f-&0fk%feFjVO9`*!mt=;S zoht-iaBHUUv+XCmS@nz-qq;=?v{>V^qG!S|<_#4B%=OP&TdLbyihNXYHl6ZyQ^M}Q zwAab=W}Ka-moO}MNxCs^CfiakPq+3iX#E87`F0;gSJuXTSf-z)uoN~xvll|X|6r4R zBLN7W{+Hw+IZuXqWJ}_WX;5_3<(+Quo!t9H-}?eZ(CeM)JH@QW+yCu?e+t~btqEIt zeRF=p=(~YBeW7Wh*vlRGg@OK8rL#X^f1iMKRr_-mwWQ4658cV{h#}CNUqfN};z1?3 z7cW6F7eNtoLL^bg(ui_QaX-l~go43OvGxR$ z&&j8#dIdnhy(FLc?g8n|rd@mKSvpKWc6`Xh)9(mqa)-vd_KBASCe5*JIi{_>h8e4C z6W89j4A{mBJQ!x+XkQXQ)mr)n>xcc9r85fIacvb`%1Q?D=;U}?h%z^G4$KI7euT2e zY+y9<5WYeF!y}87BSn{ku|&@-4N3b5I~?1K6YYCR^C{;;jKx+T_%u(zLC!G&1?R2ip=qHTgT| zLoMQEj~2M)pjK5e^=P5=0GHjq<#B~hJNx>*7o5TPl!eqQ`1?MRVA9mTC=aQm=+3Ih z{p<P|hx(+y;~NXH3;Sb#1mOVYIa-)Sg@#{Od;Cs(3hS zc{v?WIz0Pk|0teBoCZ_F(mVH4?L2q(4nYlvHl_gy&@oIHx}@^x9~#2R zLq{UTKr$MIkzOCAmp1xr1HI%dbTmAD@ORh)F34gC{VeO%0g{`ms5)kG%=UQvS$|CI zcf)1@6E*jrEz<lb2-(Me0rioOK=K8-VYh zv;Sc4_l6CuJ0`DAyzzXQnnmr`eZ5D#KMv9TI~2JKXVM48-w~g*xi(_|vEO^pk_2Z< zMTrOl7aoRdi@sQ~ubTAUewbxaE>YD<4qqVS_PZ4Z7QqZNR1Jq8)ixApuJCyL4@=p7 zxb>s~&ujr2U+)LS^70}N(UKp*F4j$Q)1w}s`2Q_D^;L^6Xt15TgLc-afg&-eLs1Km zup^g#7eNbR#JCKU&j&cIT_U{MXcjmew1b(*3#nn}$m5k(GzQ26sNaHeihPvKeOr=S zk($X)#5CffG;!JdwxK9g-jP5DS@5a+;5TQj%1%FfA@N413+0`zdIs-^48f5OduXzeE87lP|>{nLl?R!C~^ z*p#1^)rN$_6t8!!RU&qB_ie}4{*&p9)V34t>o&R?(6;aqF{S}_eU(a5equuT50aB; z7$&Rp-XA^Z&iXgI4t8X49XT-z<(6<-z!tSjok2dGjqXiVt=-bw7PW=7LB$I^;A)WG z^GnF{7vxs5Q_L=dRMpbc+TDUzZIcHiJrAej@aoA4HI@^W6tR8B+zb{0OrYJH{`=BR zp{Ty*#KK)B9yh;MAILsZc&4yD&z}iIGd07B-rb;|y^LPDgM+CFODzPRYti2)r(;`L zfMrLd9H9jCz63~y;!@8cO2e*3>)n#>(!rc7-xF!x6V_bYpLtyKvE1$IguK*cWiFL-J4!vecSHxAAz z^E?341!-v^(p~f}{sNmkLCalUN`EU>7FI`fw+at@t7jVA?gKz?a!*Vo^6(bAX}PYr z@4-pk+Y<)V3GoPezdp%d7ry)-qROXN)<1k7cc0TtAuSXys_(ZCLANL1_luzVl~WhN z+_;7>(Rhjt|1>K@GO0c=SCf<#DJAY73#4P~ElNv*S}9@fAalf%VL|sRBsTyK)Z$!O zfqXXX%_Cshf2(VkkGD}{Wk@Km+^BF7wwS7@*b(sh4gK93j8(P)B3%vWtK_Ll1vZvr zuH5y8i)wf^VRL5&qW_?WZ(yfkMN=1a}y>dUvj( zZua6*!f-l_WSccv7%E0;_>{5lL)JI|`Y8 zj>I1W@kCneekRK%PC7ascxSi7Ef`J{{-2=J95nb-O%uhRYeQv3Df(5Q zfK>rH5OJ$13PziIC37TqI;HEvGHPPTg8k`v^TD9bmJ9Uw0 zz&0=s`N0JgJw(mh=?p%vnHf;REuwEL2KtpKWmw zKq?O}Ui+fqAZ`cxVz+l!Zi@D@)Qf8H6JAznvXr>cEeWEh$2MB^ISCqB< zwg3xi|0E(x#A8|7iEa6OCbjpZkI$VCr_{ag=L_!4bKkh3@E4hWYw1pCGJt(#yt2*Ef84>uhm`J**kU>AS+B- z@5r~@7}Racn~Kl3v>ZmP41ZiX>Sefd9@{4Wfl#OsS~;G8$EjC&S0H8=`bS=+F2KF^INX(d=Dy#U=NdP+SV@?Uq>vACs=MKQsn z4k5#r@_Dm=Dvi-dMhn3>Rj&%o4i2ZE#J1_hE(Q`yw98qa zZntqUWw%{vfT^fj{&$ zvEIH?m*WN>nC_f3|BB0e71k*( zT|vMer7|aGg5vZvR$=C(3W-CKH803j8RB-L^t6>Ui>Cp6yhuqXIG6>Me`M4-d($$} zm#wR`JNgu5JX&mN{m?NT_I{9?iFZSK>D^vA$!dB;tWM?{^xNKXOg*1)!HfW+S)w#C z*+Lmc3h5Zs_Pc8a5AthXl6+N-!UMlAqg%ER&D9Hx>CYlN-Z(#T*yf)ZP$|N7i z;0#z_N2m}b$=}__DY&0-&pUt7dw%uLf`z?+8w?dLSi$=2b7d#i6k@7RU=iH<(BaYi zBGA#mNvYzN&lG!Gu@ln&6N=C+1@LbFUPwI^_lF|e=WN{KvRO*b5S-FxQPK{nFX?pO zl@b?l8zDEES&zma6jTke-)}wV^I_6ZqpEJOnn!L9%+c_k{^FLvN*XLk{ZxeqYPNkp z078hPKr_}wngp87{weB}}E=WFL?!d5b;CZ|Ub(%|v z2=j7Q78$dT9c-G4Vu$$tSKq)HkTUxwdeZA}HqA7wp~;)6yGj%M{bcrHS%y||{JpY2 zBbEU!Sp_%0t}F6U`d_F8OKbC~faoTAsSXgFpJU%0C^bKnasOMZ3%*}?zW~4F2m8hL zd$Y8;{r9;(`BcZWV+ZL0KR=5-)xBK>-=w@B`oB+5C`{^pX_;Fj(L#kfl!{`~WI0n( ze?3M18s!kb)pVW%D7j1p&*FOSB8J#1WQ~rfWXXTCRk-pnyWG6;_|-QA6S)&2Va<>; z10}OCKucrFEJDgSf8@Vw6Q_LK2VkN^A~LibL9<9KR?j zgKXb95~q)7YXY!tQiV`6fiADHotH<hn}-6;NEDz-J}5H-B<-4vLL_O zYgQIll6qoQ6X<80gvf<(8E(ZC9_u`YVuJHS`@K{4LtT5X#Yn9YS)qM+Z!MCgu<>lm z2%ws+s*JT2y(ijsWA3s#3wrwULR{h@KXES`$>j&QTRD8s_JAUbs*4i9Y?`OPIYoPG>dqM%ex0D8tPfk2 z?EOFeI}5G8+Bbn*WA@=%t>^W-)IMk9&5oCs@aMYT3)_x;I;#)zkH4hsO412hBp&Y^ zz;i@uf#!s=9)XdyBy;)xqzQ8C!R=#L9>dEiZ|umFl*_hW0_;*)6ZXy7XcIf1WVpcf z=y(DjqbV|e%pPAb^OXjGnfA=Yi~IBS6R}(<00<;8CgM-dJQVqoCcM6Fgj@&Wzr`Gd zV~O+%Llv!T^Ybs@@;~-7yi(2q1^kx)0bCu_xLeU__aeHr&4KH0hMl6>;drmMn-^)m ztdHL4!14Eh*QOww+F1*<&&>?Z!5TsmE*CgSKTGp1>*eC`WF{>sQ%K+Jv(fIM-?3EW z=CR&S&2$(k*zR2HkawE8vr=0C;8pxce%83I!fDKQu!F+o+@Dm{Mx>v}Lb_+8$c`93 zewb*^ff(90mzT3K7K`Xl=43T4hyCyaa4R{=r%^N%yBVEPI#1>^6@mfyC?_)eJ@#6T z3FEAw3hb@PDOdHKf=7Gx8xt$RK094&^c}BL0;IZ@V1*@Rx=Hm2rR@Ug@^RdTU5<(< zi?qg1a0X*{24c1~E~y@ZMkR}Ig^<9l!I4NYhV?pEcp~VrLDW->(;%X^|IuY~qXJM# zJ0x_;|K*)WlKg=tqJQ3yL<>*OsKO56Mmx=FT3(+2L8P-#4(xgOWK!I9FU(f_D+mKd zS-JlX{u?h=!%s-+tu66iS*8_*UxAI=U;pu&Hi4#r+#Gs#8=aCgM|CBpBtq>5BT0C#EMm)Z;;XpJz|N_%2I($ z2eWSooBK6b+~$B$h`Vp}jLtsI+aa;fU~f*FXK!!7#Iq^vIj#1;LBWW44Bg$w2vhLX z&QbBjMA`B=4qP;q$G;Gq&)22*Hif^7ci0+1e|is|KEIk0zSH>{_(}zRHOU}hsPle& zid%}?S9nSeRz}^PIMy#9fh%Q|DbHKTUFx9pPCpTsAC-%UYbd&nn}^X_Cry~H!-sL} z)}@@L(XNZ)1-~oUGGUq7gJ~k2fx8^vE z^K4d%?aH~<^*m3n`9sFZmt9z*CxH#0j)6z{1}B+T*Jsz%LoaQsCzK%0_cE;eUAFN;0;Hsw-Dn`j#rwVKOIP39lvwb?Iey56j?>=% ze)tNz?WBA8oO>U4pafvC#|Z+{*K-OnVe%_zgz8+sc0PxkR9E@;QMy9TkmpfLJHB